python-ase-3.9.1.4567/0000775000175000017500000000000012553427753014502 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/COPYING0000664000175000017500000004325412553425526015541 0ustar jensjjensj00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. python-ase-3.9.1.4567/PKG-INFO0000664000175000017500000000153312553427753015601 0ustar jensjjensj00000000000000Metadata-Version: 1.1 Name: python-ase Version: 3.9.1.4567 Summary: Atomic Simulation Environment Home-page: https://wiki.fysik.dtu.dk/ase Author: ASE-community Author-email: ase-developers@listserv.fysik.dtu.dk License: LGPLv2.1+ Description: ASE is a python package providing an open source Atomic Simulation Environment in the Python language. Platform: linux Classifier: Development Status :: 6 - Mature Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Topic :: Scientific/Engineering :: Physics python-ase-3.9.1.4567/README.txt0000664000175000017500000000011112553425527016166 0ustar jensjjensj00000000000000========== Python ASE ========== Webpage: http://wiki.fysik.dtu.dk/ase python-ase-3.9.1.4567/ase/0000775000175000017500000000000012553427753015252 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/utils/0000775000175000017500000000000012553427753016412 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/utils/voids.py0000664000175000017500000000642012553425527020107 0ustar jensjjensj00000000000000from __future__ import print_function import numpy as np from ase import Atom, Atoms from ase.calculators.calculator import Calculator from ase.optimize import FIRE, BFGS from ase.data import atomic_numbers from ase.data.vdw import vdw_radii class RepulsivePotential(Calculator): """Purely repulsive potential (Gaussian)""" implemented_properties = ['energy', 'forces'] def calculate(self, atoms, properties, changes): radii_a = np.array([ vdw_radii[atomic_numbers[a.symbol]] for a in atoms]) self.radii_a = radii_a # last atom is the moving one energy = 0.0 forces = np.zeros((len(atoms), 3)) for a in range(len(atoms) - 1): d_c = atoms.get_distance(a, -1, mic=True, vector=True) d = np.linalg.norm(d_c) sigma2 = radii_a[a]**2 / (2 * np.log(2)) pre = np.exp(- d**2 / (2 * sigma2)) energy += pre forces[-1] += pre * d_c / sigma2 self.results['energy'] = energy self.results['forces'] = forces def voids(atoms_in): """Find location and size of voids in a given structure. Returns the voids as 'X' atoms. The atoms' charge is misused to contain the voids' radius. """ trials = 6 # XXX do not hardwire atoms = atoms_in.copy() # append moving atom atoms.append(Atom('X')) atoms.set_calculator(RepulsivePotential()) voids_a = Atoms() voids_a.set_cell(atoms.get_cell()) voids_a.set_pbc(atoms.get_pbc()) positions = atoms.get_positions() for pos in positions[:-1]: for c in range(trials): positions[-1] = pos + 0.1 * np.random.uniform(-1, 1, size=3) atoms.set_positions(positions) # XXX do not hardwire relax = FIRE(atoms, logfile=None ) # XXX do not hardwire relax.run(fmax=0.001, steps=100) # get minimal distance Rmin = 100000 for b in range(len(atoms) - 1): R = atoms.get_distance(b, -1, mic=True) if R < Rmin: Rmin = R # check if new or better voids_a.append(Atom('X', atoms.get_positions()[-1], charge=Rmin)) voids_a.set_positions(voids_a.get_positions(wrap=True)) remove = [] last = len(voids_a) - 1 for ia, a in enumerate(voids_a[:-1]): d = voids_a.get_distance(ia, -1, mic=True) if d < a.charge or d < Rmin: if a.charge > Rmin: remove.append(last) else: remove.append(ia) remove.sort() if last not in remove: p = voids_a.get_positions()[-1] print('found new void at [%g,%g,%g], R=%g' % (p[0], p[1], p[2], Rmin)) for a in remove[::-1]: if a != last: p = voids_a.get_positions()[a] print('removing void at [%g,%g,%g], R=%g' % (p[0], p[1], p[2], voids_a[a].charge)) voids_a.pop(a) return voids_a python-ase-3.9.1.4567/ase/utils/eos.py0000664000175000017500000000350712553425527017554 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- import numpy as np from ase.utils.sjeos import EquationOfStateSJEOS try: # ase.utils.eosase2 requires scipy import scipy from ase.utils.eosase2 import EquationOfStateASE2 class EquationOfState: """Fit equation of state for bulk systems. The following equation is used:: sjeos (default) A third order inverse polynomial fit 10.1103/PhysRevB.67.026103 2 3 -1/3 E(V) = c + c t + c t + c t , t = V 0 1 2 3 taylor A third order Taylor series expansion about the minimum volume murnaghan PRB 28, 5480 (1983) birch Intermetallic compounds: Principles and Practice, Vol I: Principles. pages 195-210 birchmurnaghan PRB 70, 224107 pouriertarantola PRB 70, 224107 vinet PRB 70, 224107 antonschmidt Intermetallics 11, 23-32 (2003) p3 A third order polynomial fit Use:: eos = EquationOfState(volumes, energies, eos='sjeos') v0, e0, B = eos.fit() eos.plot() """ def __init__(self, volumes, energies, eos='sjeos'): if eos == 'sjeos': eosclass = EquationOfStateSJEOS else: eosclass = EquationOfStateASE2 # old ASE2 implementation self._impl = eosclass(volumes, energies, eos) def fit(self): return self._impl.fit() def plot(self, filename=None, show=None): return self._impl.plot(filename, show) except ImportError: # ase.utils.sjeos requires only numpy EquationOfState = EquationOfStateSJEOS python-ase-3.9.1.4567/ase/utils/__init__.py0000664000175000017500000001617012553425527020525 0ustar jensjjensj00000000000000import os import sys import time from math import sin, cos, radians, atan2, degrees from contextlib import contextmanager import numpy as np from ase.data import chemical_symbols # Python 2+3 compatibility stuff: if sys.version_info[0] == 3: import builtins exec_ = getattr(builtins, 'exec') basestring = str else: def exec_(code, dct): exec('exec code in dct') basestring = basestring @contextmanager def seterr(**kwargs): """Set how floating-point errors are handled. See np.seterr() for more details. """ old = np.seterr(**kwargs) yield np.seterr(**old) def plural(n, word): if n == 1: return '1 ' + word return '%d %ss' % (n, word) 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 def isatty(self): return False devnull = DevNull() # Only Windows has O_BINARY: CEW_FLAGS = os.O_CREAT | os.O_EXCL | os.O_WRONLY | getattr(os, 'O_BINARY', 0) def opencew(filename, world=None): """Create and open filename exclusively for writing. If master cpu gets exclusive write access to filename, a file descriptor is returned (a dummy file descriptor is returned on the slaves). If the master cpu does not get write access, None is returned on all processors.""" if world is None: from ase.parallel import world if world.rank == 0: try: fd = os.open(filename, CEW_FLAGS) except OSError: ok = 0 else: ok = 1 fd = os.fdopen(fd, 'wb') else: ok = 0 fd = devnull # Syncronize: if world.sum(ok) == 0: return None else: return fd class Lock: def __init__(self, name='lock', world=None): self.name = name if world is None: from ase.parallel import world self.world = world def acquire(self): while True: fd = opencew(self.name, self.world) if fd is not None: break time.sleep(1.0) def release(self): self.world.barrier() if self.world.rank == 0: os.remove(self.name) def __enter__(self): self.acquire() def __exit__(self, type, value, tb): self.release() class OpenLock: def acquire(self): pass def release(self): pass def __enter__(self): pass def __exit__(self, type, value, tb): pass def hill(numbers): """Convert list of atomic numbers to a chemical formula as a string. Elements are alphabetically ordered with C and H first.""" if isinstance(numbers, dict): count = dict(numbers) else: count = {} for Z in numbers: symb = chemical_symbols[Z] count[symb] = count.get(symb, 0) + 1 result = [(s, count.pop(s)) for s in 'CH' if s in count] result += [(s, count[s]) for s in sorted(count)] return ''.join('{0}{1}'.format(symbol, n) if n > 1 else symbol for symbol, n in result) def prnt(*args, **kwargs): """Python 3 style print function.""" fd = kwargs.pop('file', sys.stdout) fd.write( kwargs.pop('sep', ' ').join(str(arg) for arg in args) + kwargs.pop('end', '\n')) if kwargs.pop('flush', False): fd.flush() 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 = np.sign 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) ON_POSIX = 'posix' in sys.builtin_module_names try: from subprocess import Popen except ImportError: from os import popen3 else: def popen3(cmd): from subprocess import PIPE p = Popen(cmd, shell=True, close_fds=ON_POSIX, stdin=PIPE, stdout=PIPE, stderr=PIPE) return p.stdin, p.stdout, p.stderr python-ase-3.9.1.4567/ase/utils/adsorb.py0000664000175000017500000001455312553425527020243 0ustar jensjjensj00000000000000from __future__ import print_function # 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, bcc100, diamond111, \ add_adsorbate from ase.structure import estimate_lattice_constant, molecule 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 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' if face == '110': slab = bcc110(surf, (n, m, opt.layers), a, opt.vacuum) elif face == '100': slab = bcc100(surf, (n, m, opt.layers), a, opt.vacuum) script[0] += 'bcc' + face script += ['slab = bcc%s(%r, (%d, %d, %d), a, vac)' % (face, 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.structure 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.9.1.4567/ase/utils/sjeos.py0000664000175000017500000000716612553425527020116 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- try: import numpy as np except ImportError: # required due to ase/test/eoswoase.py pass class EquationOfStateSJEOS: """Fit equation of state for bulk systems. 10.1103/PhysRevB.67.026103 The following equation is used:: A third order inverse polynomial fit 2 3 -1/3 E(V) = c + c t + c t + c t , t = V 0 1 2 3 More methods available in ase.utils.eosase2 Use:: eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() eos.plot() """ def __init__(self, volumes, energies, eos='sjeos'): assert eos == 'sjeos', eos + ' eos not available. Probably scipy missing.' self.v = np.array(volumes) self.e = np.array(energies) self.eos_string = 'sjeos' 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 isinstance(t, float) and 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) y = self.fit0(x**-(1.0 / 3)) plt.plot(x, y, '-r') try: from ase.units import kJ plt.xlabel(u'volume [Å^3]') plt.ylabel(u'energy [eV]') plt.title(u'%s: E: %.3f eV, V: %.3f Å^3, B: %.3f GPa' % (self.eos_string, self.e0, self.v0, self.B / kJ * 1.e24)) except ImportError: plt.xlabel(u'volume [L(length)^3]') plt.ylabel(u'energy [E(energy)]') plt.title(u'%s: E: %.3f E, V: %.3f L^3, B: %.3e E/L^3' % (self.eos_string, self.e0, self.v0, self.B)) if show: plt.show() if filename is not None: f.savefig(filename) return f if __name__ == '__main__': try: import numpy as np # from ase/test/eos.py volumes = [29.205536, 30.581492, 32.000000, 33.461708, 34.967264] energies = [0.0190898, -0.0031172, -0.0096925, -0.0004014, 0.0235753] sjeos = (31.867118229937798, -0.0096410046694188622, 0.23984474782755572) eos = EquationOfStateSJEOS(volumes, energies) v0, e0, B = eos.fit() assert abs(v0 - sjeos[0]) < 5.e-6 assert abs(B - sjeos[2]) < 5.e-6 except ImportError: pass python-ase-3.9.1.4567/ase/utils/eosase2.py0000664000175000017500000002047712553425527020334 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- from __future__ import print_function import numpy as np from ase.test import NotAvailable try: import scipy except ImportError: raise NotAvailable('This needs scipy module.') try: from scipy.optimize import curve_fit except ImportError: from scipy.optimize import leastsq # this part comes from # http://projects.scipy.org/scipy/browser/trunk/scipy/optimize/minpack.py def _general_function(params, xdata, ydata, function): return function(xdata, *params) - ydata # end of this part def curve_fit(f, x, y, p0): func = _general_function args = (x, y, f) # this part comes from # http://projects.scipy.org/scipy/browser/trunk/scipy/optimize/minpack.py popt, pcov, infodict, mesg, ier = leastsq(func, p0, args=args, full_output=1) if ier not in [1,2,3,4]: raise RuntimeError("Optimal parameters not found: " + mesg) # end of this part return popt, pcov def taylor(V, E0, beta, alpha, V0): 'Taylor Expansion up to 3rd order about V0' E = E0 + beta/2.*(V-V0)**2/V0 + alpha/6.*(V-V0)**3/V0 return E def murnaghan(V, E0, B0, BP, V0): 'From PRB 28,5480 (1983' E = E0 + B0*V/BP*(((V0/V)**BP)/(BP-1)+1) - V0*B0/(BP-1) return E def birch(V, E0, B0, BP, V0): ''' From Intermetallic compounds: Principles and Practice, Vol. I: Principles Chapter 9 pages 195-210 by M. Mehl. B. Klein, D. Papaconstantopoulos paper downloaded from Web case where n=0 ''' E = (E0 + 9.0/8.0*B0*V0*((V0/V)**(2.0/3.0) - 1.0)**2 + 9.0/16.0*B0*V0*(BP-4.)*((V0/V)**(2.0/3.0) - 1.0)**3) return E def birchmurnaghan(V, E0, B0, BP, V0): 'BirchMurnaghan equation from PRB 70, 224107' eta = (V/V0)**(1./3.) E = E0 + 9.*B0*V0/16.*(eta**2-1)**2*(6 + BP*(eta**2-1.) - 4.*eta**2) return E def pouriertarantola(V, E0, B0, BP, V0): 'Pourier-Tarantola equation from PRB 70, 224107' eta = (V/V0)**(1./3.) squiggle = -3.*np.log(eta) E = E0 + B0*V0*squiggle**2/6.*(3. + squiggle*(BP - 2)) return E def vinet(V, E0, B0, BP, V0): 'Vinet equation from PRB 70, 224107' eta = (V/V0)**(1./3.) E = (E0 + 2.*B0*V0/(BP-1.)**2 * (2. - (5. +3.*BP*(eta-1.)-3.*eta)*np.exp(-3.*(BP-1.)*(eta-1.)/2.))) return E def antonschmidt(V, Einf, B, n, V0): '''From Intermetallics 11, 23-32 (2003) Einf should be E_infinity, i.e. infinite separation, but according to the paper it does not provide a good estimate of the cohesive energy. They derive this equation from an empirical formula for the volume dependence of pressure, E(vol) = E_inf + int(P dV) from V=vol to V=infinity but the equation breaks down at large volumes, so E_inf is not that meaningful n should be about -2 according to the paper. I find this equation does not fit volumetric data as well as the other equtions do. ''' E = B*V0/(n+1.) * (V/V0)**(n+1.)*(np.log(V/V0)-(1./(n+1.))) + Einf return E def p3(V, c0, c1, c2, c3): 'polynomial fit' E = c0 + c1*V + c2*V**2 + c3*V**3 return E def parabola(x, a, b, c): ''' parabola polynomial function this function is used to fit the data to get good guesses for the equation of state fits a 4th order polynomial fit to get good guesses for was not a good idea because for noisy data the fit is too wiggly 2nd order seems to be sufficient, and guarentees a single minimum''' return a + b*x + c*x**2 class EquationOfStateASE2: """Fit equation of state for bulk systems. The following equation is used:: taylor A third order Taylor series expansion about the minimum volume murnaghan PRB 28, 5480 (1983) birch Intermetallic compounds: Principles and Practice, Vol I: Principles. pages 195-210 birchmurnaghan PRB 70, 224107 pouriertarantola PRB 70, 224107 vinet PRB 70, 224107 antonschmidt Intermetallics 11, 23-32 (2003) p3 A third order polynomial fit Use:: eos = EquationOfState(volumes, energies, eos='murnaghan') v0, e0, B = eos.fit() eos.plot() """ def __init__(self, volumes, energies, eos='murnaghan'): self.v = np.array(volumes) self.e = np.array(energies) self.eos_string = eos 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') """ # old ASE2 implementation p0 = [min(self.e), 1, 1] popt, pcov = curve_fit(parabola, self.v, self.e, p0) parabola_parameters = popt ## Here I just make sure the minimum is bracketed by the volumes ## this if for the solver minvol = min(self.v) maxvol = max(self.v) # the minimum of the parabola is at dE/dV = 0, or 2*c V +b =0 c = parabola_parameters[2] b = parabola_parameters[1] a = parabola_parameters[0] parabola_vmin = -b/2/c if not (minvol < parabola_vmin and parabola_vmin < maxvol): print('Warning the minimum volume of a fitted parabola is not in your volumes. You may not have a minimum in your dataset') # evaluate the parabola at the minimum to estimate the groundstate energy E0 = parabola(parabola_vmin, a, b, c) # estimate the bulk modulus from Vo*E''. E'' = 2*c B0 = 2*c*parabola_vmin if self.eos_string == 'antonschmidt': BP = -2 else: BP = 4 initial_guess = [E0, B0, BP, parabola_vmin] # now fit the equation of state p0 = initial_guess popt, pcov = curve_fit(eval(self.eos_string), self.v, self.e, p0) self.eos_parameters = popt if self.eos_string == 'p3': c0, c1, c2, c3 = self.eos_parameters # find minimum E in E = c0 + c1*V + c2*V**2 + c3*V**3 # dE/dV = c1+ 2*c2*V + 3*c3*V**2 = 0 # solve by quadratic formula with the positive root a = 3 * c3 b = 2 * c2 c = c1 self.v0 = (-b + np.sqrt(b**2 - 4*a*c))/(2*a) self.e0 = p3(self.v0, c0, c1, c2, c3) self.B = (2*c2 + 6*c3*self.v0)*self.v0 else: self.v0 = self.eos_parameters[3] self.e0 = self.eos_parameters[0] self.B = self.eos_parameters[1] 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) y = eval(self.eos_string)(x, self.eos_parameters[0], self.eos_parameters[1], self.eos_parameters[2], self.eos_parameters[3], ) plt.plot(x, y, '-r') try: from ase.units import kJ plt.xlabel(u'volume [Å^3]') plt.ylabel(u'energy [eV]') plt.title(u'%s: E: %.3f eV, V: %.3f Å^3, B: %.3f GPa' % (self.eos_string, self.e0, self.v0, self.B / kJ * 1.e24)) except ImportError: plt.xlabel(u'volume [L(length)^3]') plt.ylabel(u'energy [E(energy)]') plt.title(u'%s: E: %.3f E, V: %.3f L^3, B: %.3e E/L^3' % (self.eos_string, self.e0, self.v0, self.B)) if show: plt.show() if filename is not None: f.savefig(filename) return f python-ase-3.9.1.4567/ase/utils/build_web_page.py0000664000175000017500000000670012553425527021714 0ustar jensjjensj00000000000000from __future__ import print_function import glob import optparse import os import shutil import subprocess import sys def svn_update(name='ase'): os.chdir(name) output = subprocess.check_output('svn update', shell=True) os.chdir('..') lastline = output.splitlines()[-1] return not lastline.startswith('At revision') def build(force_build, name='ase', env=''): if not force_build: return home = os.getcwd() os.chdir(name) # Clean up: shutil.rmtree('doc') subprocess.check_call('svn update', shell=True) # Create development snapshot tar-file and install: try: shutil.rmtree('dist') except OSError: pass subprocess.check_call('python setup.py sdist install --home=..', shell=True) # Build web-page: os.chdir('doc') os.makedirs('build/html') # Sphinx-1.1.3 needs this (1.2.2 is OK) subprocess.check_call(env + ' PYTHONPATH=' '{0}/lib/python:{0}/lib64/python:$PYTHONPATH ' 'PATH={0}/bin:$PATH '.format(home) + 'make html', shell=True) # Use https for mathjax: subprocess.check_call( 'find build -name "*.html" | ' 'xargs sed -i "s|http://cdn.mathjax.org|https://cdn.mathjax.org|"', shell=True) tar = glob.glob('../dist/*.tar.gz')[0].split('/')[-1] os.rename('../dist/' + tar, 'build/html/' + tar) # Set correct version of snapshot tar-file: subprocess.check_call( 'find build/html -name download.html | ' 'xargs sed -i s/snapshot.tar.gz/{}/g'.format(tar), shell=True) os.chdir('..') output = subprocess.check_output( 'epydoc --docformat restructuredtext --parse-only ' '--name {0} --url http://wiki.fysik.dtu.dk/{1} ' '--show-imports --no-frames -v {1}'.format(name.upper(), name), shell=True) # Check for warnings: for line in output.splitlines(): if line.startswith('|'): print(line) os.rename('html', 'doc/build/html/epydoc') os.chdir('doc/build') dir = name + '-web-page' os.rename('html', dir) subprocess.check_call('tar -czf {0}.tar.gz {0}'.format(dir), shell=True) os.rename('{}.tar.gz'.format(dir), '../../../{}.tar.gz'.format(dir)) os.chdir('../../..') try: shutil.rmtree('lib64') except OSError: pass shutil.rmtree('lib') shutil.rmtree('bin') shutil.rmtree('share') def main(build=build): """Build web-page if there are changes in the source. The optional build function is used by GPAW to build its web-page. """ if os.path.isfile('build-web-page.lock'): print('Locked', file=sys.stderr) return try: open('build-web-page.lock', 'w').close() parser = optparse.OptionParser(usage='Usage: %prog [-f]', description='Build web-page') parser.add_option('-f', '--force-build', action='store_true', help='Force build instead of building only when ' 'there are changes to the docs or code.') opts, args = parser.parse_args() assert len(args) == 0 changes = svn_update('ase') build(opts.force_build or changes) finally: os.remove('build-web-page.lock') if __name__ == '__main__': main() python-ase-3.9.1.4567/ase/utils/sphinx.py0000664000175000017500000001550012553425527020273 0ustar jensjjensj00000000000000from __future__ import print_function import os import traceback import warnings from os.path import join from stat import ST_MTIME from docutils import nodes from docutils.parsers.rst.roles import set_classes import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from ase.utils import exec_ def mol_role(role, rawtext, text, lineno, inliner, options={}, content=[]): n = [] t = '' while text: if text[0] == '_': n.append(nodes.Text(t)) t = '' n.append(nodes.subscript(text=text[1])) text = text[2:] else: t += text[0] text = text[1:] n.append(nodes.Text(t)) return n, [] def svn_role_tmpl(urlroot, role, rawtext, text, lineno, inliner, options={}, content=[]): if text[-1] == '>': i = text.index('<') name = text[:i - 1] text = text[i + 1:-1] else: name = text if name[0] == '~': name = name.split('/')[-1] text = text[1:] if '?' in name: name = name[:name.index('?')] ref = urlroot + text set_classes(options) node = nodes.reference(rawtext, name, refuri=ref, **options) return [node], [] def trac_role_tmpl(urlroot, role, rawtext, text, lineno, inliner, options={}, content=[]): if text[-1] == '>': i = text.index('<') name = text[:i - 1] text = text[i + 1:-1] else: name = text if name[0] == '~': name = name.split('/')[-1] text = text[1:] if '?' in name: name = name[:name.index('?')] ref = urlroot + text set_classes(options) node = nodes.reference(rawtext, name, refuri=ref, **options) return [node], [] def epydoc_role_tmpl(package_name, urlroot, role, rawtext, text, lineno, inliner, options={}, content=[]): name = None if text[-1] == '>': i = text.index('<') name = text[:i - 1] text = text[i + 1:-1] components = text.split('.') if components[0] != package_name: components.insert(0, package_name) if name is None: name = components[-1] try: module = None for n in range(2, len(components) + 1): module = __import__('.'.join(components[:n])) except ImportError: if module is None: print('epydoc: could not process: %s' % str(components)) raise for component in components[1:n]: module = getattr(module, component) ref = '.'.join(components[:n]) if isinstance(module, type): ref += '-class.html' else: ref += '-module.html' if n < len(components): ref += '#' + components[-1] else: ref = '.'.join(components) + '-module.html' ref = urlroot + ref set_classes(options) node = nodes.reference(rawtext, name, refuri=ref, **options) return [node], [] def creates(): """Generator for Python scripts and their output filenames.""" for dirpath, dirnames, filenames in os.walk('.'): for filename in filenames: if filename.endswith('.py'): path = join(dirpath, filename) lines = open(path).readlines() if len(lines) == 0: continue line = lines[0] if 'coding: utf-8' in line: line = lines[1] if line.startswith('# creates:'): yield dirpath, filename, [file.rstrip(',') for file in line.split()[2:]] if '.svn' in dirnames: dirnames.remove('.svn') if 'build' in dirnames: dirnames.remove('build') def create_png_files(): errcode = os.system('povray -h 2> /dev/null') if errcode: warnings.warn('No POVRAY!') # Replace write_pov with write_png: from ase.io import pov from ase.io.png import write_png def write_pov(filename, atoms, run_povray=False, **parameters): p = {} for key in ['rotation', 'show_unit_cell', 'radii', 'bbox', 'colors', 'scale']: if key in parameters: p[key] = parameters[key] write_png(filename[:-3] + 'png', atoms, **p) pov.write_pov = write_pov olddir = os.getcwd() for dir, pyname, outnames in creates(): path = join(dir, pyname) t0 = os.stat(path)[ST_MTIME] run = False for outname in outnames: try: t = os.stat(join(dir, outname))[ST_MTIME] except OSError: run = True break else: if t < t0: run = True break if run: print('running:', path) os.chdir(dir) plt.figure() try: exec_(compile(open(pyname).read(), pyname, 'exec'), {}) except KeyboardInterrupt: return except: traceback.print_exc() finally: os.chdir(olddir) plt.close() for outname in outnames: print(dir, outname) def clean(): """Remove all generated files.""" for dir, pyname, outnames in creates(): for outname in outnames: if os.path.isfile(os.path.join(dir, outname)): os.remove(os.path.join(dir, outname)) def visual_inspection(): """Manually inspect generated files.""" import subprocess images = [] text = [] pdf = [] for dir, pyname, outnames in creates(): for outname in outnames: path = os.path.join(dir, outname) ext = path.rsplit('.', 1)[1] if ext == 'pdf': pdf.append(path) elif ext in ['csv', 'txt', 'out']: text.append(path) else: images.append(path) subprocess.call(['eog'] + images) subprocess.call(['evince'] + pdf) subprocess.call(['more'] + text) if __name__ == '__main__': import argparse parser = argparse.ArgumentParser(description='Process generated files.') parser.add_argument('command', nargs='?', default='list', choices=['list', 'inspect', 'clean']) args = parser.parse_args() if args.command == 'clean': clean() elif args.command == 'list': for dir, pyname, outnames in creates(): for outname in outnames: print(os.path.join(dir, outname)) else: visual_inspection() python-ase-3.9.1.4567/ase/utils/deprecate.py0000664000175000017500000000260312553425527020716 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/utils/memory.py0000664000175000017500000004063212553425527020276 0ustar jensjjensj00000000000000from __future__ import print_function 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.items(): 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.items(): 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 isinstance(ndims, 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 isinstance(maxseed, int) and maxseed>=1 assert type(size) in [int,float] and size>=1 assert isinstance(ndims, 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.9.1.4567/ase/utils/timing.py0000664000175000017500000001147512553425527020260 0ustar jensjjensj00000000000000from __future__ import print_function # Copyright (C) 2003 CAMP # Please see the accompanying LICENSE file for further information. import sys import time import functools def function_timer(func, *args, **kwargs): out = kwargs.pop('timeout', sys.stdout) t1 = time.time() r = func(*args, **kwargs) t2 = time.time() print(t2 - t1, file=out) return r class Timer: """Timer object. Use like this:: timer = Timer() timer.start('description') # do something timer.stop() or:: with timer('description'): # do something To get a summary call:: timer.write() """ def __init__(self, print_levels=1000): self.timers = {} self.t0 = time.time() self.running = [] self.print_levels = print_levels def print_info(self, calc): """Override to get to write info during calculator's initialize().""" pass def start(self, name): names = tuple(self.running + [name]) self.timers[names] = self.timers.get(names, 0.0) - time.time() self.running.append(name) def stop(self, name=None): if name is None: name = self.running[-1] names = tuple(self.running) running = self.running.pop() if name != running: raise RuntimeError('Must stop timers by stack order. ' 'Requested stopping of %s but topmost is %s' % (name, running)) self.timers[names] += time.time() return names def __call__(self, name): """Context manager for timing a block of code. Example (t is a timer object):: with t('Add two numbers'): x = 2 + 2 # same as this: t.start(Add two numbers') x = 2 + 2 t.stop() """ self.start(name) return self def __enter__(self): pass def __exit__(self, *args): self.stop() def get_time(self, *names): return self.timers[names] def write(self, out=sys.stdout): were_running = list(self.running) while self.running: self.stop() if len(self.timers) == 0: return t0 = time.time() tot = t0 - self.t0 n = max([len(names[-1]) + len(names) for names in self.timers]) + 1 line = '=' * (n + 26) + '\n' out.write(line) out.write('%-*s incl. excl.\n' % (n, 'Timing:')) out.write(line) tother = tot inclusive = self.timers.copy() exclusive = self.timers.copy() keys = sorted(exclusive.keys()) for names in keys: t = exclusive[names] if len(names) > 1: if len(names) < self.print_levels + 1: exclusive[names[:-1]] -= t else: tother -= t exclusive[('Other',)] = tother inclusive[('Other',)] = tother keys.append(('Other',)) for names in keys: t = exclusive[names] tinclusive = inclusive[names] r = t / tot p = 100 * r i = int(40 * r + 0.5) if i == 0: bar = '|' else: bar = '|%s|' % ('-' * (i - 1)) level = len(names) if level > self.print_levels: continue name = (level - 1) * ' ' + names[-1] + ':' out.write('%-*s%9.3f %9.3f %5.1f%% %s\n' % (n, name, tinclusive, t, p, bar)) out.write(line) out.write('%-*s%9.3f %5.1f%%\n' % (n + 10, 'Total:', tot, 100.0)) out.write(line) out.write('date: %s\n' % time.asctime()) for name in were_running: self.start(name) def add(self, timer): for name, t in timer.timers.items(): self.timers[name] = self.timers.get(name, 0.0) + t class timer: """Decorator for timing a method call. Example:: from ase.utils.timing import timer, Timer class A: def __init__(self): self.timer = Timer() @timer('Add two numbers') def add(self, x, y): return x + y """ def __init__(self, name): self.name = name def __call__(self, method): @functools.wraps(method) def new_method(slf, *args, **kwargs): slf.timer.start(self.name) x = method(slf, *args, **kwargs) try: slf.timer.stop() except IndexError: pass return x return new_method python-ase-3.9.1.4567/ase/utils/linesearch.py0000664000175000017500000003365412553425527021111 0ustar jensjjensj00000000000000import numpy as np pymin = min pymax = 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 True: 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.9.1.4567/ase/utils/stylecheck.py0000664000175000017500000000632412553425551021121 0ustar jensjjensj00000000000000import argparse import os import smtplib import subprocess from email.mime.text import MIMEText def mail(to, subject, txt): msg = MIMEText(txt) msg['Subject'] = subject msg['From'] = 'pep8@fysik.dtu.dk' msg['To'] = to s = smtplib.SMTP('mail.fysik.dtu.dk') s.sendmail(msg['From'], [to], msg.as_string()) s.quit() p8 = 'pep8 --ignore W293,E129' def pep8(name): if not os.path.isfile(name): return [] try: output = subprocess.check_output(p8 + ' ' + name, shell=True) except subprocess.CalledProcessError as ex: output = ex.output lines = [] for line in output.decode().splitlines(): name, l, c, error = line.split(':', 3) if error.startswith(' E226'): ln = open(name).readlines()[int(l) - 1] c = int(c) - 1 if ln[c:c + 2] == '**': continue lines.append(line) return lines def pyflakes(name): try: output = subprocess.check_output('pyflakes ' + name, shell=True) except subprocess.CalledProcessError as ex: output = ex.output return [line for line in output.decode().splitlines() if 'list comprehension redefines' not in line] def check_file(name): for line in pep8(name): print(line) for line in pyflakes(name): print(line) def check_repository(to): output = subprocess.check_output('svn merge --dry-run -r BASE:HEAD .', shell=True) lines = output.decode().splitlines() names = [] for line in lines: st, name = line.split()[:2] if st in ['U', 'A'] and name.endswith('.py'): names.append(name) warnings = {} for name in names: w = pep8(name) warnings[name] = len(w) if names: subprocess.call('svn up > up.out', shell=True) n81 = 0 n82 = 0 nf = 0 txt = [] for name in names: w = pep8(name) n1 = warnings[name] n2 = len(w) if n2 > n1: n81 += n1 n82 += n2 txt.append('Number of PEP-8 errors increased from {} to {}:' .format(n1, n2)) for x in w: txt.append(x) txt.append('') q = pyflakes(name) if q: nf += len(q) txt.append('Warnings from PyFlakes:') txt += q txt.append('') if txt: subject = [] if n82 > n81: subject.append( 'PEP8 warnings increased from {} to {}'.format(n81, n82)) if nf: subject.append('PyFlakes warnings: {}'.format(nf)) txt = '\n'.join(txt) if to: mail(to, ' - '.join(subject), txt) else: print(txt) parser = argparse.ArgumentParser(description='Run both pep8 and pyflakes ' 'on file(s).') parser.add_argument('--check-repository', action='store_true') parser.add_argument('--mail') parser.add_argument('filenames', nargs='*', metavar='filename') args = parser.parse_args() if args.check_repository: check_repository(args.mail) else: for name in args.filenames: check_file(name) python-ase-3.9.1.4567/ase/utils/geometry.py0000664000175000017500000007472012553425527020626 0ustar jensjjensj00000000000000from __future__ import print_function # 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 wrap_positions(positions, cell, pbc=True, center=(0.5, 0.5, 0.5), eps=1e-7): """Wrap positions to unit cell. Returns positions changed by a multiple of the unit cell vectors to fit inside the space spanned by these vectors. See also the :meth:`ase.atoms.Atoms.wrap` method. Parameters: positions: float ndarray of shape (n, 3) Positions of the atoms cell: float ndarray of shape (3, 3) Unit cell vectors. pbc: one or 3 bool For each axis in the unit cell decides whether the positions will be moved along this axis. center: three float The positons in fractional coordinates that the new positions will be nearest possible to. eps: float Small number to prevent slightly negative coordinates from beeing wrapped. Example: >>> from ase.utils.geometry import wrap_positions >>> wrap_positions([[-0.1, 1.01, -0.5]], ... [[1, 0, 0], [0, 1, 0], [0, 0, 4]], ... pbc=[1, 1, 0]) array([[ 0.9 , 0.01, -0.5 ]]) """ if not hasattr(pbc, '__len__'): pbc = (pbc,) * 3 shift = np.asarray(center) - 0.5 + eps * np.asarray(pbc, dtype=bool) fractional = np.linalg.solve(np.asarray(cell).T, np.asarray(positions).T).T + shift for i, periodic in enumerate(pbc): if periodic: fractional[:, i] %= 1.0 fractional[:, i] -= shift[i] return np.dot(fractional, cell) 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, output_strained=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'. If *output_strained* is True, then the strained versions of *atoms1* and *atoms2* are returned in addition to the stacked structure. 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 output_strained: atoms1_strained = atoms1.copy() atoms2_strained = atoms2.copy() 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) if output_strained: return atoms1, atoms1_strained, atoms2_strained else: 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 = sorted([(tag, i) for i, tag in enumerate(tags)]) indices = [i for tag, i in deco] return atoms[indices] def rotation_matrix(a1, a2, b1, b2): """Returns a rotation matrix that rotates the vectors *a1* in the direction of *a2* and *b1* in the direction of *b2*. In the case that the angle between *a2* and *b2* is not the same as between *a1* and *b1*, a proper rotation matrix will anyway be constructed by first rotate *b2* in the *b1*, *b2* plane. """ a1 = np.asarray(a1, dtype=float) / np.norm(a1) b1 = np.asarray(b1, dtype=float) / np.norm(b1) c1 = np.cross(a1, b1) c1 /= np.norm(c1) # clean out rounding errors... a2 = np.asarray(a2, dtype=float) / np.norm(a2) b2 = np.asarray(b2, dtype=float) / np.norm(b2) c2 = np.cross(a2, b2) c2 /= np.norm(c2) # clean out rounding errors... # Calculate rotated *b2* theta = np.arccos(np.dot(a2, b2)) - np.arccos(np.dot(a1, b1)) b3 = np.sin(theta) * a2 + np.cos(theta) * b2 b3 /= np.norm(b3) # clean out rounding errors... A1 = np.array([a1, b1, c1]) A2 = np.array([a2, b3, c2]) R = np.linalg.solve(A1, A2).T return R def rotate(atoms, a1, a2, b1, b2, rotate_cell=True, center=(0, 0, 0)): """Rotate *atoms*, such that *a1* will be rotated in the direction of *a2* and *b1* in the direction of *b2*. The point at *center* is fixed. Use *center='COM'* to fix the center of mass. If *rotate_cell* is true, the cell will be rotated together with the atoms. Note that the 000-corner of the cell is by definition fixed at origo. Hence, setting *center* to something other than (0, 0, 0) will rotate the atoms out of the cell, even if *rotate_cell* is True. """ if isinstance(center, str) and center.lower() == 'com': center = atoms.get_center_of_mass() R = rotation_matrix(a1, a2, b1, b2) atoms.positions[:] = np.dot(atoms.positions - center, R.T) + center if rotate_cell: atoms.cell[:] = np.dot(atoms.cell, R.T) def minimize_tilt_ij(atoms, modified=1, fixed=0, fold_atoms=True): """Minimize the tilt angle for two given axes. The problem is underdetermined. Therefore one can choose one axis that is kept fixed. """ orgcell_cc = atoms.get_cell() pbc_c = atoms.get_pbc() i = fixed j = modified if not (pbc_c[i] and pbc_c[j]): raise RuntimeError('Axes have to be periodic') prod_cc = np.dot(orgcell_cc, orgcell_cc.T) cell_cc = 1. * orgcell_cc nji = np.floor(- prod_cc[i, j] / prod_cc[i, i] + 0.5) cell_cc[j] = orgcell_cc[j] + nji * cell_cc[i] # sanity check def volume(cell): return np.abs(np.dot(cell[2], np.cross(cell[0], cell[1]))) V = volume(cell_cc) assert(abs(volume(orgcell_cc) - V) / V < 1.e-10) atoms.set_cell(cell_cc) if fold_atoms: atoms.set_scaled_positions(atoms.get_scaled_positions()) def minimize_tilt(atoms, order=range(3), fold_atoms=True): """Minimize the tilt angles of the unit cell.""" pbc_c = atoms.get_pbc() for i1, c1 in enumerate(order): for c2 in order[i1 + 1:]: if pbc_c[c1] and pbc_c[c2]: minimize_tilt_ij(atoms, c1, c2, fold_atoms) def find_mic(D, cell, pbc=True): """Finds the minimum-image representation of vector(s) D""" # Calculate the 4 unique unit cell diagonal lengths diags = np.sqrt((np.dot([[1, 1, 1], [-1, 1, 1], [1, -1, 1], [-1, -1, 1], ], cell)**2).sum(1)) # calculate 'mic' vectors (D) and lengths (D_len) using simple method Dr = np.dot(D, np.linalg.inv(cell)) D = np.dot(Dr - np.round(Dr) * pbc, cell) D_len = np.sqrt((D**2).sum(1)) # return mic vectors and lengths for only orthorhombic cells, # as the results may be wrong for non-orthorhombic cells if (max(diags) - min(diags)) / max(diags) < 1e-9: return D, D_len # The cutoff radius is the longest direct distance between atoms # or half the longest lattice vector, whichever is smaller cutoff = min(max(D_len), max(diags) / 2.) # The number of neighboring images to search in each direction is # equal to the ceiling of the cutoff distance (defined above) divided # by the length of the projection of the lattice vector onto its # corresponding surface normal. a's surface normal vector is e.g. # b x c / (|b| |c|), so this projection is (a . (b x c)) / (|b| |c|). # The numerator is just the lattice volume, so this can be simplified # to V / (|b| |c|). This is rewritten as V |a| / (|a| |b| |c|) # for vectorization purposes. latt_len = np.sqrt((cell**2).sum(1)) V = abs(np.linalg.det(cell)) n = pbc * np.array(np.ceil(cutoff * np.prod(latt_len) / (V * latt_len)), dtype=int) # Construct a list of translation vectors. For example, if we are # searching only the nearest images (27 total), tvecs will be a # 27x3 array of translation vectors. This is the only nested loop # in the routine, and it takes a very small fraction of the total # execution time, so it is not worth optimizing further. tvecs = [] for i in range(-n[0], n[0] + 1): latt_a = i * cell[0] for j in range(-n[1], n[1] + 1): latt_ab = latt_a + j * cell[1] for k in range(-n[2], n[2] + 1): tvecs.append(latt_ab + k * cell[2]) tvecs = np.array(tvecs) # Translate the direct displacement vectors by each translation # vector, and calculate the corresponding lengths. D_trans = tvecs[np.newaxis] + D[:, np.newaxis] D_trans_len = np.sqrt((D_trans**2).sum(2)) # Find mic distances and corresponding vector(s) for each given pair # of atoms. For symmetrical systems, there may be more than one # translation vector corresponding to the MIC distance; this finds the # first one in D_trans_len. D_min_len = np.min(D_trans_len, axis=1) D_min_ind = D_trans_len.argmin(axis=1) D_min = D_trans[range(len(D_min_ind)), D_min_ind] return D_min, D_min_len def niggli_reduce(atoms): """Convert the supplied atoms object's unit cell into its maximally-reduced Niggli unit cell. Even if the unit cell is already maximally reduced, it will be converted into its unique Niggli unit cell. This will also wrap all atoms into the new unit cell. References: Niggli, P. "Krystallographische und strukturtheoretische Grundbegriffe. Handbuch der Experimentalphysik", 1928, Vol. 7, Part 1, 108-176. Krivy, I. and Gruber, B., "A Unified Algorithm for Determining the Reduced (Niggli) Cell", Acta Cryst. 1976, A32, 297-298. Grosse-Kunstleve, R.W.; Sauter, N. K.; and Adams, P. D. "Numerically stable algorithms for the computation of reduced unit cells", Acta Cryst. 2004, A60, 1-6. """ assert all(atoms.pbc), 'Can only reduce 3d periodic unit cells!' C = np.eye(3, dtype=int) class _gtensor(object): """The G tensor as defined in Grosse-Kunstleve.""" def __init__(self, atoms): self.atoms = atoms self.epsilon = 1e-5 * atoms.get_volume()**(1. / 3.) self.a = np.dot(atoms.cell[0], atoms.cell[0]) self.b = np.dot(atoms.cell[1], atoms.cell[1]) self.c = np.dot(atoms.cell[2], atoms.cell[2]) self.x = 2 * np.dot(atoms.cell[1], atoms.cell[2]) self.y = 2 * np.dot(atoms.cell[0], atoms.cell[2]) self.z = 2 * np.dot(atoms.cell[0], atoms.cell[1]) self._G = np.array([[self.a, self.z / 2., self.y / 2.], [self.z / 2., self.b, self.x / 2.], [self.y / 2., self.x / 2., self.c]]) self._lmn() def update(self, C): """Procedure A0 as defined in Krivy.""" self._G = np.dot(C.T, np.dot(self._G, C)) self.a = self._G[0][0] self.b = self._G[1][1] self.c = self._G[2][2] self.x = 2 * self._G[1][2] self.y = 2 * self._G[0][2] self.z = 2 * self._G[0][1] self._lmn() def _lmn(self): """Updates G-tensor l, m, n values""" self.l = 0 self.m = 0 self.n = 0 if self.x < -self.epsilon: self.l = -1 elif self.x > self.epsilon: self.l = 1 if self.y < -self.epsilon: self.m = -1 elif self.y > self.epsilon: self.m = 1 if self.z < -self.epsilon: self.n = -1 elif self.z > self.epsilon: self.n = 1 def get_new_cell(self): """Returns new basis vectors""" a = np.sqrt(self.a) b = np.sqrt(self.b) c = np.sqrt(self.c) ad = self.atoms.cell[0] / np.linalg.norm(self.atoms.cell[0]) Z = np.cross(self.atoms.cell[0], self.atoms.cell[1]) Z /= np.linalg.norm(Z) X = ad - np.dot(ad, Z) * Z X /= np.linalg.norm(X) Y = np.cross(Z, X) alpha = np.arccos(self.x / (2 * b * c)) beta = np.arccos(self.y / (2 * a * c)) gamma = np.arccos(self.z / (2 * a * b)) va = a * np.array([1, 0, 0]) vb = b * np.array([np.cos(gamma), np.sin(gamma), 0]) cx = np.cos(beta) cy = (np.cos(alpha) - np.cos(beta) * np.cos(gamma)) \ / np.sin(gamma) cz = np.sqrt(1. - cx * cx - cy * cy) vc = c * np.array([cx, cy, cz]) abc = np.vstack((va, vb, vc)) T = np.vstack((X, Y, Z)) return np.dot(abc, T) G = _gtensor(atoms) # Once A2 and A5-A8 all evaluate to False, the unit cell will have # been fully reduced. for count in range(10000): if (G.a > G.b + G.epsilon or (not np.abs(G.a - G.b) > G.epsilon and np.abs(G.x) > np.abs(G.y) + G.epsilon)): # Procedure A1 A = np.array([[0, -1, 0], [-1, 0, 0], [0, 0, -1]]) G.update(A) C = np.dot(C, A) if (G.b > G.c + G.epsilon or (not np.abs(G.b - G.c) > G.epsilon and np.abs(G.y) > np.abs(G.z) + G.epsilon)): # Procedure A2 A = np.array([[-1, 0, 0], [0, 0, -1], [0, -1, 0]]) G.update(A) C = np.dot(C, A) continue if G.l * G.m * G.n == 1: # Procedure A3 i = -1 if G.l == -1 else 1 j = -1 if G.m == -1 else 1 k = -1 if G.n == -1 else 1 A = np.array([[i, 0, 0], [0, j, 0], [0, 0, k]]) G.update(A) C = np.dot(C, A) else: # Procedure A4 i = -1 if G.l == 1 else 1 j = -1 if G.m == 1 else 1 k = -1 if G.n == 1 else 1 if i * j * k == -1: if G.l == 0: i = -1 if G.m == 0: j = -1 if G.n == 0: k = -1 A = np.array([[i, 0, 0], [0, j, 0], [0, 0, k]]) G.update(A) C = np.dot(C, A) if (np.abs(G.x) > G.b + G.epsilon or (not np.abs(G.b - G.x) > G.epsilon and 2 * G.y < G.z - G.epsilon) or (not np.abs(G.b + G.x) > G.epsilon and G.z < -G.epsilon)): # Procedure A5 A = np.array([[1, 0, 0], [0, 1, -np.sign(G.x)], [0, 0, 1]], dtype=int) G.update(A) C = np.dot(C, A) elif (np.abs(G.y) > G.a + G.epsilon or (not np.abs(G.a - G.y) > G.epsilon and 2 * G.x < G.z - G.epsilon) or (not np.abs(G.a + G.y) > G.epsilon and G.z < -G.epsilon)): # Procedure A6 A = np.array([[1, 0, -np.sign(G.y)], [0, 1, 0], [0, 0, 1]], dtype=int) G.update(A) C = np.dot(C, A) elif (np.abs(G.z) > G.a + G.epsilon or (not np.abs(G.a - G.z) > G.epsilon and 2 * G.x < G.y - G.epsilon) or (not np.abs(G.a + G.z) > G.epsilon and G.y < -G.epsilon)): # Procedure A7 A = np.array([[1, -np.sign(G.z), 0], [0, 1, 0], [0, 0, 1]], dtype=int) G.update(A) C = np.dot(C, A) elif (G.x + G.y + G.z + G.a + G.b < -G.epsilon or (not np.abs(G.x + G.y + G.z + G.a + G.b) > G.epsilon and 2 * (G.a + G.y) + G.z > G.epsilon)): # Procedure A8 A = np.array([[1, 0, 1], [0, 1, 1], [0, 0, 1]]) G.update(A) C = np.dot(C, A) else: break else: raise RuntimeError('Niggli did not converge \ in {n} iterations!'.format(n=count)) scpos = np.dot(atoms.get_scaled_positions(), np.linalg.inv(C).T) scpos %= 1.0 scpos %= 1.0 atoms.set_cell(G.get_new_cell()) atoms.set_scaled_positions(scpos) # Self test if __name__ == '__main__': import doctest print('doctest: ', doctest.testmod()) python-ase-3.9.1.4567/ase/utils/extrapolate.py0000664000175000017500000000453112553425527021314 0ustar jensjjensj00000000000000from __future__ import print_function import numpy as np import sys from ase.parallel import paropen def extrapolate(x, y, n=-1.5, plot=0, reg=0, txt=None): '''Extrapolation tool. Mainly intended for RPA correlation energies, but could be useful for other purposes. Fits a straight line to an expression of the form: y=b + alpha*x**n and extrapolates the result to infinite x. reg=N gives linear regression using the last N points in x. reg should be larger than 2''' if txt is None: f = sys.stdout elif isinstance(txt, str): f = paropen(txt, 'a') else: f = txt assert len(x) == len(y) ext = [] print('Two-point extrapolation:', file=f) for i in range(len(x)-1): alpha = (y[i] - y[i+1]) / (x[i]**n - x[i+1]**n) ext.append(y[i+1] - alpha*x[i+1]**n) print(' ', x[i], '-', x[i+1], ':', ext[-1], file=f) print(file=f) if plot: import pylab as pl #pl.subplot(211) pl.plot(x**n, y, 'o-', label='Data') pl.xticks(x**n, [int(e) for e in x]) pl.axis([0, None, None, None]) if reg > 2: a = x[-reg:]**n b = y[-reg:] N = reg delta = N * np.sum(a**2) - (np.sum(a))**2 A = (np.sum(a**2) * np.sum(b) - np.sum(a) * np.sum(a*b)) / delta B = (N * np.sum(a*b) - np.sum(a) * np.sum(b)) / delta sigma_y = (1./(N-2.) * np.sum((b - A - B * a)**2))**0.5 sigma_A = sigma_y * (np.sum(a**2) / delta)**0.5 print('Linear regression using last %s points:' % N, file=f) print(' Extrapolated result:', A, file=f) print(' Uncertainty:', sigma_A, file=f) print(file=f) if plot: print([a[0], 0], [A + B * a[0], A]) pl.plot([a[0], 0], [A + B * a[0], A], '--', label='Regression') pl.legend(loc='upper left') else: A = 0 B = 0 sigma_A = 0 if plot: pl.show() #pl.subplot(212) pl.plot(x[1:], ext, 'o-', label='Two-point extrapolation') if reg > 2: pl.plot([x[-reg], x[-1]], [A, A], '--', label='Regression') pl.errorbar(x[-2], A, yerr=sigma_A, elinewidth=2.0, capsize=5, c='g') pl.legend(loc='lower right') pl.show() if not txt is None: f.close() return ext, A, B, sigma_A python-ase-3.9.1.4567/ase/utils/bee.py0000664000175000017500000000255712553425527017525 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/utils/_linprog.py0000664000175000017500000003303412553425527020575 0ustar jensjjensj00000000000000"""Copy of SciPy-0.15's scipy.optimize._linprog module.""" from __future__ import division, print_function, absolute_import import collections import numpy as np OptimizeResult = collections.namedtuple('OptimizeResult', 'x, fun') def _pivot_col(T, tol=1.0E-12, bland=False): ma = np.ma.masked_where(T[-1, :-1] >= -tol, T[-1, :-1], copy=False) if ma.count() == 0: return False, np.nan if bland: return True, np.where(ma.mask is False)[0][0] return True, np.ma.where(ma == ma.min())[0][0] def _pivot_row(T, pivcol, phase, tol=1.0E-12): if phase == 1: k = 2 else: k = 1 ma = np.ma.masked_where(T[:-k, pivcol] <= tol, T[:-k, pivcol], copy=False) if ma.count() == 0: return False, np.nan mb = np.ma.masked_where(T[:-k, pivcol] <= tol, T[:-k, -1], copy=False) q = mb / ma return True, np.ma.where(q == q.min())[0][0] def _solve_simplex(T, n, basis, maxiter=1000, phase=2, callback=None, tol=1.0E-12, nit0=0, bland=False): nit = nit0 complete = False solution = np.zeros(T.shape[1] - 1, dtype=np.float64) if phase == 1: m = T.shape[0] - 2 elif phase == 2: m = T.shape[0] - 1 else: raise ValueError("Argument 'phase' to _solve_simplex must be 1 or 2") while not complete: # Find the pivot column pivcol_found, pivcol = _pivot_col(T, tol, bland) if not pivcol_found: pivcol = np.nan pivrow = np.nan status = 0 complete = True else: # Find the pivot row pivrow_found, pivrow = _pivot_row(T, pivcol, phase, tol) if not pivrow_found: status = 3 complete = True if callback is not None: solution[:] = 0 solution[basis[:m]] = T[:m, -1] callback(solution[:n], **{"tableau": T, "phase": phase, "nit": nit, "pivot": (pivrow, pivcol), "basis": basis, "complete": complete and phase == 2}) if not complete: if nit >= maxiter: # Iteration limit exceeded status = 1 complete = True else: # variable represented by pivcol enters # variable in basis[pivrow] leaves basis[pivrow] = pivcol pivval = T[pivrow][pivcol] T[pivrow, :] = T[pivrow, :] / pivval for irow in range(T.shape[0]): if irow != pivrow: T[irow] = T[irow] - T[pivrow] * T[irow, pivcol] nit += 1 return nit, status def linprog(c, A_ub=None, b_ub=None, A_eq=None, b_eq=None, bounds=None, maxiter=1000, disp=False, callback=None, tol=1.0E-12, bland=False, **unknown_options): status = 0 messages = {0: "Optimization terminated successfully.", 1: "Iteration limit reached.", 2: "Optimzation failed. Unable to find a feasible" " starting point.", 3: "Optimization failed. The problem appears to be unbounded.", 4: "Optimization failed. Singular matrix encountered."} have_floor_variable = False cc = np.asarray(c) # The initial value of the objective function element in the tableau f0 = 0 # The number of variables as given by c n = len(c) # Convert the input arguments to arrays (sized to zero if not provided) Aeq = np.asarray(A_eq) if A_eq is not None else np.empty([0, len(cc)]) Aub = np.asarray(A_ub) if A_ub is not None else np.empty([0, len(cc)]) beq = np.ravel(np.asarray(b_eq)) if b_eq is not None else np.empty([0]) bub = np.ravel(np.asarray(b_ub)) if b_ub is not None else np.empty([0]) # Analyze the bounds and determine what modifications to me made to # the constraints in order to accommodate them. L = np.zeros(n, dtype=np.float64) U = np.ones(n, dtype=np.float64) * np.inf if bounds is None or len(bounds) == 0: pass elif len(bounds) == 2 and not hasattr(bounds[0], '__len__'): # All bounds are the same L = np.asarray(n * [bounds[0]], dtype=np.float64) U = np.asarray(n * [bounds[1]], dtype=np.float64) else: if len(bounds) != n: status = -1 message = ("Invalid input for linprog with method = 'simplex'. " "Length of bounds is inconsistent with the length of c") else: try: for i in range(n): if len(bounds[i]) != 2: raise IndexError() L[i] = (bounds[i][0] if bounds[i][0] is not None else -np.inf) U[i] = bounds[i][1] if bounds[i][1] is not None else np.inf except IndexError: status = -1 message = ("Invalid input for linprog with " "method = 'simplex'. bounds must be a n x 2 " "sequence/array where n = len(c).") if np.any(L == -np.inf): # If any lower-bound constraint is a free variable # add the first column variable as the "floor" variable which # accommodates the most negative variable in the problem. n = n + 1 L = np.concatenate([np.array([0]), L]) U = np.concatenate([np.array([np.inf]), U]) cc = np.concatenate([np.array([0]), cc]) Aeq = np.hstack([np.zeros([Aeq.shape[0], 1]), Aeq]) Aub = np.hstack([np.zeros([Aub.shape[0], 1]), Aub]) have_floor_variable = True # Now before we deal with any variables with lower bounds < 0, # deal with finite bounds which can be simply added as new constraints. # Also validate bounds inputs here. for i in range(n): if(L[i] > U[i]): status = -1 message = ("Invalid input for linprog with method = 'simplex'. " "Lower bound %d is greater than upper bound %d" % (i, i)) if np.isinf(L[i]) and L[i] > 0: status = -1 message = ("Invalid input for linprog with method = 'simplex'. " "Lower bound may not be +infinity") if np.isinf(U[i]) and U[i] < 0: status = -1 message = ("Invalid input for linprog with method = 'simplex'. " "Upper bound may not be -infinity") if np.isfinite(L[i]) and L[i] > 0: # Add a new lower-bound (negative upper-bound) constraint Aub = np.vstack([Aub, np.zeros(n)]) Aub[-1, i] = -1 bub = np.concatenate([bub, np.array([-L[i]])]) L[i] = 0 if np.isfinite(U[i]): # Add a new upper-bound constraint Aub = np.vstack([Aub, np.zeros(n)]) Aub[-1, i] = 1 bub = np.concatenate([bub, np.array([U[i]])]) U[i] = np.inf # Now find negative lower bounds (finite or infinite) which require a # change of variables or free variables and handle them appropriately for i in range(0, n): if L[i] < 0: if np.isfinite(L[i]) and L[i] < 0: # Add a change of variables for x[i] # For each row in the constraint matrices, we take the # coefficient from column i in A, # and subtract the product of that and L[i] to the RHS b beq[:] = beq[:] - Aeq[:, i] * L[i] bub[:] = bub[:] - Aub[:, i] * L[i] # We now have a nonzero initial value for the objective # function as well. f0 = f0 - cc[i] * L[i] else: # This is an unrestricted variable, let x[i] = u[i] - v[0] # where v is the first column in all matrices. Aeq[:, 0] = Aeq[:, 0] - Aeq[:, i] Aub[:, 0] = Aub[:, 0] - Aub[:, i] cc[0] = cc[0] - cc[i] if np.isinf(U[i]): if U[i] < 0: status = -1 message = ("Invalid input for linprog with " "method = 'simplex'. Upper bound may not be -inf.") # The number of upper bound constraints (rows in A_ub and elements in b_ub) mub = len(bub) # The number of equality constraints (rows in A_eq and elements in b_eq) meq = len(beq) # The total number of constraints m = mub + meq # The number of slack variables (one for each of the upper-bound # constraints) n_slack = mub # The number of artificial variables (one for each lower-bound and equality # constraint) n_artificial = meq + (bub < 0).sum() try: Aub_rows, Aub_cols = Aub.shape except ValueError: raise ValueError("Invalid input. A_ub must be two-dimensional") try: Aeq_rows, Aeq_cols = Aeq.shape except ValueError: raise ValueError("Invalid input. A_eq must be two-dimensional") if Aeq_rows != meq: status = -1 message = ("Invalid input for linprog with method = 'simplex'. " "The number of rows in A_eq must be equal " "to the number of values in b_eq") if Aub_rows != mub: status = -1 message = ("Invalid input for linprog with method = 'simplex'. " "The number of rows in A_ub must be equal " "to the number of values in b_ub") if Aeq_cols > 0 and Aeq_cols != n: status = -1 message = ("Invalid input for linprog with method = 'simplex'. " "Number of columns in A_eq must be equal " "to the size of c") if Aub_cols > 0 and Aub_cols != n: status = -1 message = ("Invalid input for linprog with method = 'simplex'. " "Number of columns in A_ub must be equal to the size of c") if status != 0: # Invalid inputs provided raise ValueError(message) # Create the tableau T = np.zeros([m + 2, n + n_slack + n_artificial + 1]) # Insert objective into tableau T[-2, :n] = cc T[-2, -1] = f0 b = T[:-2, -1] if meq > 0: # Add Aeq to the tableau T[:meq, :n] = Aeq # Add beq to the tableau b[:meq] = beq if mub > 0: # Add Aub to the tableau T[meq:meq + mub, :n] = Aub # At bub to the tableau b[meq:meq + mub] = bub # Add the slack variables to the tableau np.fill_diagonal(T[meq:m, n:n + n_slack], 1) # Further setup the tableau # If a row corresponds to an equality constraint or a negative b (a lower # bound constraint), then an artificial variable is added for that row. # Also, if b is negative, first flip the signs in that constraint. slcount = 0 avcount = 0 basis = np.zeros(m, dtype=int) r_artificial = np.zeros(n_artificial, dtype=int) for i in range(m): if i < meq or b[i] < 0: # basic variable i is in column n+n_slack+avcount basis[i] = n + n_slack + avcount r_artificial[avcount] = i avcount += 1 if b[i] < 0: b[i] *= -1 T[i, :-1] *= -1 T[i, basis[i]] = 1 T[-1, basis[i]] = 1 else: # basic variable i is in column n+slcount basis[i] = n + slcount slcount += 1 # Make the artificial variables basic feasible variables by subtracting # each row with an artificial variable from the Phase 1 objective for r in r_artificial: T[-1, :] = T[-1, :] - T[r, :] nit1, status = _solve_simplex(T, n, basis, phase=1, callback=callback, maxiter=maxiter, tol=tol, bland=bland) # if pseudo objective is zero, remove the last row from the tableau and # proceed to phase 2 if abs(T[-1, -1]) < tol: # Remove the pseudo-objective row from the tableau T = T[:-1, :] # Remove the artificial variable columns from the tableau T = np.delete(T, np.s_[n + n_slack:n + n_slack + n_artificial], 1) else: # Failure to find a feasible starting point status = 2 if status != 0: message = messages[status] if disp: print(message) 2 / 0 # Phase 2 nit2, status = _solve_simplex(T, n, basis, maxiter=maxiter - nit1, phase=2, callback=callback, tol=tol, nit0=nit1, bland=bland) solution = np.zeros(n + n_slack + n_artificial) solution[basis[:m]] = T[:m, -1] x = solution[:n] slack = solution[n:n + n_slack] # For those variables with finite negative lower bounds, # reverse the change of variables masked_L = np.ma.array(L, mask=np.isinf(L), fill_value=0.0).filled() x = x + masked_L # For those variables with infinite negative lower bounds, # take x[i] as the difference between x[i] and the floor variable. if have_floor_variable: for i in range(1, n): if np.isinf(L[i]): x[i] -= x[0] x = x[1:] # Optimization complete at this point obj = -T[-1, -1] if status in (0, 1): if disp: print(messages[status]) print(" Current function value: {: <12.6f}".format(obj)) print(" Iterations: {:d}".format(nit2)) else: if disp: print(messages[status]) print(" Iterations: {:d}".format(nit2)) return OptimizeResult(x, obj) python-ase-3.9.1.4567/ase/utils/distance.py0000664000175000017500000000340612553425527020556 0ustar jensjjensj00000000000000import numpy as np def distance(s1, s2, permute=True): """Get the distance between two structures s1 and s2. The distance is defined by the Frobenius norm of the spatial distance between all coordinates (see numpy.linalg.norm for the definition). permute: minimise the distance by 'permuting' same elements """ s1 = s1.copy() s2 = s2.copy() for s in [s1, s2]: s.translate(-s.get_center_of_mass()) s2pos = 1. * s2.get_positions() def align(struct, xaxis='x', yaxis='y'): """Align moments of inertia with the coordinate system.""" Is, Vs = struct.get_moments_of_inertia(True) IV = list(zip(Is, Vs)) IV.sort(key=lambda x: x[0]) struct.rotate(IV[0][1], xaxis) Is, Vs = struct.get_moments_of_inertia(True) IV = list(zip(Is, Vs)) IV.sort(key=lambda x: x[0]) struct.rotate(IV[1][1], yaxis) align(s1) def dd(s1, s2, permute): if permute: s2 = s2.copy() dist = 0 for a in s1: imin = None dmin = np.Inf for i, b in enumerate(s2): if a.symbol == b.symbol: d = np.sum((a.position - b.position)**2) if d < dmin: dmin = d imin = i dist += dmin s2.pop(imin) return np.sqrt(dist) else: return np.linalg.norm(s1.get_positions() - s2.get_positions()) dists = [] # principles for x, y in zip(['x', '-x', 'x', '-x'], ['y', 'y', '-y', '-y']): s2.set_positions(s2pos) align(s2, x, y) dists.append(dd(s1, s2, permute)) return min(dists) python-ase-3.9.1.4567/ase/cli/0000775000175000017500000000000012553427753016021 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/cli/__init__.py0000664000175000017500000000000012553425527020115 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/cli/build.py0000664000175000017500000001207512553425527017474 0ustar jensjjensj00000000000000import sys import optparse import numpy as np from ase.db import connect from ase.lattice import bulk from ase.io import read, write from ase.visualize import view from ase.structure import molecule from ase.atoms import Atoms, string2symbols from ase.data import ground_state_magnetic_moments from ase.data import atomic_numbers, covalent_radii def main(): parser = optparse.OptionParser( usage='%prog [options] name/input-file [output-file]') add = parser.add_option add('-M', '--magnetic-moment', metavar='M1,M2,...', help='Magnetic moment(s). ' + 'Use "-M 1" or "-M 2.3,-2.3".') add('--modify', metavar='...', help='Modify atoms with Python statement. ' + 'Example: --modify="atoms.positions[-1,2]+=0.1".') add('-v', '--vacuum', type=float, default=3.0, help='Amount of vacuum to add around isolated atoms ' '(in Angstrom).') add('--unit-cell', help='Unit cell. Examples: "10.0" or "9,10,11" ' + '(in Angstrom).') add('--bond-length', type=float, help='Bond length of dimer in Angstrom.') add('-x', '--crystal-structure', help='Crystal structure.', choices=['sc', 'fcc', 'bcc', 'hcp', 'diamond', 'zincblende', 'rocksalt', 'cesiumchloride', 'fluorite', 'wurtzite']) add('-a', '--lattice-constant', default='', help='Lattice constant(s) in Angstrom.') add('--orthorhombic', action='store_true', help='Use orthorhombic unit cell.') add('--cubic', action='store_true', help='Use cubic unit cell.') add('-r', '--repeat', help='Repeat unit cell. Use "-r 2" or "-r 2,3,1".') add('-g', '--gui', action='store_true') opts, args = parser.parse_args() if len(args) == 0 or len(args) > 2: parser.error('Wrong number of arguments!') name = args.pop(0) if '.' in name: # Read from file: atoms = read(name) elif opts.crystal_structure: atoms = build_bulk(name, opts) else: atoms = build_molecule(name, opts) if opts.magnetic_moment: magmoms = np.array( [float(m) for m in opts.magnetic_moment.split(',')]) atoms.set_initial_magnetic_moments( np.tile(magmoms, len(atoms) // len(magmoms))) if opts.modify: exec(opts.modify, {'atoms': atoms}) if opts.repeat is not None: r = opts.repeat.split(',') if len(r) == 1: r = 3 * r atoms = atoms.repeat([int(c) for c in r]) if opts.gui: view(atoms) if args: write(args[0], atoms) elif sys.stdout.isatty(): write(name + '.json', atoms) else: con = connect(sys.stdout, type='json') con.write(atoms, name=name) def build_molecule(name, opts): try: # Known molecule or atom? atoms = molecule(name) except NotImplementedError: symbols = string2symbols(name) if len(symbols) == 1: Z = atomic_numbers[symbols[0]] magmom = ground_state_magnetic_moments[Z] atoms = Atoms(name, magmoms=[magmom]) elif len(symbols) == 2: # Dimer if opts.bond_length is None: b = (covalent_radii[atomic_numbers[symbols[0]]] + covalent_radii[atomic_numbers[symbols[1]]]) else: b = opts.bond_length atoms = Atoms(name, positions=[(0, 0, 0), (b, 0, 0)]) else: raise ValueError('Unknown molecule: ' + name) else: if len(atoms) == 2 and opts.bond_length is not None: atoms.set_distance(0, 1, opts.bond_length) if opts.unit_cell is None: atoms.center(vacuum=opts.vacuum) else: a = [float(x) for x in opts.unit_cell.split(',')] if len(a) == 1: cell = [a[0], a[0], a[0]] elif len(a) == 3: cell = a else: a, b, c, alpha, beta, gamma = a 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) cell = [[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)]] atoms.cell = cell atoms.center() return atoms def build_bulk(name, opts): L = opts.lattice_constant.replace(',', ' ').split() d = dict([(key, float(x)) for key, x in zip('ac', L)]) atoms = bulk(name, crystalstructure=opts.crystal_structure, a=d.get('a'), c=d.get('c'), orthorhombic=opts.orthorhombic, cubic=opts.cubic) M, X = {'Fe': (2.3, 'bcc'), 'Co': (1.2, 'hcp'), 'Ni': (0.6, 'fcc')}.get(name, (None, None)) if M is not None and opts.crystal_structure == X: atoms.set_initial_magnetic_moments([M] * len(atoms)) return atoms python-ase-3.9.1.4567/ase/cli/info.py0000775000175000017500000000167512553425527017337 0ustar jensjjensj00000000000000#!/usr/bin/env python from optparse import OptionParser from ase.io import filetype from ase.io.aff import print_aff_info from ase.io.pickletrajectory import print_trajectory_info from ase.io.bundletrajectory import print_bundletrajectory_info description = 'Print summary of information from trajectory files.' def main(): p = OptionParser(usage='%prog file.traj [file2.traj ...]', description=description) opts, args = p.parse_args() if len(args) == 0: p.error('Incorrect number of arguments') for f in args: ft = filetype(f) print("File type of '{0}' appears to be of type '{1}'".format(f, ft)) if ft == 'traj': print_aff_info(f) elif ft == 'trj': print_trajectory_info(f) elif ft == 'bundle': print_bundletrajectory_info(f) else: p.error('%s is of type %s; cannot print info about this type of file' % f) python-ase-3.9.1.4567/ase/cli/run.py0000664000175000017500000002652612553425527017207 0ustar jensjjensj00000000000000from __future__ import division, print_function import sys import os.path import optparse import os import tempfile import time import traceback import numpy as np from ase.io import read from ase.parallel import world from ase.utils import devnull from ase.constraints import FixAtoms, UnitCellFilter from ase.optimize import LBFGS from ase.io.trajectory import Trajectory from ase.utils.eos import EquationOfState from ase.calculators.calculator import get_calculator, names as calcnames import ase.db as db def main(): runner = Runner() runner.parse() if runner.errors: sys.exit(runner.errors) class Runner: def __init__(self): self.db = None self.opts = None self.errors = 0 self.names = [] self.calculator_name = None if world.rank == 0: self.logfile = sys.stdout else: self.logfile = devnull def parse(self, args=None): parser = self.make_parser() self.add_options(parser) self.opts, names = parser.parse_args(args) if args is None and self.opts.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.cli.run import Runner\n') file.write('atoms = Runner().parse(%r)\n' % ([self.calculator_name] + sys.argv[1:])) file.flush() os.system('python -i %s' % file.name) return if self.calculator_name is None: if names: self.calculator_name = names.pop(0) else: parser.error('Missing calculator name') atoms = self.run(names) return atoms def make_parser(self): parser = optparse.OptionParser( usage='ase-run calculator [options] [system, ...]', description="Run calculation with one of ASE's calculators: " + ', '.join(calcnames) + '.') return parser def add_options(self, parser): add = parser.add_option add('-t', '--tag', help='String tag added to filenames.') add('-p', '--parameters', default='', metavar='key=value,...', help='Comma-separated key=value pairs of ' + 'calculator specific parameters.') add('-d', '--database', help='Use a filename with a ".db" extension for a sqlite3 ' + 'database or a ".json" extension for a simple json database. ' + 'Default is no database') add('-S', '--skip', action='store_true', help='Skip calculations already done.') add('--properties', default='efsdMm', help='Default value is "efsdMm" meaning calculate energy, ' + 'forces, stress, dipole moment, total magnetic moment and ' + 'atomic magnetic moments.') add('-f', '--maximum-force', type=float, help='Relax internal coordinates.') add('--constrain-tags', metavar='T1,T2,...', help='Constrain atoms with tags T1, T2, ...') add('-s', '--maximum-stress', type=float, help='Relax unit-cell and internal coordinates.') add('-E', '--equation-of-state', help='Equation of state ...') add('--eos-type', default='sjeos', help='Selects the type of eos.') add('-i', '--interactive-python-session', action='store_true') add('-c', '--collection') add('--modify', metavar='...', help='Modify atoms with Python statement. ' + 'Example: --modify="atoms.positions[-1,2]+=0.1".') add('--after', help='Perform operation after calculation. ' + 'Example: --after="atoms.calc.write(...)"') def log(self, *args, **kwargs): print(file=self.logfile, *args, **kwargs) def run(self, names): opts = self.opts if self.db is None: # Create database connection: self.db = db.connect(opts.database, use_lock_file=True) self.expand(names) if not names: names.insert(0, '-') atoms = None for name in names: if atoms is not None: del atoms.calc # release resources from last calculation atoms = self.build(name) if opts.modify: exec(opts.modify, {'atoms': atoms, 'np': np}) if name == '-': name = atoms.info['key_value_pairs']['name'] skip = False id = None if opts.skip: id = self.db.reserve(name=name) if id is None: skip = True if not skip: self.set_calculator(atoms, name) tstart = time.time() try: self.log('Running:', name) data = self.calculate(atoms, name) except KeyboardInterrupt: raise except Exception: self.log(name, 'FAILED') traceback.print_exc(file=self.logfile) tstop = time.time() data = {'time': tstop - tstart} self.errors += 1 else: tstop = time.time() data['time'] = tstop - tstart self.db.write(atoms, name=name, data=data) if id: del self.db[id] return atoms def calculate(self, atoms, name): opts = self.opts data = {} if opts.maximum_force or opts.maximum_stress: data = self.optimize(atoms, name) if opts.equation_of_state: data.update(self.eos(atoms, name)) data.update(self.calculate_once(atoms, name)) if opts.after: exec(opts.after, {'atoms': atoms, 'data': data}) return data def expand(self, names): if not self.names and self.opts.collection: con = db.connect(self.opts.collection) self.names = [dct.id for dct in con.select()] if not names: names[:] = self.names return if not self.names: return i = 0 while i < len(names): name = names[i] if name.count('-') == 1: s1, s2 = name.split('-') if s1 in self.names and s2 in self.names: j1 = self.names.index(s1) j2 = self.names.index(s2) names[i:i + 1] = self.names[j1:j2 + 1] i += j2 - j1 i += 1 def build(self, name): if name == '-': con = db.connect(sys.stdin, 'json') return con.get_atoms(add_additional_information=True) elif self.opts.collection: con = db.connect(self.opts.collection) return con.get_atoms(name) else: return read(name) def set_calculator(self, atoms, name): cls = get_calculator(self.calculator_name) parameters = str2dict(self.opts.parameters) if getattr(cls, 'nolabel', False): atoms.calc = cls(**parameters) else: atoms.calc = cls(label=self.get_filename(name), **parameters) def calculate_once(self, atoms, name): opts = self.opts for p in opts.properties or 'efsdMm': property, method = {'e': ('energy', 'get_potential_energy'), 'f': ('forces', 'get_forces'), 's': ('stress', 'get_stress'), 'd': ('dipole', 'get_dipole_moment'), 'M': ('magmom', 'get_magnetic_moment'), 'm': ('magmoms', 'get_magnetic_moments')}[p] try: getattr(atoms, method)() except NotImplementedError: pass data = {} return data def optimize(self, atoms, name): opts = self.opts if opts.constrain_tags: tags = [int(t) for t in opts.constrain_tags.split(',')] mask = [t in tags for t in atoms.get_tags()] atoms.constraints = FixAtoms(mask=mask) trajectory = Trajectory(self.get_filename(name, 'traj'), 'w', atoms) if opts.maximum_stress: optimizer = LBFGS(UnitCellFilter(atoms), logfile=self.logfile) fmax = opts.maximum_stress else: optimizer = LBFGS(atoms, logfile=self.logfile) fmax = opts.maximum_force optimizer.attach(trajectory) optimizer.run(fmax=fmax) data = {} if hasattr(optimizer, 'force_calls'): data['force_calls'] = optimizer.force_calls return data def eos(self, atoms, name): opts = self.opts traj = Trajectory(self.get_filename(name, 'traj'), 'w', atoms) eps = 0.01 strains = np.linspace(1 - eps, 1 + eps, 5) v1 = atoms.get_volume() volumes = strains**3 * v1 energies = [] cell1 = atoms.cell for s in strains: atoms.set_cell(cell1 * s, scale_atoms=True) energies.append(atoms.get_potential_energy()) traj.write(atoms) traj.close() eos = EquationOfState(volumes, energies, opts.eos_type) v0, e0, B = eos.fit() atoms.set_cell(cell1 * (v0 / v1)**(1 / 3), scale_atoms=True) data = {'volumes': volumes, 'energies': energies, 'fitted_energy': e0, 'fitted_volume': v0, 'bulk_modulus': B, 'eos_type': opts.eos_type} return data def get_filename(self, name=None, ext=None): if name is None: if self.opts.tag is None: filename = 'ase' else: filename = self.opts.tag else: if '.' in name: name = name.rsplit('.', 1)[0] if self.opts.tag is None: filename = name else: filename = name + '-' + self.opts.tag if ext: filename += '.' + ext return filename def str2dict(s, namespace={}, sep='='): """Convert comma-separated key=value string to dictionary. Examples: >>> str2dict('xc=PBE,nbands=200,parallel={band:4}') {'xc': 'PBE', 'nbands': 200, 'parallel': {'band': 4}} >>> str2dict('a=1.2,b=True,c=ab,d=1,2,3,e={f:42,g:cd}') {'a': 1.2, 'c': 'ab', 'b': True, 'e': {'g': 'cd', 'f': 42}, 'd': (1, 2, 3)} """ def myeval(value): try: value = eval(value, namespace) except (NameError, SyntaxError): pass return value dct = {} s = (s + ',').split(sep) for i in range(len(s) - 1): key = s[i] m = s[i + 1].rfind(',') value = s[i + 1][:m] if value[0] == '{': assert value[-1] == '}' value = str2dict(value[1:-1], namespace, ':') elif value[0] == '(': assert value[-1] == ')' value = [myeval(t) for t in value[1:-1].split(',')] else: value = myeval(value) dct[key] = value s[i + 1] = s[i + 1][m + 1:] return dct python-ase-3.9.1.4567/ase/thermochemistry.py0000664000175000017500000004763112553425527021062 0ustar jensjjensj00000000000000from __future__ import print_function """Modules for calculating thermochemical information from computational outputs.""" import os import sys import numpy as np from ase import units def rotationalinertia(atoms): """Calculates the three principle moments of inertia for an ASE atoms object. This uses the atomic masses from ASE, which (if not explicitly specified by the user) gives an inexact approximation of an isotopically averaged result. Units are in amu*angstroms**2.""" # Calculate the center of mass. xcm, ycm, zcm = atoms.get_center_of_mass() masses = atoms.get_masses() # Calculate moments of inertia in the current frame of reference. Ixx = 0. Iyy = 0. Izz = 0. Ixy = 0. Ixz = 0. Iyz = 0. for index, atom in enumerate(atoms): m = masses[index] x = atom.x - xcm y = atom.y - ycm z = atom.z - zcm Ixx += m * (y**2. + z**2.) Iyy += m * (x**2. + z**2.) Izz += m * (x**2. + y**2.) Ixy += m * x * y Ixz += m * x * z Iyz += m * y * z # Create the inertia tensor in the current frame of reference. I_ = np.matrix([[ Ixx, -Ixy, -Ixz], [-Ixy, Iyy, -Iyz], [-Ixz, -Iyz, Izz]]) # Find the eigenvalues, which are the principle moments of inertia. I = np.linalg.eigvals(I_) return I class ThermoChem: """Base class containing common methods used in thermochemistry calculations.""" def get_ZPE_correction(self): """Returns the zero-point vibrational energy correction in eV.""" zpe = 0. for energy in self.vib_energies: zpe += 0.5 * energy return zpe def _vibrational_energy_contribution(self, temperature): """Calculates the change in internal energy due to vibrations from 0K to the specified temperature for a set of vibrations given in eV and a temperature given in Kelvin. Returns the energy change in eV.""" kT = units.kB * temperature dU = 0. for energy in self.vib_energies: dU += energy / (np.exp(energy / kT) - 1.) return dU def _vibrational_entropy_contribution(self, temperature): """Calculates the entropy due to vibrations for a set of vibrations given in eV and a temperature given in Kelvin. Returns the entropy in eV/K.""" kT = units.kB * temperature S_v = 0. for energy in self.vib_energies: x = energy / kT S_v += x / (np.exp(x) - 1.) - np.log(1. - np.exp(-x)) S_v *= units.kB return S_v def _vprint(self, text): """Print output if verbose flag True.""" if self.verbose: sys.stdout.write(text + os.linesep) class HarmonicThermo(ThermoChem): """Class for calculating thermodynamic properties in the approximation that all degrees of freedom are treated harmonically. Often used for adsorbates. Inputs: vib_energies : list a list of the harmonic energies of the adsorbate (e.g., from ase.vibrations.Vibrations.get_energies). The number of energies should match the number of degrees of freedom of the adsorbate; i.e., 3*n, where n is the number of atoms. Note that this class does not check that the user has supplied the correct number of energies. Units of energies are eV. electronicenergy : float the electronic energy in eV (if electronicenergy is unspecified, then the methods of this class can be interpreted as the energy corrections) """ def __init__(self, vib_energies, electronicenergy=None): self.vib_energies = vib_energies # Check for imaginary frequencies. if sum(np.iscomplex(self.vib_energies)): raise ValueError('Imaginary vibrational energies are present.') else: self.vib_energies = np.real(self.vib_energies) # clear +0.j if electronicenergy: self.electronicenergy = electronicenergy else: self.electronicenergy = 0. def get_internal_energy(self, temperature, verbose=True): """Returns the internal energy, in eV, in the harmonic approximation at a specified temperature (K).""" self.verbose = verbose write = self._vprint fmt = '%-15s%13.3f eV' write('Internal energy components at T = %.2f K:' % temperature) write('=' * 31) U = 0. write(fmt % ('E_elec', self.electronicenergy)) U += self.electronicenergy zpe = self.get_ZPE_correction() write(fmt % ('E_ZPE', zpe)) U += zpe dU_v = self._vibrational_energy_contribution(temperature) write(fmt % ('Cv_harm (0->T)', dU_v)) U += dU_v write('-' * 31) write(fmt % ('U', U)) write('=' * 31) return U def get_entropy(self, temperature, verbose=True): """Returns the entropy, in eV/K, in the harmonic approximation at a specified temperature (K).""" self.verbose = verbose write = self._vprint fmt = '%-15s%13.7f eV/K%13.3f eV' write('Entropy components at T = %.2f K:' % temperature) write('=' * 49) write('%15s%13s %13s' % ('', 'S', 'T*S')) S = 0. S_v = self._vibrational_entropy_contribution(temperature) write(fmt % ('S_harm', S_v, S_v * temperature)) S += S_v write('-' * 49) write(fmt % ('S', S, S * temperature)) write('=' * 49) return S def get_gibbs_energy(self, temperature, verbose=True): """Returns the Gibbs free energy, in eV, in the harmonic approximation at a specified temperature (K).""" self.verbose = True write = self._vprint U = self.get_internal_energy(temperature, verbose=verbose) write('') S = self.get_entropy(temperature, verbose=verbose) G = U - temperature * S write('') write('Free energy components at T = %.2f K:' % temperature) write('=' * 23) fmt = '%5s%15.3f eV' write(fmt % ('U', U)) write(fmt % ('-T*S', -temperature * S)) write('-' * 23) write(fmt % ('G', G)) write('=' * 23) return G class IdealGasThermo(ThermoChem): """Class for calculating thermodynamic properties of a molecule based on statistical mechanical treatments in the ideal gas approximation. Inputs for enthalpy calculations: vib_energies : list a list of the vibrational energies of the molecule (e.g., from ase.vibrations.Vibrations.get_energies). The number of vibrations used is automatically calculated by the geometry and the number of atoms. If more are specified than are needed, then the lowest numbered vibrations are neglected. If either atoms or natoms is unspecified, then uses the entire list. Units are eV. geometry : 'monatomic', 'linear', or 'nonlinear' geometry of the molecule electronicenergy : float the electronic energy in eV (if electronicenergy is unspecified, then the methods of this class can be interpreted as the enthalpy and free energy corrections) natoms : integer the number of atoms, used along with 'geometry' to determine how many vibrations to use. (Not needed if an atoms object is supplied in 'atoms' or if the user desires the entire list of vibrations to be used.) Extra inputs needed for for entropy / free energy calculations: atoms : an ASE atoms object used to calculate rotational moments of inertia and molecular mass symmetrynumber : integer symmetry number of the molecule. See, for example, Table 10.1 and Appendix B of C. Cramer "Essentials of Computational Chemistry", 2nd Ed. spin : float the total electronic spin. (0 for molecules in which all electrons are paired, 0.5 for a free radical with a single unpaired electron, 1.0 for a triplet with two unpaired electrons, such as O_2.) """ def __init__(self, vib_energies, geometry, electronicenergy=None, atoms=None, symmetrynumber=None, spin=None, natoms=None): if electronicenergy == None: self.electronicenergy = 0. else: self.electronicenergy = electronicenergy self.geometry = geometry self.atoms = atoms self.sigma = symmetrynumber self.spin = spin if natoms == None: if atoms: natoms = len(atoms) # Cut the vibrations to those needed from the geometry. if natoms: if geometry == 'nonlinear': self.vib_energies = vib_energies[-(3 * natoms - 6):] elif geometry == 'linear': self.vib_energies = vib_energies[-(3 * natoms - 5):] elif geometry == 'monatomic': self.vib_energies = [] else: self.vib_energies = vib_energies # Make sure no imaginary frequencies remain. if sum(np.iscomplex(self.vib_energies)): raise ValueError('Imaginary frequencies are present.') else: self.vib_energies = np.real(self.vib_energies) # clear +0.j self.referencepressure = 101325. # Pa def get_enthalpy(self, temperature, verbose=True): """Returns the enthalpy, in eV, in the ideal gas approximation at a specified temperature (K).""" self.verbose = verbose write = self._vprint fmt = '%-15s%13.3f eV' write('Enthalpy components at T = %.2f K:' % temperature) write('=' * 31) H = 0. write(fmt % ('E_elec', self.electronicenergy)) H += self.electronicenergy zpe = self.get_ZPE_correction() write(fmt % ('E_ZPE', zpe)) H += zpe Cv_t = 3. / 2. * units.kB # translational heat capacity (3-d gas) write(fmt % ('Cv_trans (0->T)', Cv_t * temperature)) H += Cv_t * temperature if self.geometry == 'nonlinear': # rotational heat capacity Cv_r = 3. / 2. * units.kB elif self.geometry == 'linear': Cv_r = units.kB elif self.geometry == 'monatomic': Cv_r = 0. write(fmt % ('Cv_rot (0->T)', Cv_r * temperature)) H += Cv_r * temperature dH_v = self._vibrational_energy_contribution(temperature) write(fmt % ('Cv_vib (0->T)', dH_v)) H += dH_v Cp_corr = units.kB * temperature write(fmt % ('(C_v -> C_p)', Cp_corr)) H += Cp_corr write('-' * 31) write(fmt % ('H', H)) write('=' * 31) return H def get_entropy(self, temperature, pressure, verbose=True): """Returns the entropy, in eV/K, in the ideal gas approximation at a specified temperature (K) and pressure (Pa).""" if self.atoms == None or self.sigma == None or self.spin == None: raise RuntimeError('atoms, symmetrynumber, and spin must be ' 'specified for entropy and free energy ' 'calculations.') self.verbose = verbose write = self._vprint fmt = '%-15s%13.7f eV/K%13.3f eV' write('Entropy components at T = %.2f K and P = %.1f Pa:' % (temperature, pressure)) write('=' * 49) write('%15s%13s %13s' % ('', 'S', 'T*S')) S = 0.0 # Translational entropy (term inside the log is in SI units). mass = sum(self.atoms.get_masses()) * units._amu # kg/molecule S_t = (2 * np.pi * mass * units._k * temperature / units._hplanck**2)**(3.0 / 2) S_t *= units._k * temperature / self.referencepressure S_t = units.kB * (np.log(S_t) + 5.0 / 2.0) write(fmt % ('S_trans (1 atm)', S_t, S_t * temperature)) S += S_t # Rotational entropy (term inside the log is in SI units). if self.geometry == 'monatomic': S_r = 0.0 elif self.geometry == 'nonlinear': inertias = (rotationalinertia(self.atoms) * units._amu / (10.0**10)**2) # kg m^2 S_r = np.sqrt(np.pi * np.product(inertias)) / self.sigma S_r *= (8.0 * np.pi**2 * units._k * temperature / units._hplanck**2)**(3.0 / 2.0) S_r = units.kB * (np.log(S_r) + 3.0 / 2.0) elif self.geometry == 'linear': inertias = (rotationalinertia(self.atoms) * units._amu / (10.0**10)**2) # kg m^2 inertia = max(inertias) # should be two identical and one zero S_r = (8 * np.pi**2 * inertia * units._k * temperature / self.sigma / units._hplanck**2) S_r = units.kB * (np.log(S_r) + 1.) write(fmt % ('S_rot', S_r, S_r * temperature)) S += S_r # Electronic entropy. S_e = units.kB * np.log(2 * self.spin + 1) write(fmt % ('S_elec', S_e, S_e * temperature)) S += S_e # Vibrational entropy. S_v = self._vibrational_entropy_contribution(temperature) write(fmt % ('S_vib', S_v, S_v * temperature)) S += S_v # Pressure correction to translational entropy. S_p = - units.kB * np.log(pressure / self.referencepressure) write(fmt % ('S (1 atm -> P)', S_p, S_p * temperature)) S += S_p write('-' * 49) write(fmt % ('S', S, S * temperature)) write('=' * 49) return S def get_gibbs_energy(self, temperature, pressure, verbose=True): """Returns the Gibbs free energy, in eV, in the ideal gas approximation at a specified temperature (K) and pressure (Pa).""" self.verbose = verbose write = self._vprint H = self.get_enthalpy(temperature, verbose=verbose) write('') S = self.get_entropy(temperature, pressure, verbose=verbose) G = H - temperature * S write('') write('Free energy components at T = %.2f K and P = %.1f Pa:' % (temperature, pressure)) write('=' * 23) fmt = '%5s%15.3f eV' write(fmt % ('H', H)) write(fmt % ('-T*S', -temperature * S)) write('-' * 23) write(fmt % ('G', G)) write('=' * 23) return G class CrystalThermo(ThermoChem): """Class for calculating thermodynamic properties of a crystalline solid in the approximation that a lattice of N atoms behaves as a system of 3N independent harmonic oscillators. Inputs: phonon_DOS : list a list of the phonon density of states, where each value represents the phonon DOS at the vibrational energy value of the corresponding index in phonon_energies. phonon_energies : list a list of the range of vibrational energies (hbar*omega) over which the phonon density of states has been evaluated. This list should be the same length as phonon_DOS and integrating phonon_DOS over phonon_energies should yield approximately 3N, where N is the number of atoms per unit cell. If the first element of this list is zero-valued it will be deleted along with the first element of phonon_DOS. Units of vibrational energies are eV. electronicenergy : float the electronic energy in eV (if electronicenergy is unspecified, then the methods of this class can be interpreted as the phonon energy corrections.) formula_units : int the number of formula units per unit cell. If unspecified, the thermodynamic quantities calculated will be listed on a per-unit-cell basis. """ def __init__(self, phonon_DOS, phonon_energies, formula_units=None, electronicenergy=None): self.phonon_energies = phonon_energies self.phonon_DOS = phonon_DOS if formula_units: self.formula_units = formula_units if electronicenergy: self.electronicenergy = electronicenergy / formula_units else: self. electronicenergy = electronicenergy else: self.formula_units = 0 if electronicenergy: self.electronicenergy = electronicenergy else: self.electronicenergy = 0 def get_internal_energy(self, temperature, verbose=True): """Returns the internal energy, in eV, of crystalline solid at a specified temperature (K).""" self.verbose = verbose write = self._vprint fmt = '%-15s%13.4f eV' if self.formula_units == 0: write('Internal energy components at ' 'T = %.2f K,\non a per-unit-cell basis:' % temperature) else: write('Internal energy components at ' 'T = %.2f K,\non a per-formula-unit basis:' % temperature) write('=' * 31) U = 0. omega_e = self.phonon_energies dos_e = self.phonon_DOS if omega_e[0] == 0.: omega_e = np.delete(omega_e, 0) dos_e = np.delete(dos_e, 0) write(fmt % ('E_elec', self.electronicenergy)) U += self.electronicenergy zpe_list = omega_e / 2. if self.formula_units == 0: zpe = np.trapz(zpe_list * dos_e, omega_e) else: zpe = np.trapz(zpe_list * dos_e, omega_e) / self.formula_units write(fmt % ('E_ZPE', zpe)) U += zpe B = 1. / (units.kB * temperature) E_vib = omega_e / (np.exp(omega_e * B) - 1.) if self.formula_units == 0: E_phonon = np.trapz(E_vib * dos_e, omega_e) else: E_phonon = np.trapz(E_vib * dos_e, omega_e) / self.formula_units write(fmt % ('E_phonon', E_phonon)) U += E_phonon write('-' * 31) write(fmt % ('U', U)) write('=' * 31) return U def get_entropy(self, temperature, verbose=True): """Returns the entropy, in eV/K, of crystalline solid at a specified temperature (K).""" self.verbose = verbose write = self._vprint fmt = '%-15s%13.7f eV/K%13.4f eV' if self.formula_units == 0: write('Entropy components at ' 'T = %.2f K,\non a per-unit-cell basis:' % temperature) else: write('Entropy components at ' 'T = %.2f K,\non a per-formula-unit basis:' % temperature) write('=' * 49) write('%15s%13s %13s' % ('', 'S', 'T*S')) omega_e = self.phonon_energies dos_e = self.phonon_DOS if omega_e[0] == 0.: omega_e = np.delete(omega_e, 0) dos_e = np.delete(dos_e, 0) B = 1. / (units.kB * temperature) S_vib = (omega_e / (temperature * (np.exp(omega_e * B) - 1.)) - units.kB * np.log(1. - np.exp(-omega_e * B))) if self.formula_units == 0: S = np.trapz(S_vib * dos_e, omega_e) else: S = np.trapz(S_vib * dos_e, omega_e) / self.formula_units write('-' * 49) write(fmt % ('S', S, S * temperature)) write('=' * 49) return S def get_helmholtz_energy(self, temperature, verbose=True): """Returns the Helmholtz free energy, in eV, of crystalline solid at a specified temperature (K).""" self.verbose = True write = self._vprint U = self.get_internal_energy(temperature, verbose=verbose) write('') S = self.get_entropy(temperature, verbose=verbose) F = U - temperature * S write('') if self.formula_units == 0: write('Helmholtz free energy components at ' 'T = %.2f K,\non a per-unit-cell basis:' % temperature) else: write('Helmholtz free energy components at ' 'T = %.2f K,\non a per-formula-unit basis:' % temperature) write('=' * 23) fmt = '%5s%15.4f eV' write(fmt % ('U', U)) write(fmt % ('-T*S', -temperature * S)) write('-' * 23) write(fmt % ('F', F)) write('=' * 23) return F python-ase-3.9.1.4567/ase/__init__.py0000664000175000017500000000062012553425526017355 0ustar jensjjensj00000000000000# Copyright 2008, 2009 CAMd # (see accompanying license files for details). """Atomic Simulation Environment.""" __all__ = ['Atoms', 'Atom'] from ase.atom import Atom from ase.atoms import Atoms import numpy as np if np.version.version < '1.9': # Make isinstance(x, numbers.Integral) work also for np.intxx: import numbers numbers.Integral.register(np.integer) del numbers del np python-ase-3.9.1.4567/ase/visualize/0000775000175000017500000000000012553427753017265 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/visualize/__init__.py0000664000175000017500000000327712553425526021403 0ustar jensjjensj00000000000000import os import tempfile from ase.io import write import ase.parallel as parallel def view(atoms, data=None, viewer='ase-gui', repeat=None, block=False): # Ignore for parallel calculations: if parallel.size != 1: return vwr = viewer.lower() if vwr == 'ase-gui': format = 'traj' if repeat is None: command = 'ase-gui' else: command = 'ase-gui --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-') if repeat is not None: atoms = atoms.repeat() if data is None: write(filename, atoms, format=format) else: write(filename, atoms, format=format, data=data) if block: os.system('%s %s' % (command, filename)) os.remove(filename) else: if os.name in ['ce', 'nt']: # Win # XXX: how to make it non-blocking? os.system('%s %s' % (command, filename)) os.remove(filename) else: os.system('%s %s & ' % (command, filename)) os.system('(sleep 60; rm %s) &' % filename) python-ase-3.9.1.4567/ase/visualize/sage.py0000664000175000017500000000143312553425526020553 0ustar jensjjensj00000000000000from 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.9.1.4567/ase/visualize/colortable.py0000664000175000017500000011520612553425526021766 0ustar jensjjensj00000000000000"""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 isinstance(infile, type("string")): infile = open(infile) if outfile is None: outfile = sys.stdout if isinstance(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.9.1.4567/ase/visualize/mlab.py0000664000175000017500000001016612553425526020552 0ustar jensjjensj00000000000000from __future__ import print_function import optparse import numpy as np from ase.data import covalent_radii from ase.io.cube import read_cube_data from ase.data.colors import cpk_colors from ase.calculators.calculator import get_calculator def plot(atoms, data, contours): """Plot atoms, unit-cell and iso-surfaces using Mayavi. Parameters: atoms: Atoms object Positions, atomiz numbers and unit-cell. data: 3-d ndarray of float Data for iso-surfaces. countours: list of float Contour values. """ # Delay slow imports: from mayavi import mlab mlab.figure(1, bgcolor=(1, 1, 1)) # make a white figure # Plot the atoms as spheres: for pos, Z in zip(atoms.positions, atoms.numbers): mlab.points3d(*pos, scale_factor=covalent_radii[Z], resolution=20, color=tuple(cpk_colors[Z])) # Draw the unit cell: A = atoms.cell for i1, a in enumerate(A): i2 = (i1 + 1) % 3 i3 = (i1 + 2) % 3 for b in [np.zeros(3), A[i2]]: for c in [np.zeros(3), A[i3]]: p1 = b + c p2 = p1 + a mlab.plot3d([p1[0], p2[0]], [p1[1], p2[1]], [p1[2], p2[2]], tube_radius=0.1) cp = mlab.contour3d(data, contours=contours, transparent=True, opacity=0.5, colormap='hot') # Do some tvtk magic in order to allow for non-orthogonal unit cells: polydata = cp.actor.actors[0].mapper.input pts = np.array(polydata.points) - 1 # Transform the points to the unit cell: polydata.points = np.dot(pts, A / np.array(data.shape)[:, np.newaxis]) # Apparently we need this to redraw the figure, maybe it can be done in # another way? mlab.view(azimuth=155, elevation=70, distance='auto') # Show the 3d plot: mlab.show() description = """\ Plot iso-surfaces from a cube-file or a wave function or an electron density from a calculator-restart file.""" def main(args=None): parser = optparse.OptionParser(usage='%prog [options] filename', description=description) add = parser.add_option add('-n', '--band-index', type=int, metavar='INDEX', help='Band index counting from zero.') add('-s', '--spin-index', type=int, metavar='SPIN', help='Spin index: zero or one.') add('-c', '--contours', default='4', help='Use "-c 3" for 3 contours or "-c -0.5,0.5" for specific ' + 'values. Default is four contours.') add('-r', '--repeat', help='Example: "-r 2,2,2".') add('-C', '--calculator-name', metavar='NAME', help='Name of calculator.') opts, args = parser.parse_args(args) if len(args) != 1: parser.error('Incorrect number of arguments') arg = args[0] if arg.endswith('.cube'): data, atoms = read_cube_data(arg) else: calc = get_calculator(opts.calculator_name)(arg, txt=None) atoms = calc.get_atoms() if opts.band_index is None: data = calc.get_pseudo_density(opts.spin_index) else: data = calc.get_pseudo_wave_function(opts.band_index, opts.spin_index or 0) if data.dtype == complex: data = abs(data) mn = data.min() mx = data.max() print('Min: %16.6f' % mn) print('Max: %16.6f' % mx) if opts.contours.isdigit(): n = int(opts.contours) d = (mx - mn) / n contours = np.linspace(mn + d / 2, mx - d / 2, n).tolist() else: contours = [float(x) for x in opts.contours.split(',')] if len(contours) == 1: print('1 contour:', contours[0]) else: print('%d contours: %.6f, ..., %.6f' % (len(contours), contours[0], contours[-1])) if opts.repeat: repeat = [int(r) for r in opts.repeat.split(',')] data = np.tile(data, repeat) atoms *= repeat plot(atoms, data, contours) if __name__ == '__main__': main() python-ase-3.9.1.4567/ase/visualize/fieldplotter.py0000664000175000017500000002563112553425526022337 0ustar jensjjensj00000000000000from __future__ import print_function """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 range(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.9.1.4567/ase/visualize/vtk/0000775000175000017500000000000012553427753020071 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/visualize/vtk/__init__.py0000664000175000017500000000207612553425526022203 0ustar jensjjensj00000000000000try: 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.9.1.4567/ase/visualize/vtk/volume.py0000664000175000017500000000452312553425526021752 0ustar jensjjensj00000000000000 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.9.1.4567/ase/visualize/vtk/pipeline.py0000664000175000017500000001546412553425526022256 0ustar jensjjensj00000000000000from __future__ import print_function 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): for f in vtkish_filters: self.append(f) 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.9.1.4567/ase/visualize/vtk/sources.py0000664000175000017500000000754112553425526022131 0ustar jensjjensj00000000000000 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.9.1.4567/ase/visualize/vtk/data.py0000664000175000017500000001617512553425526021362 0ustar jensjjensj00000000000000 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.9.1.4567/ase/visualize/vtk/cell.py0000664000175000017500000000774312553425526021371 0ustar jensjjensj00000000000000 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(list(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(list(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.9.1.4567/ase/visualize/vtk/atoms.py0000664000175000017500000001117212553425526021564 0ustar jensjjensj00000000000000 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.9.1.4567/ase/visualize/vtk/module.py0000664000175000017500000001746112553425526021735 0ustar jensjjensj00000000000000 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.9.1.4567/ase/visualize/vtk/grid.py0000664000175000017500000002551512553425526021374 0ustar jensjjensj00000000000000 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.9.1.4567/ase/visualize/primiplotter.py0000664000175000017500000010540512553425526022372 0ustar jensjjensj00000000000000from __future__ import print_function """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 import collections 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. The colors can either be a dictionary mapping tags to colors or an array of colors, one per atom. Each color is specified as a greyscale value from 0.0 to 1.0 or as three RGB values from 0.0 to 1.0. """ self.colors = colors def set_color_function(self, colors): """Set a color function, to be used to color the atoms.""" if isinstance(colors, collections.Callable): 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 isinstance(invfunc, collections.Callable): 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 isinstance(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 isinstance(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): "Attach an output device to the plotter." 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: ").with_traceback(+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 range(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): PrimiPlotter.__init__(self, *args, **kwargs) self.isparallel = 1 import ase.parallel self.mpi = ase.parallel.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.get_ghost_positions() self.numberofrealatoms = len(realpos) self.numberofghostatoms = len(ghostpos) return concatenate((realpos, ghostpos)) def _getatomicnumbers(self): realz = self.atoms.get_atomic_numbers() ghostz = self.atoms.get_ghost_atomic_numbers() 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]) self.mpi.max(maximal) self.mpi.min(minimal) maxx, maxy = maximal minx, miny = minimal 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)]) self.mpi.max(maximal) self.mpi.min(minimal) maxx, maxy, maxradius = maximal minx, miny = minimal 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.get_ghost_positions()) newcolshape = (nghost + col.shape[0],) + col.shape[1:] newcol = zeros(newcolshape, col.dtype) 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 ncolmax = self.mpi.max(ncol) 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), 4+ncol), float) data[:,:3] = coords data[:,3] = radii if ncol == 1: data[:,4] = colors else: data[:,4:] = colors if not self.master: datashape = array(data.shape) assert datashape.shape == (2,) self.mpi.send(datashape, 0, self.mpitag) self.mpi.send(data, 0, self.mpitag) else: total = [data] n = len(coords) colsmin = colsmax = 4+ncol for proc in range(1, self.mpi.size): self._verb("Receiving from processor "+str(proc)) datashape = zeros(2, int) self.mpi.receive(datashape, proc, self.mpitag) fdat = zeros(tuple(datashape)) self.mpi.receive(fdat, proc, self.mpitag) 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") 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") 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 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(isinstance(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 isinstance(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 range(len(cls)): colors[i] = dict[cls[i]] return colors python-ase-3.9.1.4567/ase/lattice/0000775000175000017500000000000012553427753016677 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/lattice/__init__.py0000664000175000017500000000004212553425527021001 0ustar jensjjensj00000000000000from ase.lattice.bulk import bulk python-ase-3.9.1.4567/ase/lattice/orthorhombic.py0000664000175000017500000001253312553425527021751 0ustar jensjjensj00000000000000from __future__ import print_function """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 isinstance(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.9.1.4567/ase/lattice/cubic.py0000664000175000017500000001062712553425527020341 0ustar jensjjensj00000000000000from __future__ import print_function """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], end=' ') 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.9.1.4567/ase/lattice/compounds.py0000664000175000017500000001574212553425527021266 0ustar jensjjensj00000000000000"""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.9.1.4567/ase/lattice/bulk.py0000664000175000017500000001752012553425527020210 0ustar jensjjensj00000000000000from __future__ import division 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, u=None, orthorhombic=False, cubic=False): """Creating bulk systems. Crystal structure and lattice constant(s) will be guessed if not provided. name: str Chemical symbol or symbols as in 'MgO' or 'NaCl'. crystalstructure: str Must be one of sc, fcc, bcc, hcp, diamond, zincblende, rocksalt, cesiumchloride, fluorite or wurtzite. a: float Lattice constant. c: float Lattice constant. covera: float c/a raitio used for hcp. Default is ideal ratio: sqrt(8/3). u: float Internal coordinate for Wurtzite structure. orthorhombic: bool Construct orthorhombic unit cell instead of primitive cell which is the default. cubic: bool Construct cubic unit cell if possible. """ if covera is not None and c is not None: raise ValueError("Don't specify both c and c/a!") xref = None if name in chemical_symbols: Z = atomic_numbers[name] ref = reference_states[Z] if ref is not None: xref = ref['symmetry'] if crystalstructure is None: crystalstructure = xref if a is None: if xref != crystalstructure: raise ValueError('You need to specify the lattice constant.') a = ref['a'] if crystalstructure in ['hcp', 'wurtzite']: cubic = False if c is not None: covera = c / a elif covera is None: if xref == crystalstructure: covera = ref['c/a'] else: covera = sqrt(8 / 3) if orthorhombic and crystalstructure != 'sc': return _orthorhombic_bulk(name, crystalstructure, a, covera, u) if cubic and crystalstructure in ['bcc', 'cesiumchloride']: 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 / 3, 2 / 3, 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 elif crystalstructure == 'cesiumchloride': s1, s2 = string2symbols(name) atoms = bulk(s1, 'sc', a) + bulk(s2, 'sc', a) atoms.positions[1, :] += a / 2 elif crystalstructure == 'fluorite': s1, s2, s3 = string2symbols(name) atoms = bulk(s1, 'fcc', a) + bulk(s2, 'fcc', a) + bulk(s3, 'fcc', a) atoms.positions[1, :] += a / 4 atoms.positions[2, :] += a * 3 / 4 elif crystalstructure == 'wurtzite': u = u or 0.25 + 1 / 3 / covera**2 atoms = Atoms(2 * name, scaled_positions=[(0, 0, 0), (1 / 3, 2 / 3, 0.5 - u), (1 / 3, 2 / 3, 0.5), (0, 0, 1 - u)], cell=[(a, 0, 0), (-a / 2, a * sqrt(3) / 2, 0), (0, 0, a * covera)], pbc=True) else: raise ValueError('Unknown crystal structure: ' + crystalstructure) return atoms def _orthorhombic_bulk(name, crystalstructure, a, covera=None, u=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 / 6, 0.5), (0, 2 / 3, 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)]) elif crystalstructure == 'cesiumchloride': atoms = Atoms(name, cell=(a, a, a), pbc=True, scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)]) elif crystalstructure == 'wurtzite': u = u or 0.25 + 1 / 3 / covera**2 atoms = Atoms(4 * name, cell=(a, a * 3**0.5, covera * a), scaled_positions = [(0, 0, 0), (0, 1 / 3, 0.5 - u), (0, 1 / 3, 0.5), (0, 0, 1 - u), (0.5, 0.5, 0), (0.5, 5 / 6, 0.5 - u), (0.5, 5 / 6, 0.5), (0.5, 0.5, 1 - u)], pbc=True) 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.9.1.4567/ase/lattice/bravais.py0000664000175000017500000004443012553425527020702 0ustar jensjjensj00000000000000from __future__ import print_function """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 range(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 range(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 range(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.9.1.4567/ase/lattice/general_surface.py0000664000175000017500000000662112553425527022400 0ustar jensjjensj00000000000000import 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. Note that the unit-cell must be the conventional cell - not the primitive cell. 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 = [(0, 0, 1), (1, 0, 0), (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.9.1.4567/ase/lattice/surface.py0000664000175000017500000004634712553425527020714 0ustar jensjjensj00000000000000"""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 __future__ import division from math import sqrt, hypot, acos from operator import itemgetter 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.cubic import FaceCenteredCubic from ase.lattice.general_surface import surface __all__ = ['surface', 'add_adsorbate', 'add_vacuum', 'bcc100', 'bcc110', 'bcc111', 'diamond100', 'diamond111', 'fcc100', 'fcc110', 'fcc111', 'fcc211', 'hcp0001', 'hcp10m10', 'mx2'] 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: # Assume it is a string representing a single Atom ads = Atoms([Atom(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 add_vacuum(atoms, vacuum): """Add vacuum layer to the atoms. Parameters: atoms: An Atoms object most likely created by one of the ase.lattice modules. vacuum: The thickness of the vacuum layer (in Angstrom). """ uc = atoms.get_cell() normal = np.cross(uc[0], uc[1]) costheta = np.dot(normal, uc[2]) / np.sqrt(np.dot(normal, normal) * np.dot(uc[2], uc[2])) length = np.sqrt(np.dot(uc[2], uc[2])) newlength = length + vacuum / costheta uc[2] *= newlength / length atoms.set_cell(uc) 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 def fcc211(symbol, size, a=None, vacuum=None, orthogonal=True): """FCC(211) surface. Does not currently support special adsorption sites. Currently only implemented for *orthogonal=True* with size specified as (i, j, k), where i, j, and k are number of atoms in each direction. i must be divisible by 3 to accomodate the step width. """ if not orthogonal: raise NotImplementedError('Only implemented for orthogonal ' 'unit cells.') if size[0] % 3 != 0: raise NotImplementedError('First dimension of size must be ' 'divisible by 3.') atoms = FaceCenteredCubic(symbol, directions=[[1, -1, -1], [0, 2, -2], [2, 1, 1]], miller=(None, None, (2, 1, 1)), latticeconstant=a, size=(1, 1, 1), pbc=True) z = (size[2] + 1) // 2 atoms = atoms.repeat((size[0] // 3, size[1], z)) if size[2] % 2: # Odd: remove bottom layer and shrink cell. remove_list = [atom.index for atom in atoms if atom.z < atoms[1].z] del atoms[remove_list] dz = atoms[0].z atoms.translate((0., 0., -dz)) atoms.cell[2][2] -= dz atoms.center(vacuum=vacuum, axis=2) # Renumber systematically from top down. orders = [(atom.index, round(atom.x, 3), round(atom.y, 3), -round(atom.z, 3), atom.index) for atom in atoms] orders.sort(key=itemgetter(3, 1, 2)) newatoms = atoms.copy() for index, order in enumerate(orders): newatoms[index].position = atoms[order[0]].position.copy() return newatoms def fcc111_root(symbol, root, size, a=None, vacuum=0.0, orthogonal=False, search_zone=(20, 20)): """FCC(111) surface maniupulated to repeat with *root* number of atoms in each x/y plane. The cell is generated as a rotated 60-120-60-120 cell in the x/y plane. The rotation and size is chosen to allow for the length of the cell vectors to be equal to the root of *root* with a lattice constant of 2**0.5. *root* should be given as a positive whole number.""" atomic_number = atomic_numbers[symbol] if orthogonal: raise NotImplementedError('Only implemented for orthogonal ' 'unit cells.') if a is None: if reference_states[atomic_number]['symmetry'] == 'fcc': a = reference_states[atomic_number]['a'] else: raise ValueError("Can't guess lattice constant for %s-%s!" % ('fcc', symbol)) searchx, searchy = search_zone c = 0.5 s = (3**0.5) / 2. def rhomb(x, y): return float(x + (c * y)), float(s * y) desired = root**0.5 location = None locations = [] for iy in range(searchy): for ix in range(searchx): x, y = rhomb(ix, iy) locations.append([x, y]) distances = np.sqrt((np.array(locations)**2).sum(1)) for index, dist in enumerate(distances): if abs(dist - desired) <= 1e-13: location = locations[index] if location is None: raise ValueError( "Can't find a root cell in the searched zone of size \ (%d, %d). A larger zone may be needed for large root values" % search_zone) angle = acos(location[0] / desired) cutting_board = fcc111(symbol, (searchx, searchy, size[2]), a=2**0.5) cutting_board.translate((-searchx, 0, 0)) cutting_board += fcc111(symbol, (searchx, searchy, size[2]), a=2**0.5) cutting_board.rotate('z', -angle) cutting_board.set_cell(((desired, 0, 0), (desired / 2, desired * ((3**0.5) / 2), 0), (0, 0, 2**0.5 * size[2])), scale_atoms=False) cell = cutting_board.get_cell() remove = [] for index, position in enumerate(cutting_board.positions): if not (0 < position[0] < (cell[0][0] + cell[1][0])): remove.append(index) if not (0 < position[1] < cell[1][1]): remove.append(index) del cutting_board[remove] def remove_doubles(): scaled = cutting_board.get_scaled_positions() remove = [] for index, position in enumerate(scaled): for inner_index in range(index): inner_position = scaled[inner_index] if hypot(position[0] - inner_position[0], position[1] - inner_position[1]) < 1e-10: remove.append(index) del cutting_board[remove] cutting_board.set_scaled_positions( cutting_board.get_scaled_positions()) remove_doubles() cutting_board.translate((0.1, 0.1, 0)) remove_doubles() cell *= a / (2 ** (0.5)) cutting_board.set_cell(cell, scale_atoms=True) cutting_board.adsorbate_info = {} cutting_board *= (size[0], size[1], 1) cutting_board.center(axis=2, vacuum=vacuum) return cutting_board def mx2(formula='MoS2', kind='2H', a=3.18, thickness=3.19, size=(1, 1, 1), vacuum=7.5): """Create three-layer 2D materials with hexagonal structure. For metal dichalcogenites, ect. The kind argument accepts '2H', which gives a mirror plane symmetry and '1T', which gives an inversion symmetry.""" if kind == '2H': basis = [(0, 0, 0), (2 / 3, 1 / 3, 0.5 * thickness), (2 / 3, 1 / 3, -0.5 * thickness)] elif kind == '1T': basis = [(0, 0, 0), (2 / 3, 1 / 3, 0.5 * thickness), (1 / 3, 2 / 3, -0.5 * thickness)] else: raise ValueError('Structure not recognized') cell = [[a, 0, 0], [-a / 2, a * 3**0.5 / 2, 0], [0, 0, 1]] atoms = Atoms(formula, cell=cell, scaled_positions=basis, pbc=(1, 1, 0)) atoms.center(vacuum=vacuum, axis=2) return atoms python-ase-3.9.1.4567/ase/lattice/triclinic.py0000664000175000017500000000622212553425527021230 0ustar jensjjensj00000000000000"""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 isinstance(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.9.1.4567/ase/lattice/tetragonal.py0000664000175000017500000000266212553425527021414 0ustar jensjjensj00000000000000"""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 isinstance(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.9.1.4567/ase/lattice/hexagonal.py0000664000175000017500000000766012553425527021225 0ustar jensjjensj00000000000000from __future__ import print_function """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 isinstance(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.9.1.4567/ase/lattice/monoclinic.py0000664000175000017500000000322212553425527021377 0ustar jensjjensj00000000000000"""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 isinstance(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.9.1.4567/ase/lattice/spacegroup/0000775000175000017500000000000012553427753021047 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/lattice/spacegroup/__init__.py0000664000175000017500000000014512553425527023155 0ustar jensjjensj00000000000000from .spacegroup import Spacegroup from .crystal import crystal __all__ = ['Spacegroup', 'crystal'] python-ase-3.9.1.4567/ase/lattice/spacegroup/findsym.py0000664000175000017500000002023212553425527023066 0ustar jensjjensj00000000000000from __future__ import print_function # Copyright (C) 2012, Jesper Friis # (see accompanying license files for ASE). """ Determines space group of an atoms object using the FINDSYM program from the ISOTROPY (http://stokes.byu.edu/iso/isotropy.html) software package by H. T. Stokes and D. M. Hatch, Brigham Young University, USA. In order to use this module, you have to download the ISOTROPY package from http://stokes.byu.edu/iso/isotropy.html and set the environment variable ISODATA to the path of the directory containing findsym and data_space.txt (NB: the path should end with a slash (/)). Example ------- >>> from ase.lattice.spacegroup import crystal >>> from ase.utils.geometry import cut # Start with simple fcc Al >>> al = crystal('Al', [(0,0,0)], spacegroup=225, cellpar=4.05) >>> d = findsym(al) >>> d['spacegroup'] 225 # No problem with a more complex structure... >>> skutterudite = crystal(('Co', 'Sb'), ... basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)], ... spacegroup=204, ... cellpar=9.04) >>> d = findsym(skutterudite) >>> d['spacegroup'] 204 # ... or a non-conventional cut slab = cut(skutterudite, a=(1, 1, 0), b=(0, 2, 0), c=(0, 0, 1)) d = findsym(slab) >>> d['spacegroup'] 204 """ import os import subprocess import numpy as np import ase __all__ = ['findsym', 'unique'] def make_input(atoms, tol=1e-3, centering='P', types=None): """Returns input to findsym. See findsym() for a description of the arguments.""" if types is None: types = atoms.numbers s = [] s.append(atoms.get_chemical_formula()) s.append('%g tolerance' % tol) s.append('2 form of lattice parameters: to be entered as lengths ' 'and angles') s.append('%g %g %g %g %g %g a,b,c,alpha,beta,gamma' % tuple(ase.lattice.spacegroup.cell.cell_to_cellpar(atoms.cell))) s.append('2 form of vectors defining unit cell') # ?? s.append('%s centering (P=unknown)' % centering) s.append('%d number of atoms in primitive unit cell' % len(atoms)) s.append(' '.join(str(n) for n in types) + ' type of each atom') for p in atoms.get_scaled_positions(): s.append('%10.5f %10.5f %10.5f' % tuple(p)) return '\n'.join(s) def run(atoms, tol=1e-3, centering='P', types=None, isodata_dir=None): """Runs FINDSYM and returns its standard output.""" if isodata_dir is None: isodata_dir = os.getenv('ISODATA') if isodata_dir is None: isodata_dir = '.' isodata_dir = os.path.normpath(isodata_dir) findsym = os.path.join(isodata_dir, 'findsym') data_space = os.path.join(isodata_dir, 'data_space.txt') for path in findsym, data_space: if not os.path.exists(path): raise IOError('no such file: %s. Have you set the ISODATA ' 'environment variable to the directory containing ' 'findsym and data_space.txt?' % path) env = os.environ.copy() env['ISODATA'] = isodata_dir + os.sep p = subprocess.Popen([findsym], stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=env) stdout = p.communicate(make_input(atoms, tol, centering, types))[0] # if os.path.exists('findsym.log'): # os.remove('findsym.log') return stdout def parse(output): """Parse output from FINDSYM (Version 3.2.3, August 2007) and return a dict. See docstring for findsym() for a description of the tokens.""" d = {} lines = output.splitlines() def search_for_line(line_str): check_line = [i for i, line in enumerate(lines) if line.startswith(line_str)] return check_line i_cellpar = search_for_line('Lattice parameters')[0] d['cellpar'] = np.array([float(v) for v in lines[i_cellpar + 1].split()]) i_natoms = search_for_line('Number of atoms in unit cell')[0] natoms = int(lines[i_natoms + 1].split()[0]) # Determine number of atoms from atom types, since the number of # atoms is written with only 3 digits, which crashes the parser # for more than 999 atoms i_spg = search_for_line('Space Group')[0] tokens = lines[i_spg].split() d['spacegroup'] = int(tokens[2]) # d['symbol_nonconventional'] = tokens[3] d['symbol'] = tokens[4] i_origin = search_for_line('Origin at')[0] d['origin'] = np.array([float(v) for v in lines[i_origin].split()[2:]]) i_abc = search_for_line('Vectors a,b,c')[0] d['abc'] = np.array([[float(v) for v in line.split()] for line in lines[i_abc + 1:i_abc + 4]]).T i_wyck_start = search_for_line('Wyckoff position') d['wyckoff'] = [] d['tags'] = -np.ones(natoms, dtype=int) i_wyck_stop = i_wyck_start[1:] i_wyck_stop += [i_wyck_start[0] + natoms + 3] # sort the tags to the indivual atoms for tag, (i_start, i_stop) in enumerate(zip(i_wyck_start, i_wyck_stop)): tokens = lines[i_start].split() d['wyckoff'].append(tokens[2].rstrip(',')) i_tag = [int(line.split()[0]) - 1 for line in lines[i_start + 1:i_stop]] d['tags'][i_tag] = tag return d def findsym(atoms, tol=1e-3, centering='P', types=None, isodata_dir=None): """Returns a dict describing the symmetry of *atoms*. Arguments --------- atoms: Atoms instance Atoms instance to find space group of. tol: float Accuracy to which dimensions of the unit cell and positions of atoms are known. Units in Angstrom. centering: 'P' | 'I' | 'F' | 'A' | 'B' | 'C' | 'R' Known centering: P (no known centering), I (body-centered), F (face-centered), A,B,C (base centered), R (rhombohedral centered with coordinates of centered points at (2/3,1/3,1/3) and (1/3,2/3,2/3)). types: None | sequence of integers Sequence of arbitrary positive integers identifying different atomic sites, so that a symmetry operation that takes one atom into another with different type would be forbidden. Returned dict items ------------------- abc: 3x3 float array The vectors a, b, c defining the cell in scaled coordinates. cellpar: 6 floats Cell parameters a, b, c, alpha, beta, gamma with lengths in Angstrom and angles in degree. origin: 3 floats Origin of the space group with respect to the origin in the input data. Coordinates are dimensionless, given in terms of the lattice parameters of the unit cell in the input. spacegroup: int Space group number from the International Tables of Crystallography. symbol: str Hermann-Mauguin symbol (no spaces). tags: int array Array of site numbers for each atom. Only atoms within the first conventional unit cell are tagged, the rest have -1 as tag. wyckoff: list List of wyckoff symbols for each site. """ output = run(atoms, tol, centering, types, isodata_dir) d = parse(output) return d def unique(atoms, tol=1e-3, centering='P', types=None, isodata_dir=None): """Returns an Atoms object containing only one atom from each unique site. """ d = findsym(atoms, tol=tol, centering=centering, types=types, isodata_dir=isodata_dir) mask = np.concatenate(([True], np.diff(d['tags']) != 0)) * (d['tags'] >= 0) at = atoms[mask] a, b, c, alpha, beta, gamma = d['cellpar'] A, B, C = d['abc'] A *= a B *= b C *= c from numpy.linalg import norm from numpy import cos, pi assert abs(np.dot(A, B) - (norm(A) * norm(B) * cos(gamma * pi / 180.))) < 1e-5 assert abs(np.dot(A, C) - (norm(A) * norm(C) * cos(beta * pi / 180.))) < 1e-5 assert abs(np.dot(B, C) - (norm(B) * norm(C) * cos(alpha * pi / 180.))) < 1e-5 at.cell = np.array([A, B, C]) for k in 'origin', 'spacegroup', 'wyckoff': at.info[k] = d[k] at.info['unit_cell'] = 'unique' scaled = at.get_scaled_positions() at.set_scaled_positions(scaled) return at if __name__ == '__main__': import doctest print('doctest:', doctest.testmod()) python-ase-3.9.1.4567/ase/lattice/spacegroup/spacegroup.py0000664000175000017500000006457612553425527023610 0ustar jensjjensj00000000000000from __future__ import print_function # 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__.items(): 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 todict(self): return {'number': self.no, 'setting': 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 __cmp__(self, other): """Compares *self* with *other* by number and setting.""" if self.no > other.no: return 1 elif self.no < other.no: return -1 elif self.setting > other.setting: return 1 elif self.setting < other.setting: return -1 else: return 0 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.tile(np.vstack((self.translations, -self.translations)), (self.nsubtrans, 1)) trans += np.repeat(self.subtrans, 2 * len(self.rotations), axis=0) trans = np.mod(trans, 1) else: rot = np.tile(self.rotations, (self.nsubtrans, 1, 1)) trans = np.tile(self.translations, (self.nsubtrans, 1)) trans += np.repeat(self.subtrans, len(self.rotations), axis=0) trans = np.mod(trans, 1) 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 = [] 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.all((abs(t) < symprec) | (abs(abs(t) - 1.0) < symprec), axis=1) 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, map_to_unitcell=True): """Returns an array of same size as *scaled_positions*, containing the corresponding symmetry-equivalent sites of lowest indices. If *map_to_unitcell* is true, the returned positions are all mapped into the unit cell, i.e. lattice translations are included as symmetry operator. 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 if map_to_unitcell: # 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, map_to_unitcell=True): """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. If *map_to_unitcell* is true, all sites are first mapped into the unit cell making e.g. [0, 0, 0] and [1, 0, 0] equivalent. 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, map_to_unitcell) 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(): if len(fixed) and fixed[-1] == '/': fixed.append(c) else: 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([[float(s) for s in f.readline().split()] for i in range(3)], dtype=np.float) # primitive reciprocal vectors f.readline() spg._reciprocal_cell = np.array([[int(i) for i in f.readline().split()] for i in range(3)], dtype=np.int) # subtranslations spg._nsubtrans = int(f.readline().split()[0]) spg._subtrans = np.array([[float(t) for t in f.readline().split()] for i in range(spg._nsubtrans)], dtype=np.float) # symmetry operations nsym = int(f.readline().split()[0]) symop = np.array([[float(s) for s in 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, str): #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, str) 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. from . import spacegroup import doctest print('doctest: ', doctest.testmod()) python-ase-3.9.1.4567/ase/lattice/spacegroup/cell.py0000664000175000017500000000662212553425527022343 0ustar jensjjensj00000000000000from __future__ import print_function # 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, 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.9.1.4567/ase/lattice/spacegroup/spacegroup.dat0000664000175000017500000112027312553425527023714 0ustar jensjjensj000000000000001 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.9.1.4567/ase/lattice/spacegroup/crystal.py0000664000175000017500000001370412553425527023104 0ustar jensjjensj00000000000000from __future__ import print_function # 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, str): symbols = string2symbols(symbols) return symbols #----------------------------------------------------------------- # Self test if __name__ == '__main__': import doctest print('doctest: ', doctest.testmod()) python-ase-3.9.1.4567/ase/cluster/0000775000175000017500000000000012553427753016733 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/cluster/factory.py0000664000175000017500000002106412553425526020753 0ustar jensjjensj00000000000000from __future__ import print_function 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 Cluster = Cluster # Make it possible to change the class of the object returned. 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 self.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.9.1.4567/ase/cluster/cluster.py0000664000175000017500000001002512553425526020760 0ustar jensjjensj00000000000000import os import math import numpy as np import pickle from ase import Atoms 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 self.surfaces is not 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 Warning('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.9.1.4567/ase/cluster/__init__.py0000664000175000017500000000067212553425526021045 0ustar jensjjensj00000000000000"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.9.1.4567/ase/cluster/cubic.py0000664000175000017500000000335612553425526020375 0ustar jensjjensj00000000000000""" 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." % (self.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): spacegroup = 229 xtal_name = 'bcc' atomic_basis = np.array([[0., 0., 0.], [.5, .5, .5]]) BodyCenteredCubic = BodyCenteredCubicFactory() class FaceCenteredCubicFactory(SimpleCubicFactory): spacegroup = 225 xtal_name = 'fcc' atomic_basis = np.array([[0., 0., 0.], [0., .5, .5], [.5, 0., .5], [.5, .5, 0.]]) FaceCenteredCubic = FaceCenteredCubicFactory() python-ase-3.9.1.4567/ase/cluster/compounds.py0000664000175000017500000000074512553425526021316 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/cluster/decahedron.py0000664000175000017500000000672212553425526021404 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/cluster/wulff.py0000664000175000017500000001573412553425526020436 0ustar jensjjensj00000000000000from __future__ import print_function import numpy as np delta = 1e-10 _debug = False def wulff_construction(symbol, surfaces, energies, size, structure, rounding='closest', latticeconstant=None, debug=False, maxiter=100): """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. Each surface is an (h, k, l) tuple or list of integers. 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: %s' % rounding) # 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: error = 'Crystal structure %s is not supported.' % structure raise NotImplementedError(error) # 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 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 == maxiter: 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) atoms = structure(symbol, surfaces, layers, latticeconstant=latticeconstant) if _debug: print('Created a cluster with %i atoms: %s' % (len(atoms), str(layers))) return (atoms, layers) python-ase-3.9.1.4567/ase/cluster/octahedron.py0000664000175000017500000000341512553425526021432 0ustar jensjjensj00000000000000""" 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.9.1.4567/ase/cluster/base.py0000664000175000017500000001043012553425526020211 0ustar jensjjensj00000000000000import numpy as np class ClusterBase: def get_layer_distance(self, miller, layers=1, tol=1e-9, new=True): """Returns the distance between planes defined by the given miller index. """ if new: # Create lattice sample size = np.zeros(3, int) for i, m in enumerate(miller): size[i] = np.abs(m) + 2 m = len(self.atomic_basis) p = np.zeros((size.prod() * m, 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 p[m*i:m*(i+1)] = np.dot([h, k, l] + self.atomic_basis, self.lattice_basis) # Project lattice positions on the miller direction. n = self.miller_to_direction(miller) d = np.sum(n * p, axis=1) if np.all(d < tol): # All negative incl. zero d = np.sort(np.abs(d)) reverse = True else: # Some or all positive d = np.sort(d[d > -tol]) reverse = False d = d[np.concatenate((d[1:] - d[:-1] > tol, [True]))] d = d[1:] - d[:-1] # Look for a pattern in the distances between layers. A pattern is # accepted if more than 50 % of the distances obeys it. pattern = None for i in range(len(d)): for n in range(1, (len(d) - i) / 2 + 1): if np.all(np.abs(d[i:i+n] - d[i+n:i+2*n]) < tol): counts = 2 for j in range(i+2*n, len(d), n): if np.all(np.abs(d[j:j+n] - d[i:i+n]) < tol): counts += 1 if counts * n * 1.0 / len(d) > 0.5: pattern = d[i:i+n].copy() break if pattern is not None: break if pattern is None: raise RuntimeError('Could not find layer distance for the ' + '(%i,%i,%i) surface.' % miller) if reverse: pattern = pattern[::-1] if layers < 0: pattern = -1 * pattern[::-1] layers *= -1 map = np.arange(layers - layers % 1 + 1, dtype=int) % len(pattern) return pattern[map][:-1].sum() + layers % 1 * pattern[map][-1] 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.9.1.4567/ase/cluster/hexagonal.py0000664000175000017500000000524412553425526021254 0ustar jensjjensj00000000000000""" 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): "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.], [1./3., 2./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.9.1.4567/ase/cluster/data/0000775000175000017500000000000012553427753017644 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/cluster/data/symmetry.py0000664000175000017500000000567412553425526022117 0ustar jensjjensj00000000000000from ase.cluster.data.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.9.1.4567/ase/cluster/data/__init__.py0000664000175000017500000000040412553425526021747 0ustar jensjjensj00000000000000from ase.data import atomic_numbers, chemical_symbols, reference_states from ase.units import * from . import fcc from . import hcp from . import au lattice = {'fcc': fcc.data, 'hcp': hcp.data, } element = {79: au.data, #Au } python-ase-3.9.1.4567/ase/cluster/data/au.py0000664000175000017500000000124112553425526020615 0ustar jensjjensj00000000000000"""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.9.1.4567/ase/cluster/data/hcp.py0000664000175000017500000001026312553425526020766 0ustar jensjjensj00000000000000"""Structure data - Hexagonal Closed Packed""" import numpy as np from ase.cluster.data.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.9.1.4567/ase/cluster/data/fcc.py0000664000175000017500000002411312553425526020746 0ustar jensjjensj00000000000000from __future__ import print_function """Lattice data - Face Centered Cubic""" import numpy as np from ase.cluster.data.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.9.1.4567/ase/cluster/icosahedron.py0000664000175000017500000001043112553425526021576 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/gui/0000775000175000017500000000000012553427753016036 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/defaults.py0000664000175000017500000000134312553425527020215 0ustar jensjjensj00000000000000""" 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 ase-gui 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 'gui_foreground_color': '#000000', 'gui_background_color': '#ffffff', 'covalent_radii' : None, 'radii_scale': 0.89, } def read_defaults(): import os.path name = os.path.expanduser('~/.ase/gui.py') config = gui_default_settings if os.path.exists(name): exec(compile(open(name).read(), name, 'exec')) return config python-ase-3.9.1.4567/ase/gui/__init__.py0000664000175000017500000000000012553425527020132 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/colors.py0000664000175000017500000007176712553425527017730 0ustar jensjjensj00000000000000from __future__ import print_function # 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.colordata = {} 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_charge = gtk.RadioButton(self.radio_jmol, _('By charge')) self.radio_magnetic_moment = gtk.RadioButton( self.radio_jmol, _('By magnetic moment')) self.radio_coordination = gtk.RadioButton( self.radio_jmol, _('By coordination')) 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() self.charge_box = gtk.VBox() self.magnetic_moment_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.radio_charge, self.charge_box, self.radio_magnetic_moment, self.magnetic_moment_box, self.radio_coordination, 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 in forces!")) pack(self.force_box, [self.force_label]) self.min = gtk.Adjustment(0.0, 0.0, 100.0, 0.05) self.max = gtk.Adjustment(0.0, 0.0, 100.0, 0.05) self.steps = gtk.Adjustment(10, 2, 500, 1) force_apply = gtk.Button(_('Update')) force_apply.connect('clicked', self.set_min_max_colors) pack(self.force_box, [gtk.Label(_('Min: ')), gtk.SpinButton(self.min, 1.0, 2), gtk.Label(_(' Max: ')), gtk.SpinButton(self.max, 1.0, 2), gtk.Label(_(' Steps: ')), gtk.SpinButton(self.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]) velocity_apply = gtk.Button(_('Update')) velocity_apply.connect('clicked', self.set_min_max_colors) pack(self.velocity_box, [gtk.Label(_('Min: ')), gtk.SpinButton(self.min, 1.0, 3), gtk.Label(_(' Max: ')), gtk.SpinButton(self.max, 1.0, 3), gtk.Label(_(' Steps: ')), gtk.SpinButton(self.steps, 1, 0), gtk.Label(' '), velocity_apply]) self.velocity_box.hide() # Now fill in the box for additional information in case # the charge is used. self.charge_label = gtk.Label(_("This should not be displayed!")) pack(self.charge_box, [self.charge_label]) charge_apply = gtk.Button(_('Update')) charge_apply.connect('clicked', self.set_min_max_colors) pack(self.charge_box, [gtk.Label(_('Min: ')), gtk.SpinButton(self.min, 10.0, 2), gtk.Label(_(' Max: ')), gtk.SpinButton(self.max, 10.0, 2), gtk.Label(_(' Steps: ')), gtk.SpinButton(self.steps, 1, 0), gtk.Label(' '), charge_apply]) self.charge_box.hide() # Now fill in the box for additional information in case # the magnetic moment is used. self.magnetic_moment_label = gtk.Label(_( "This should not be displayed!")) pack(self.magnetic_moment_box, [self.magnetic_moment_label]) magnetic_moment_apply = gtk.Button(_('Update')) magnetic_moment_apply.connect('clicked', self.set_min_max_colors) pack(self.magnetic_moment_box, [gtk.Label(_('Min: ')), gtk.SpinButton(self.min, 10.0, 2), gtk.Label(_(' Max: ')), gtk.SpinButton(self.max, 10.0, 2), gtk.Label(_(' Steps: ')), gtk.SpinButton(self.steps, 1, 0), gtk.Label(' '), magnetic_moment_apply]) self.magnetic_moment_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'), _('Blue - white - red'), _('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) if not self.gui.images.q.any(): self.radio_charge.set_sensitive(False) else: self.radio_charge.set_sensitive(True) if not self.gui.images.M.any(): self.radio_magnetic_moment.set_sensitive(False) else: self.radio_magnetic_moment.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 == 'atno': self.radio_atno.set_active(True) elif cm == 'tags': 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 == 'charge': self.radio_charge.set_active(True) elif cm == 'magnetic moment': self.radio_magnetic_moment.set_active(True) elif cm == 'coordination': self.radio_coordination.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_min_max_colors('force') elif widget is self.radio_velocity: self.show_velocity_stuff() self.set_min_max_colors('velocity') elif widget is self.radio_charge: self.show_charge_stuff() self.set_min_max_colors('charge') elif widget is self.radio_magnetic_moment: self.show_magnetic_moment_stuff() self.set_min_max_colors('magnetic moment') elif widget is self.radio_coordination: self.set_coordination_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 = range(tags.min(), tags.max() + 1) 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_min_max_colors(self, mode): borders = np.linspace(self.min.value, self.max.value, self.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 (mode not in self.colordata or len(self.colordata[mode]) != len(borders)): colors = self.get_color_scale(len(borders), self.scaletype_created) else: colors = [y for x, y in self.colordata[mode]] self.colordata[mode] = [[x, y] for x, y in zip(borders, colors)] self.actual_colordata = self.colordata[mode] self.color_labels = ["%.2f:" % x for x, y in self.colordata[mode]] self.make_colorwin() self.colormode = mode factor = self.steps.value / (self.max.value - self.min.value) self.colormode_data = (self.min.value, factor) def set_coordination_colors(self, *args): "Use coordination as basis for the colors." if not hasattr(self.gui, 'coordination'): self.gui.toggle_show_bonds(None) coords = self.gui.coordination existing = range(0, coords.max() + 1) if not hasattr(self, 'colordata_coordination'): colors = self.get_named_colors(len(named_colors)) self.colordata_coordination = [[x, y] for x, y in enumerate(colors)] self.actual_colordata = self.colordata_coordination self.color_labels = [(str(x) + ':') for x, y in self.colordata_coordination] self.make_colorwin() self.colormode = 'coordination' 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 == 'charge': oldcolors = np.array([None] * len(self.actual_colordata)) oldcolors[:] = [y for x, y in self.actual_colordata] q = self.gui.images.q[self.gui.frame] nq = ((q - self.colormode_charge_data[0]) * self.colormode_charge_data[1]) nq = np.clip(nq.astype(int), 0, len(oldcolors)-1) colors[:] = oldcolors[nq] elif self.colormode == 'magnetic moment': oldcolors = np.array([None] * len(self.actual_colordata)) oldcolors[:] = [y for x, y in self.actual_colordata] q = self.gui.images.q[self.gui.frame] nq = ((q - self.colormode_magnetic_moment_data[0]) * self.colormode_magnetic_moment_data[1]) nq = np.clip(nq.astype(int), 0, len(oldcolors)-1) colors[:] = oldcolors[nq] elif self.colormode == 'coordination': oldcolors = np.array([None] * len(self.actual_colordata)) oldcolors[:] = [y for x, y in self.actual_colordata] print(self.gui.images.bonds) 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 get_min_max_text(self, mode, vmin, vmax, min_frame, max_frame): nimages = self.gui.images.nimages txt = 'Max {0}: {1:.2f}'.format(mode, vmax) if nimages > 1: txt += '(all frames), {0:.2f} (this frame)'.format(max_frame) self.max.value = vmax if vmin is None: self.min.value = 0. else: txt += ', Min {0:.2f}'.format(vmin) if nimages > 1: txt += '(all frames), {0:.2f} (this frame)'.format(min_frame) self.min.value = vmin return txt def show_force_stuff(self): "Show and update widgets needed for selecting the force scale." self.force_box.show() # XXX is this projected on some axis ? XXX F = np.sqrt(((self.gui.images.F * self.gui.images.dynamic[:,np.newaxis])**2).sum(axis=-1)) txt = self.get_min_max_text( 'force', None, F.max(), None, self.gui.images.F[self.gui.frame].max()) self.force_label.set_text(_(txt)) 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)) Vframe = np.sqrt((self.gui.images.V[self.gui.frame] * self.gui.images.V[self.gui.frame]).sum(axis=-1)) txt = self.get_min_max_text( 'velocity', None, V.max(), None, Vframe.max()) self.velocity_label.set_text(_(txt)) def show_charge_stuff(self): "Show and update widgets needed for selecting the charge scale." self.charge_box.show() txt = self.get_min_max_text( 'charge', self.gui.images.q.min(), self.gui.images.q.max(), self.gui.images.q[self.gui.frame].min(), self.gui.images.q[self.gui.frame].max()) self.charge_label.set_text(_(txt)) def show_magnetic_moment_stuff(self): "Show and update widgets needed for selecting the magn. mom. scale." self.magnetic_moment_box.show() txt = self.get_min_max_text( 'magnetic moment', self.gui.images.M.min(), self.gui.images.M.max(), self.gui.images.M[self.gui.frame].min(), self.gui.images.M[self.gui.frame].max()) self.magnetic_moment_label.set_text(_(txt)) 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('changed', 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: # Blue - White - Red scale = self.new_color_scale([[0, [0,0,1]], [0.5, [1,1,1]], [2, [1,0,0]]], n) elif s == 5: # 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 == 6: # 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 in [ 'force', 'velocity', 'charge', 'magnetic moment']: # Use integers instead for border values colordata = [[i, x[1]] for i, x in enumerate(self.actual_colordata)] self.gui.colormode_data = self.colormode_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 = colordata self.gui.draw() return True def cancel(self, *args): self.destroy() def ok(self, *args): if self.apply(): self.destroy() python-ase-3.9.1.4567/ase/gui/images.py0000664000175000017500000004042712553425527017661 0ustar jensjjensj00000000000000from __future__ import print_function from math import sqrt import numpy as np from ase.atoms import Atoms from ase.calculators.singlepoint import SinglePointCalculator from ase.constraints import FixAtoms from ase.data import covalent_radii from ase.gui.defaults import read_defaults from ase.io import read, write, string2index 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 filenames is None: filenames = [None] * self.nimages self.filenames = filenames if hasattr(images[0], 'get_shapes'): self.Q = np.empty((self.nimages, self.natoms, 4)) self.shapes = images[0].get_shapes() import os as os if os.path.exists('shapes'): shapesfile = open('shapes') lines = shapesfile.readlines() shapesfile.close() if '#{type:(shape_x,shape_y,shape_z), .....,}' in lines[0]: shape = eval(lines[1]) shapes = [] for an in images[0].get_atomic_numbers(): shapes.append(shape[an]) self.shapes = np.array(shapes) else: print('shape file has wrong format') else: print('no shapesfile found: default shapes were used!') else: self.shapes = None 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.D = np.empty((self.nimages, 3)) self.Z = images[0].get_atomic_numbers() self.q = np.empty((self.nimages, self.natoms)) 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'): self.Q[i] = atoms.get_quaternions() self.A[i] = atoms.get_cell() self.D[i] = atoms.get_celldisp().reshape((3,)) 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: M = atoms.get_magnetic_moments() if M.ndim == 2: M = M[:, 2] self.M[i] = M except (RuntimeError, AttributeError): self.M[i] = atoms.get_initial_magnetic_moments() self.q[i] = atoms.get_initial_charges() # 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(config['radii_scale']) 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', 'D', 'q'): 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() self.D[i] = atoms.get_celldisp().reshape((3,)) self.q[i] = atoms.get_initial_charges() 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 is 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) for image in images: if 'radii' in image.info: self.set_radii(image.info['radii']) break 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 ase-gui 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, remove_hidden=False): 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)) # Remove hidden atoms if applicable if remove_hidden: atoms = atoms[self.visible] f = self.F[frame][self.visible] else: f = self.F[frame] atoms.set_calculator(SinglePointCalculator(atoms, energy=self.E[frame], forces=f)) 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) T = np.empty((self.nimages, self.natoms), int) D = np.empty((self.nimages, 3)) 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] T[:] = self.T[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] D[i] = y * self.D[0] + x * self.D[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] D[-1] = self.D[1] self.P = P self.V = V self.F = F self.A = A self.E = E self.T = T self.D = D self.filenames[1:1] = [None] * m python-ase-3.9.1.4567/ase/gui/gui.py0000664000175000017500000013750212553425527017201 0ustar jensjjensj00000000000000from __future__ import print_function # 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 import pickle 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.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.save import SaveWindow from ase.version import version 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('ase-gui &')), ('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), ('ShowLabels', None, _('Show _Labels')), ('HideAtoms', None, _('Hide selected atoms'), None, '', self.hide_selected), ('ShowAtoms', None, _('Show selected atoms'), None, '', self.show_selected), ('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 ...'), 'C', '', 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), ('ChangeView', None, _('Change View')), ('ResetView', None, _('Reset View'), 'equal', '', self.reset_view), ('xyPlane', None, _('\'xy\' Plane'), 'z', '', self.set_view), ('yzPlane', None, _('\'yz\' Plane'), 'x', '', self.set_view), ('zxPlane', None, _('\'zx\' Plane'), 'y', '', self.set_view), ('yxPlane', None, _('\'yx\' Plane'), 'z', '', self.set_view), ('zyPlane', None, _('\'zy\' Plane'), 'x', '', self.set_view), ('xzPlane', None, _('\'xz\' Plane'), 'y', '', self.set_view), ('a2a3Plane', None, _('\'a2 a3\' Plane'), '1', '', self.set_view), ('a3a1Plane', None, _('\'a3 a1\' Plane'), '2', '', self.set_view), ('a1a2Plane', None, _('\'a1 a2\' Plane'), '3', '', self.set_view), ('a3a2Plane', None, _('\'a3 a2\' Plane'), '1', '', self.set_view), ('a1a3Plane', None, _('\'a1 a3\' Plane'), '2', '', self.set_view), ('a2a1Plane', None, _('\'a2 a1\' Plane'), '3', '', self.set_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), ('ShowVelocities', None, _('Show _velocities'), 'G', 'Bold', self.toggle_show_velocities, False), ('ShowForces', None, _('Show _forces'), 'F', 'Bold', self.toggle_show_forces, False), ('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) ]) actions.add_radio_actions(( ('NoLabel', None, _('_None'), None, None, 0), ('AtomIndex', None, _('Atom _Index'), None, None, 1), ('MagMom', None, _('_Magnetic Moments'), None, None, 2), ('Element', None, _('_Element Symbol'), None, None, 3)), 0, self.show_labels) 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 as 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.vulnerable_windows = [] self.simulation = {} # Used by modules on Calculate menu. self.module_state = {} # Used by modules to store their state. 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." clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD) 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 atoms.reference_position = ref clip.set_text(pickle.dumps(atoms, 0)) def paste_atoms(self, widget): "Inserts clipboard selection into the current frame using the add_atoms window." clip = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD) try: atoms = pickle.loads(clip.wait_for_text()) self.add_atoms(widget, data='Paste', paste=atoms) except: pass 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: import ase.structure a = ase.structure.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) # Updates atomic labels cv = self.ui.get_action_groups()[0].\ get_action("NoLabel").get_current_value() self.ui.get_action_groups()[0].\ get_action("NoLabel").set_current_value(0) self.ui.get_action_groups()[0].\ get_action("NoLabel").set_current_value(cv) # 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, menuitem): SaveWindow(self) 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() dialog.set_version(version) dialog.set_website( 'https://wiki.fysik.dtu.dk/ase/ase/gui/gui.html') except AttributeError: self.xxx() else: dialog.run() dialog.destroy() def webpage(widget): import webbrowser webbrowser.open('https://wiki.fysik.dtu.dk/ase/ase/gui/gui.html') python-ase-3.9.1.4567/ase/gui/status.py0000664000175000017500000000675012553425527017740 0ustar jensjjensj00000000000000# -*- 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 = sorted(hist.keys()) 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.9.1.4567/ase/gui/repeat.py0000664000175000017500000000237012553425527017667 0ustar jensjjensj00000000000000import gtk from gettext import gettext as _ import numpy as np from ase.gui.widgets import pack 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.9.1.4567/ase/gui/execute.py0000664000175000017500000003251112553425527020051 0ustar jensjjensj00000000000000import __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: ase-gui window python object img:\tadvanced: ase-gui 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 = list(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.9.1.4567/ase/gui/nanoparticle.py0000664000175000017500000006252712553425527021100 0ustar jensjjensj00000000000000# 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 ase.data 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(_(u"ų"))]) 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.data.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(_(u"%.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.9.1.4567/ase/gui/energyforces.py0000664000175000017500000000653512553425527021111 0ustar jensjjensj00000000000000# 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.9.1.4567/ase/gui/po/0000775000175000017500000000000012553427753016454 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/is/0000775000175000017500000000000012553427753017067 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/is/LC_MESSAGES/0000775000175000017500000000000012553427753020654 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/is/LC_MESSAGES/ag.po0000664000175000017500000015146212553425527021611 0ustar jensjjensj00000000000000# Icelandic translation of ag # Copyright (C) 2012 CAMD # This file is distributed under the same license as the ase-gui package. # # Elvar Örn Jonsson , 2012. # msgid "" msgstr "" "Project-Id-Version: ag-3.5.2\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2012-09-10 15:12+0200\n" "PO-Revision-Date: 2012-02-01 15:45+0100\n" "Last-Translator: Elvar Örn Jonsson \n" "Language-Team: Icelandic\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: \n" "Plural-Forms: nplurals=2; plural=(n % 100 != 1 && n % 100 != 21 && n % 100 !" "= 31 && n % 100 != 41 && n % 100 != 51 && n % 100 != 61 && n % 100 != 71 && " "n % 100 != 81 && n % 100 != 91)\n" "\n" #: ../ag.py:136 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:452 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:470 ../calculator.py:482 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "" #: ../calculator.py:473 msgid "You must set up the GPAW parameters" msgstr "" #: ../calculator.py:514 msgid "You must set up the FHI-aims parameters" msgstr "" #: ../calculator.py:528 msgid "You must set up the VASP parameters" msgstr "" #: ../calculator.py:552 #, python-format msgid "Element %(sym)s not allowed by the '%(name)s' calculator" msgstr "" #: ../calculator.py:559 msgid "Info" msgstr "" #: ../calculator.py:575 msgid "Lennard-Jones parameters" msgstr "" #: ../calculator.py:587 msgid "Specify the Lennard-Jones parameters here" msgstr "" #: ../calculator.py:590 msgid "Epsilon (eV):" msgstr "" #: ../calculator.py:594 msgid "Sigma (Å):" msgstr "" #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:598 msgid "Shift to make smooth at cutoff" msgstr "" #: ../calculator.py:679 msgid "GPAW parameters" msgstr "" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:694 ../calculator.py:983 ../calculator.py:1471 #, python-format msgid "%i atoms.\n" msgstr "" #: ../calculator.py:696 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "" #: ../calculator.py:698 msgid "Non-orthogonal unit cell:\n" msgstr "" #: ../calculator.py:708 ../calculator.py:999 ../calculator.py:1486 msgid "Exchange-correlation functional: " msgstr "" #. Grid spacing #: ../calculator.py:712 msgid "Grid spacing" msgstr "" #: ../calculator.py:716 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "" #: ../calculator.py:717 msgid "Grid points" msgstr "" #: ../calculator.py:726 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "" #: ../calculator.py:752 ../calculator.py:1014 ../calculator.py:1522 msgid "k-points k = (" msgstr "" #: ../calculator.py:756 ../calculator.py:1018 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "" #. Spin polarized #: ../calculator.py:761 ../calculator.py:1484 msgid "Spin polarized" msgstr "" #: ../calculator.py:767 msgid "FD - Finite Difference (grid) mode" msgstr "" #: ../calculator.py:768 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "" #: ../calculator.py:771 msgid "Mode: " msgstr "" #: ../calculator.py:773 msgid "sz - Single Zeta" msgstr "" #: ../calculator.py:774 msgid "szp - Single Zeta polarized" msgstr "" #: ../calculator.py:775 msgid "dzp - Double Zeta polarized" msgstr "" #. dzp #: ../calculator.py:777 msgid "Basis functions: " msgstr "" #. Mixer #: ../calculator.py:783 msgid "Non-standard mixer parameters" msgstr "" #: ../calculator.py:979 msgid "FHI-aims parameters" msgstr "" #: ../calculator.py:986 msgid "Periodic geometry, unit cell is:\n" msgstr "" #: ../calculator.py:991 msgid "Non-periodic geometry.\n" msgstr "" #: ../calculator.py:998 msgid "Hirshfeld-based dispersion correction" msgstr "" #. Spin polarized, charge, relativity #: ../calculator.py:1024 msgid "Spin / initial moment " msgstr "" #: ../calculator.py:1042 msgid " Charge" msgstr "" #: ../calculator.py:1044 msgid " Relativity" msgstr "" #: ../calculator.py:1046 msgid " Threshold" msgstr "" #. self-consistency criteria #: ../calculator.py:1051 msgid "Self-consistency convergence:" msgstr "" #: ../calculator.py:1064 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:1075 msgid "Energy: " msgstr "" #: ../calculator.py:1077 msgid " eV Sum of eigenvalues: " msgstr "" #: ../calculator.py:1079 ../calculator.py:1557 msgid " eV" msgstr "" #: ../calculator.py:1080 msgid "Electron density: " msgstr "" #: ../calculator.py:1082 msgid " Force convergence: " msgstr "" #: ../calculator.py:1084 msgid " eV/Ang " msgstr "" #: ../calculator.py:1097 ../calculator.py:1568 msgid "Additional keywords: " msgstr "" #. run command and species defaults: #: ../calculator.py:1111 msgid "FHI-aims execution command: " msgstr "" #: ../calculator.py:1113 ../calculator.py:1585 msgid "Directory for species defaults: " msgstr "" #: ../calculator.py:1125 ../calculator.py:1593 msgid "Set Defaults" msgstr "" #: ../calculator.py:1127 msgid "Import control.in" msgstr "" #: ../calculator.py:1129 msgid "Export control.in" msgstr "" #: ../calculator.py:1315 msgid "Export parameters ... " msgstr "" #: ../calculator.py:1335 msgid "Import control.in file ... " msgstr "" #: ../calculator.py:1391 ../calculator.py:1903 #, python-format msgid "" "Please use the facilities provided in this window to manipulate the keyword: " "%s!" msgstr "" #: ../calculator.py:1394 #, 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:1467 msgid "VASP parameters" msgstr "" #: ../calculator.py:1473 msgid "Periodic geometry, unit cell is: \n" msgstr "" #: ../calculator.py:1525 msgid ") Cutoff: " msgstr "" #: ../calculator.py:1526 msgid " Precision: " msgstr "" #: ../calculator.py:1528 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "" #: ../calculator.py:1544 msgid "Smearing: " msgstr "" #: ../calculator.py:1546 msgid " order: " msgstr "" #: ../calculator.py:1548 msgid " width: " msgstr "" #: ../calculator.py:1555 msgid "Self-consistency convergence: " msgstr "" #. run command and location of POTCAR files: #: ../calculator.py:1581 msgid "VASP execution command: " msgstr "" #: ../calculator.py:1595 msgid "Import VASP files" msgstr "" #: ../calculator.py:1597 msgid "Export VASP files" msgstr "" #: ../calculator.py:1806 msgid "WARNING: cutoff energy is lower than recommended minimum!" msgstr "" #: ../calculator.py:1858 msgid "Import VASP input files: choose directory ... " msgstr "" #: ../calculator.py:1873 msgid "Export VASP input files: choose directory ... " msgstr "" #: ../calculator.py:1906 #, 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:90 msgid "Constraints" msgstr "" #: ../constraints.py:15 ../constraints.py:18 ../settings.py:17 #: ../widgets.py:92 ../widgets.py:95 msgid "Constrain" msgstr "" #: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:93 msgid " selected atoms" msgstr "" #: ../constraints.py:19 ../widgets.py:96 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:100 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 ../graphene.py:27 #, 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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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: ase-gui window python object\n" " img:\tadvanced: ase-gui 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:16 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:33 ../gui.py:316 msgid "Graphene" msgstr "" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "" #: ../graphene.py:42 msgid "Infinite sheet" msgstr "" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "" #: ../graphene.py:53 msgid "zigzag" msgstr "" #: ../graphene.py:53 msgid "armchair" msgstr "" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 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:90 msgid "Width: " msgstr "" #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr "" #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "" #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr "" #: ../graphene.py:194 msgid "Please specify a consistent set of atoms. " msgstr "" #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../pybutton.py:49 ../surfaceslab.py:249 msgid "You have not (yet) specified a consistent set of parameters." msgstr "" #: ../graphs.py:9 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" #: ../graphs.py:52 ../graphs.py:55 msgid "Plot" msgstr "" #: ../graphs.py:60 msgid "clear" msgstr "" #: ../graphs.py:114 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:175 msgid "_File" msgstr "" #: ../gui.py:176 msgid "_Edit" msgstr "" #: ../gui.py:177 msgid "_View" msgstr "" #: ../gui.py:178 msgid "_Tools" msgstr "" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:180 msgid "_Setup" msgstr "" #: ../gui.py:181 msgid "_Calculate" msgstr "" #: ../gui.py:182 msgid "_Help" msgstr "" #: ../gui.py:183 msgid "_Open" msgstr "" #: ../gui.py:184 msgid "Create a new file" msgstr "" #: ../gui.py:186 msgid "_New" msgstr "" #: ../gui.py:187 msgid "New ase.gui window" msgstr "" #: ../gui.py:189 msgid "_Save" msgstr "" #: ../gui.py:190 msgid "Save current file" msgstr "" #: ../gui.py:192 msgid "_Quit" msgstr "" #: ../gui.py:193 msgid "Quit" msgstr "" #: ../gui.py:195 msgid "Select _all" msgstr "" #: ../gui.py:198 msgid "_Invert selection" msgstr "" #: ../gui.py:201 msgid "Select _constrained atoms" msgstr "" #: ../gui.py:204 msgid "Select _immobile atoms" msgstr "" #: ../gui.py:207 msgid "_Copy" msgstr "" #: ../gui.py:208 msgid "Copy current selection and its orientation to clipboard" msgstr "" #: ../gui.py:210 msgid "_Paste" msgstr "" #: ../gui.py:211 msgid "Insert current clipboard selection" msgstr "" #: ../gui.py:213 msgid "_Modify" msgstr "" #: ../gui.py:214 msgid "Change tags, moments and atom types of the selected atoms" msgstr "" #: ../gui.py:216 msgid "_Add atoms" msgstr "" #: ../gui.py:217 msgid "Insert or import atoms and molecules" msgstr "" #: ../gui.py:219 msgid "_Delete selected atoms" msgstr "" #: ../gui.py:220 msgid "Delete the selected atoms" msgstr "" #: ../gui.py:222 msgid "_First image" msgstr "" #: ../gui.py:225 msgid "_Previous image" msgstr "" #: ../gui.py:228 msgid "_Next image" msgstr "" #: ../gui.py:231 msgid "_Last image" msgstr "" #: ../gui.py:234 msgid "Show _Labels" msgstr "" #: ../gui.py:235 msgid "Hide selected atoms" msgstr "" #: ../gui.py:238 msgid "Show selected atoms" msgstr "" #: ../gui.py:241 msgid "Quick Info ..." msgstr "" #: ../gui.py:244 msgid "Repeat ..." msgstr "" #: ../gui.py:247 msgid "Rotate ..." msgstr "" #: ../gui.py:250 msgid "Colors ..." msgstr "" #. TRANSLATORS: verb #: ../gui.py:253 msgid "Focus" msgstr "" #: ../gui.py:256 msgid "Zoom in" msgstr "" #: ../gui.py:259 msgid "Zoom out" msgstr "" #: ../gui.py:262 msgid "Reset View" msgstr "" #: ../gui.py:265 msgid "Settings ..." msgstr "" #: ../gui.py:268 msgid "VMD" msgstr "" #: ../gui.py:271 msgid "RasMol" msgstr "" #: ../gui.py:274 msgid "xmakemol" msgstr "" #: ../gui.py:277 msgid "avogadro" msgstr "" #: ../gui.py:280 msgid "Graphs ..." msgstr "" #: ../gui.py:283 msgid "Movie ..." msgstr "" #: ../gui.py:286 msgid "Expert mode ..." msgstr "" #: ../gui.py:289 msgid "Constraints ..." msgstr "" #: ../gui.py:292 msgid "Render scene ..." msgstr "" #: ../gui.py:295 msgid "DFT ..." msgstr "" #: ../gui.py:298 msgid "NE_B" msgstr "" #: ../gui.py:301 msgid "B_ulk Modulus" msgstr "" #: ../gui.py:304 msgid "_Bulk Crystal" msgstr "" #: ../gui.py:305 msgid "Create a bulk crystal with arbitrary orientation" msgstr "" #: ../gui.py:307 msgid "_Surface slab" msgstr "" #: ../gui.py:308 msgid "Create the most common surfaces" msgstr "" #: ../gui.py:310 msgid "_Nanoparticle" msgstr "" #: ../gui.py:311 msgid "Create a crystalline nanoparticle" msgstr "" #: ../gui.py:313 msgid "Nano_tube" msgstr "" #: ../gui.py:314 msgid "Create a nanotube" msgstr "" #: ../gui.py:317 msgid "Create a graphene sheet or nanoribbon" msgstr "" #: ../gui.py:319 msgid "Set _Calculator" msgstr "" #: ../gui.py:320 msgid "Set a calculator used in all calculation modules" msgstr "" #: ../gui.py:322 msgid "_Energy and Forces" msgstr "" #: ../gui.py:323 msgid "Calculate energy and forces" msgstr "" #: ../gui.py:325 msgid "Energy _Minimization" msgstr "" #: ../gui.py:326 msgid "Minimize the energy" msgstr "" #: ../gui.py:328 msgid "Scale system" msgstr "" #: ../gui.py:329 msgid "Deform system by scaling it" msgstr "" #: ../gui.py:331 msgid "_About" msgstr "" #: ../gui.py:334 msgid "Webpage ..." msgstr "" #: ../gui.py:335 msgid "Debug ..." msgstr "" #: ../gui.py:337 msgid "Show _unit cell" msgstr "" #: ../gui.py:341 msgid "Show _axes" msgstr "" #: ../gui.py:345 msgid "Show _bonds" msgstr "" #: ../gui.py:349 msgid "Show _velocities" msgstr "" #: ../gui.py:353 msgid "Show _forces" msgstr "" #: ../gui.py:357 msgid "_Move atoms" msgstr "" #: ../gui.py:361 msgid "_Rotate atoms" msgstr "" #: ../gui.py:365 msgid "Orien_t atoms" msgstr "" #: ../gui.py:371 msgid "_None" msgstr "" #: ../gui.py:372 msgid "Atom _Index" msgstr "" #: ../gui.py:373 msgid "_Magnetic Moments" msgstr "" #: ../gui.py:374 msgid "_Element Symbol" msgstr "" #: ../gui.py:383 #, python-format msgid "building menus failed: %s" msgstr "" #: ../gui.py:658 ../gui.py:1064 ../gui.py:1124 msgid "Open ..." msgstr "" #: ../gui.py:662 ../gui.py:1067 msgid "<>" msgstr "" #: ../gui.py:795 msgid "Add atoms" msgstr "" #: ../gui.py:798 msgid "Paste" msgstr "" #: ../gui.py:804 msgid "Insert atom or molecule" msgstr "" #: ../gui.py:805 ../gui.py:931 msgid "Tag" msgstr "" #: ../gui.py:806 ../gui.py:932 msgid "Moment" msgstr "" #: ../gui.py:807 msgid "Position" msgstr "" #: ../gui.py:832 msgid "_Load molecule" msgstr "" #: ../gui.py:836 ../gui.py:947 msgid "_OK" msgstr "" #: ../gui.py:840 ../gui.py:951 msgid "_Cancel" msgstr "" #: ../gui.py:924 msgid "Modify" msgstr "" #: ../gui.py:930 msgid "Atom" msgstr "" #: ../gui.py:975 msgid "Confirmation" msgstr "" #: ../gui.py:979 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "" msgstr[1] "" #: ../gui.py:986 msgid "Cancel" msgstr "" #: ../gui.py:1072 ../gui.py:1154 msgid "Automatic" msgstr "" #: ../gui.py:1073 msgid "Dacapo netCDF output file" msgstr "" #: ../gui.py:1074 msgid "Virtual Nano Lab file" msgstr "" #: ../gui.py:1075 msgid "ASE pickle trajectory" msgstr "" #: ../gui.py:1076 ../gui.py:1167 msgid "ASE bundle trajectory" msgstr "" #: ../gui.py:1077 msgid "GPAW text output" msgstr "" #: ../gui.py:1078 msgid "CUBE file" msgstr "" #: ../gui.py:1079 msgid "XCrySDen Structure File" msgstr "" #: ../gui.py:1080 msgid "Dacapo text output" msgstr "" #: ../gui.py:1081 msgid "XYZ-file" msgstr "" #: ../gui.py:1082 msgid "VASP POSCAR/CONTCAR file" msgstr "" #: ../gui.py:1083 msgid "VASP OUTCAR file" msgstr "" #: ../gui.py:1084 msgid "Protein Data Bank" msgstr "" #: ../gui.py:1085 msgid "CIF-file" msgstr "" #: ../gui.py:1086 msgid "FHI-aims geometry file" msgstr "" #: ../gui.py:1087 msgid "FHI-aims output file" msgstr "" #: ../gui.py:1088 msgid "TURBOMOLE coord file" msgstr "" #: ../gui.py:1089 msgid "exciting input" msgstr "" #: ../gui.py:1090 msgid "WIEN2k structure file" msgstr "" #: ../gui.py:1091 msgid "DftbPlus input file" msgstr "" #: ../gui.py:1092 msgid "ETSF format" msgstr "" #: ../gui.py:1093 ../gui.py:1165 msgid "CASTEP geom file" msgstr "" #: ../gui.py:1094 msgid "CASTEP output file" msgstr "" #: ../gui.py:1095 msgid "CASTEP trajectory file" msgstr "" #: ../gui.py:1096 msgid "DFTBPlus GEN format" msgstr "" #: ../gui.py:1102 msgid "File type:" msgstr "" #: ../gui.py:1142 msgid "Save ..." msgstr "" #: ../gui.py:1155 msgid "XYZ file" msgstr "" #: ../gui.py:1156 msgid "ASE trajectory" msgstr "" #: ../gui.py:1157 msgid "PDB file" msgstr "" #: ../gui.py:1158 msgid "Gaussian cube file" msgstr "" #: ../gui.py:1159 msgid "Python script" msgstr "" #: ../gui.py:1160 msgid "VNL file" msgstr "" #: ../gui.py:1161 msgid "Portable Network Graphics" msgstr "" #: ../gui.py:1162 msgid "Persistence of Vision" msgstr "" #: ../gui.py:1163 msgid "Encapsulated PostScript" msgstr "" #: ../gui.py:1164 msgid "FHI-aims geometry input" msgstr "" #: ../gui.py:1166 msgid "VASP geometry input" msgstr "" #: ../gui.py:1168 msgid "cif file" msgstr "" #: ../gui.py:1190 #, python-format msgid "Save current image only (#%d)" msgstr "" #: ../gui.py:1194 msgid "Slice: " msgstr "" #: ../gui.py:1195 msgid "Help for slice ..." msgstr "" #: ../gui.py:1207 msgid "ase-gui INTERNAL ERROR: strange response in Save," msgstr "" #: ../gui.py:1226 msgid "Unknown output format!" msgstr "" #: ../gui.py:1227 #, python-format msgid "Use one of: %s" msgstr "" #: ../gui.py:1332 msgid "Not implemented!" msgstr "" #: ../gui.py:1333 msgid "do you really need it?" msgstr "" #: ../minimize.py:21 msgid "Algorithm: " msgstr "" #: ../minimize.py:26 ../progress.py:67 msgid "Convergence criterion: Fmax = " msgstr "" #: ../minimize.py:31 ../progress.py:70 msgid "Max. number of steps: " msgstr "" #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "" #: ../minimize.py:55 msgid "Energy minimization" msgstr "" #: ../minimize.py:59 msgid "Minimize the energy with respect to the positions." msgstr "" #. Don't catch errors in the function. #. Display status message #: ../minimize.py:91 ../scaling.py:299 msgid "Running ..." msgstr "" #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "" #: ../minimize.py:114 ../scaling.py:350 msgid "Out of memory, consider using LBFGS instead" msgstr "" #. Update display to reflect succesful end of simulation. #: ../minimize.py:121 #, 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:20 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:27 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:84 msgid "Face centered cubic (fcc)" msgstr "" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "" #: ../nanoparticle.py:131 msgid "Get structure" msgstr "" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "" #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "" #: ../nanoparticle.py:212 msgid "Add" msgstr "" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "" #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:196 msgid "Number of atoms: " msgstr "" #: ../nanoparticle.py:234 msgid "Volume: " msgstr "" #: ../nanoparticle.py:239 msgid "ų" msgstr "" #: ../nanoparticle.py:244 msgid "Rounding: If exact size is not possible, choose the size" msgstr "" #: ../nanoparticle.py:247 msgid "above " msgstr "" #: ../nanoparticle.py:248 msgid "below " msgstr "" #: ../nanoparticle.py:249 msgid "closest " msgstr "" #: ../nanoparticle.py:252 msgid "Smaller" msgstr "" #: ../nanoparticle.py:253 msgid "Larger" msgstr "" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr "" #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "" #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "" #: ../nanoparticle.py:333 msgid "Up" msgstr "" #: ../nanoparticle.py:338 msgid "Down" msgstr "" #: ../nanoparticle.py:343 msgid "Delete" msgstr "" #: ../nanoparticle.py:384 msgid "Surface energies (as energy/area, NOT per atom):" msgstr "" #: ../nanoparticle.py:390 msgid "Number of layers:" msgstr "" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "" #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "" #: ../nanotube.py:15 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:29 #, python-format msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: %" "(volume).3f Å3" msgstr "" #: ../nanotube.py:35 msgid "Nanotube" msgstr "" #. Choose the structure. #: ../nanotube.py:59 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:81 msgid "Help" msgstr "" #: ../widgets.py:98 msgid "Clear constraint" msgstr "" python-ase-3.9.1.4567/ase/gui/po/en_GB/0000775000175000017500000000000012553427753017426 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/en_GB/LC_MESSAGES/0000775000175000017500000000000012553427753021213 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/en_GB/LC_MESSAGES/ag.po0000664000175000017500000024427412553425551022151 0ustar jensjjensj00000000000000# English translations for ASE package # Copyright (C) 2011-2015 CAMD # This file is distributed under the same license as the ASE package. # # Ask Hjorth Larsen , 2011-2015. # msgid "" msgstr "" "Project-Id-Version: ase-3.5.2\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2015-07-15 17:25+0200\n" "PO-Revision-Date: 2015-07-15 17:30+0200\n" "Last-Translator: Ask Hjorth Larsen \n" "Language-Team: English (British) \n" "Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../ag.py:144 msgid "To get a full traceback, use: ase-gui --verbose" msgstr "To get a full traceback, use: ase-gui --verbose" #. 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 EAM/ADP potential is a many-body potential\n" "implementation of the Embedded Atom Method and\n" "equipotential plus the Angular Dependent Potential,\n" "which is an extension of the EAM to include\n" "directional bonds. EAM is suited for FCC metallic\n" "bonding while the ADP is suited for metallic bonds\n" "with some degree of directionality.\n" "\n" "For EAM see M.S. Daw and M.I. Baskes,\n" "Phys. Rev. Letters 50 (1983) 1285.\n" "\n" "For ADP see Y. Mishin, M.J. Mehl, and\n" "D.A. Papaconstantopoulos, Acta Materialia 53 2005\n" "4029--4041.\n" "\n" "Data for the potential is contained in a file in either LAMMPS Alloy\n" "or ADP format which need to be loaded before use. The Interatomic\n" "Potentials Repository Project at http://www.ctcms.nist.gov/potentials/\n" "contains many suitable potential files.\n" "\n" "For large simulations the LAMMPS calculator is more\n" "suitable; this implementation is mainly to make EAM\n" "available when LAMMPS is not installed or to develop\n" "new EAM/ADP poentials by matching results using ab\n" "initio.\n" msgstr "" "The EAM/ADP potential is a many-body potential\n" "implementation of the Embedded Atom Method and\n" "equipotential plus the Angular Dependent Potential,\n" "which is an extension of the EAM to include\n" "directional bonds. EAM is suited for FCC metallic\n" "bonding while the ADP is suited for metallic bonds\n" "with some degree of directionality.\n" "\n" "For EAM see M.S. Daw and M.I. Baskes,\n" "Phys. Rev. Letters 50 (1983) 1285.\n" "\n" "For ADP see Y. Mishin, M.J. Mehl, and\n" "D.A. Papaconstantopoulos, Acta Materialia 53 2005\n" "4029--4041.\n" "\n" "Data for the potential is contained in a file in either LAMMPS Alloy\n" "or ADP format which need to be loaded before use. The Interatomic\n" "Potentials Repository Project at http://www.ctcms.nist.gov/potentials/\n" "contains many suitable potential files.\n" "\n" "For large simulations the LAMMPS calculator is more\n" "suitable; this implementation is mainly to make EAM\n" "available when LAMMPS is not installed or to develop\n" "new EAM/ADP poentials by matching results using ab\n" "initio.\n" #: ../calculator.py:113 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:135 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:142 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:152 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:159 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:168 msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)" msgstr "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)" #: ../calculator.py:169 msgid "Alternative Cu, Ag and Au" msgstr "Alternative Cu, Ag and Au" #: ../calculator.py:170 msgid "Ruthenium" msgstr "Ruthenium" #: ../calculator.py:171 msgid "CuMg and CuZr metallic glass" msgstr "CuMg and CuZr metallic glass" #: ../calculator.py:189 msgid "Select calculator" msgstr "Select calculator" #: ../calculator.py:195 msgid "Calculator:" msgstr "Calculator:" #. No calculator (the default) #: ../calculator.py:198 msgid "None" msgstr "None" #: ../calculator.py:203 msgid "Lennard-Jones (ASAP)" msgstr "Lennard-Jones (ASAP)" #: ../calculator.py:204 ../calculator.py:231 ../calculator.py:246 #: ../calculator.py:255 ../calculator.py:264 msgid "Setup" msgstr "Setup" #: ../calculator.py:211 msgid "EMT - Effective Medium Theory (ASAP)" msgstr "EMT - Effective Medium Theory (ASAP)" #: ../calculator.py:223 msgid "EMT - Effective Medium Theory (ASE)" msgstr "EMT - Effective Medium Theory (ASE)" #: ../calculator.py:230 msgid "EAM - Embedded Atom Method/Angular Dependent Potential (ASE)" msgstr "EAM - Embedded Atom Method/Angular Dependent Potential (ASE)" #: ../calculator.py:238 msgid "Brenner Potential (ASAP)" msgstr "Brenner Potential (ASAP)" #: ../calculator.py:244 msgid "Density Functional Theory (GPAW)" msgstr "Density Functional Theory (GPAW)" #: ../calculator.py:253 msgid "Density Functional Theory (FHI-aims)" msgstr "Density Functional Theory (FHI-aims)" #: ../calculator.py:262 msgid "Density Functional Theory (VASP)" msgstr "Density Functional Theory (VASP)" #: ../calculator.py:275 msgid "Check that the calculator is reasonable." msgstr "Check that the calculator is reasonable." #: ../calculator.py:345 ../simulation.py:114 msgid "No atoms present" msgstr "No atoms present" #: ../calculator.py:439 ../calculator.py:474 ../calculator.py:521 msgid "ASAP is not installed. (Failed to import asap3)" msgstr "ASAP is not installed. (Failed to import asap3)" #: ../calculator.py:442 msgid "You must set up the Lennard-Jones parameters" msgstr "You must set up the Lennard-Jones parameters" #: ../calculator.py:447 msgid "Could not create useful Lennard-Jones calculator." msgstr "Could not create useful Lennard-Jones calculator." #: ../calculator.py:482 msgid "Could not attach EMT calculator to the atoms." msgstr "Could not attach EMT calculator to the atoms." #: ../calculator.py:503 msgid "You must set up the EAM parameters" msgstr "You must set up the EAM parameters" #: ../calculator.py:539 ../calculator.py:551 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "GPAW is not installed. (Failed to import gpaw)" #: ../calculator.py:542 msgid "You must set up the GPAW parameters" msgstr "You must set up the GPAW parameters" #: ../calculator.py:584 msgid "You must set up the FHI-aims parameters" msgstr "You must set up the FHI-aims parameters" #: ../calculator.py:599 msgid "You must set up the VASP parameters" msgstr "You must set up the VASP parameters" #: ../calculator.py:624 #, 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:632 msgid "Info" msgstr "Info" #: ../calculator.py:648 msgid "Lennard-Jones parameters" msgstr "Lennard-Jones parameters" #: ../calculator.py:660 msgid "Specify the Lennard-Jones parameters here" msgstr "Specify the Lennard-Jones parameters here" #: ../calculator.py:663 msgid "Epsilon (eV):" msgstr "Epsilon (eV):" #: ../calculator.py:667 msgid "Sigma (Å):" msgstr "Sigma (Å):" #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:671 msgid "Shift to make smooth at cutoff" msgstr "Shift to make smooth at cutoff" #: ../calculator.py:750 msgid "EAM parameters" msgstr "EAM parameters" #: ../calculator.py:764 msgid "Import Potential" msgstr "Import Potential" #: ../calculator.py:787 msgid "You need to import the potential file" msgstr "You need to import the potential file" #: ../calculator.py:795 msgid "Import .alloy or .adp potential file ... " msgstr "Import .alloy or .adp potential file ... " #: ../calculator.py:818 msgid "GPAW parameters" msgstr "GPAW parameters" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:833 ../calculator.py:1123 ../calculator.py:1612 #, python-format msgid "%i atoms.\n" msgstr "%i atoms.\n" #: ../calculator.py:835 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "Orthogonal unit cell: %.2f x %.2f x %.2f Å." #: ../calculator.py:837 msgid "Non-orthogonal unit cell:\n" msgstr "Non-orthogonal unit cell:\n" #: ../calculator.py:847 ../calculator.py:1139 ../calculator.py:1627 msgid "Exchange-correlation functional: " msgstr "Exchange-correlation functional: " #. Grid spacing #: ../calculator.py:851 msgid "Grid spacing" msgstr "Grid spacing" #: ../calculator.py:855 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "Å" #: ../calculator.py:856 msgid "Grid points" msgstr "Grid points" #: ../calculator.py:865 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "heff = (%.3f, %.3f, %.3f) Å" #: ../calculator.py:891 ../calculator.py:1154 ../calculator.py:1663 msgid "k-points k = (" msgstr "k-points k = (" #: ../calculator.py:895 ../calculator.py:1158 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "k-points x size: (%.1f, %.1f, %.1f) Å" #. Spin polarized #: ../calculator.py:900 ../calculator.py:1625 msgid "Spin polarized" msgstr "Spin polarised" #: ../calculator.py:906 msgid "FD - Finite Difference (grid) mode" msgstr "FD - Finite Difference (grid) mode" #: ../calculator.py:907 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "LCAO - Linear Combination of Atomic Orbitals" #: ../calculator.py:910 msgid "Mode: " msgstr "Mode: " #: ../calculator.py:912 msgid "sz - Single Zeta" msgstr "sz - Single Zeta" #: ../calculator.py:913 msgid "szp - Single Zeta polarized" msgstr "szp - Single Zeta polarised" #: ../calculator.py:914 msgid "dzp - Double Zeta polarized" msgstr "dzp - Double Zeta polarised" #. dzp #: ../calculator.py:916 msgid "Basis functions: " msgstr "Basis functions: " #. Mixer #: ../calculator.py:922 msgid "Non-standard mixer parameters" msgstr "Non-standard mixer parameters" #: ../calculator.py:1119 msgid "FHI-aims parameters" msgstr "FHI-aims parameters" #: ../calculator.py:1126 msgid "Periodic geometry, unit cell is:\n" msgstr "Periodic geometry, unit cell is:\n" #: ../calculator.py:1131 msgid "Non-periodic geometry.\n" msgstr "Non-periodic geometry.\n" #: ../calculator.py:1138 msgid "Hirshfeld-based dispersion correction" msgstr "Hirshfeld-based dispersion correction" #. Spin polarized, charge, relativity #: ../calculator.py:1164 msgid "Spin / initial moment " msgstr "Spin / initial moment " #: ../calculator.py:1182 msgid " Charge" msgstr " Charge" #: ../calculator.py:1184 msgid " Relativity" msgstr " Relativity" #: ../calculator.py:1186 msgid " Threshold" msgstr " Threshold" #. self-consistency criteria #: ../calculator.py:1191 msgid "Self-consistency convergence:" msgstr "Self-consistency convergence:" #: ../calculator.py:1204 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:1215 msgid "Energy: " msgstr "Energy: " #: ../calculator.py:1217 msgid " eV Sum of eigenvalues: " msgstr " eV Sum of eigenvalues: " #: ../calculator.py:1219 ../calculator.py:1698 msgid " eV" msgstr " eV" #: ../calculator.py:1220 msgid "Electron density: " msgstr "Electron density: " #: ../calculator.py:1222 msgid " Force convergence: " msgstr " Force convergence: " #: ../calculator.py:1224 msgid " eV/Ang " msgstr " eV/Ang " #: ../calculator.py:1237 ../calculator.py:1709 msgid "Additional keywords: " msgstr "Additional keywords: " #. run command and species defaults: #: ../calculator.py:1251 msgid "FHI-aims execution command: " msgstr "FHI-aims execution command: " #: ../calculator.py:1253 ../calculator.py:1726 msgid "Directory for species defaults: " msgstr "Directory for species defaults: " #: ../calculator.py:1265 ../calculator.py:1734 msgid "Set Defaults" msgstr "Set Defaults" #: ../calculator.py:1267 msgid "Import control.in" msgstr "Import control.in" #: ../calculator.py:1269 msgid "Export control.in" msgstr "Export control.in" #: ../calculator.py:1456 msgid "Export parameters ... " msgstr "Export parameters ... " #: ../calculator.py:1476 msgid "Import control.in file ... " msgstr "Import control.in file ... " #: ../calculator.py:1532 ../calculator.py:2041 #, 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:1535 #, 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:1608 msgid "VASP parameters" msgstr "VASP parameters" #: ../calculator.py:1614 msgid "Periodic geometry, unit cell is: \n" msgstr "Periodic geometry, unit cell is: \n" #: ../calculator.py:1666 msgid ") Cutoff: " msgstr ") Cutoff: " #: ../calculator.py:1667 msgid " Precision: " msgstr " Precision: " #: ../calculator.py:1669 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "k-points x size: (%.1f, %.1f, %.1f) Å " #: ../calculator.py:1685 msgid "Smearing: " msgstr "Smearing: " #: ../calculator.py:1687 msgid " order: " msgstr " order: " #: ../calculator.py:1689 msgid " width: " msgstr " width: " #: ../calculator.py:1696 msgid "Self-consistency convergence: " msgstr "Self-consistency convergence: " #. run command and location of POTCAR files: #: ../calculator.py:1722 msgid "VASP execution command: " msgstr "VASP execution command: " #: ../calculator.py:1736 msgid "Import VASP files" msgstr "Import VASP files" #: ../calculator.py:1738 msgid "Export VASP files" msgstr "Export VASP files" #: ../calculator.py:1945 msgid "WARNING: cutoff energy is lower than recommended minimum!" msgstr "WARNING: cutoff energy is lower than recommended minimum!" #: ../calculator.py:1997 msgid "Import VASP input files: choose directory ... " msgstr "Import VASP input files: choose directory ... " #: ../calculator.py:2011 msgid "Export VASP input files: choose directory ... " msgstr "Export VASP input files: choose directory ... " #: ../calculator.py:2044 #, 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:27 msgid "Colors" msgstr "Colours" #. Upper left: Choose how the atoms are colored. #: ../colors.py:44 msgid "Choose how the atoms are colored:" msgstr "Choose how the atoms are coloured:" #: ../colors.py:46 msgid "By atomic number, default \"jmol\" colors" msgstr "By atomic number, default \"jmol\" colours" #: ../colors.py:48 msgid "By atomic number, user specified" msgstr "By atomic number, user specified" #: ../colors.py:49 msgid "By tag" msgstr "By tag" #: ../colors.py:50 msgid "By force" msgstr "By force" #: ../colors.py:51 msgid "By velocity" msgstr "By velocity" #: ../colors.py:52 msgid "By charge" msgstr "By charge" #: ../colors.py:54 msgid "By magnetic moment" msgstr "By magnetic moment" #: ../colors.py:56 msgid "By coordination" msgstr "By coordination" #: ../colors.py:57 msgid "Manually specified" msgstr "Manually specified" #: ../colors.py:58 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:74 msgid "This should not be displayed in forces!" msgstr "This should not be displayed in forces!" #: ../colors.py:79 ../colors.py:93 ../colors.py:108 ../colors.py:124 #: ../rotate.py:25 msgid "Update" msgstr "Update" #: ../colors.py:81 ../colors.py:95 ../colors.py:110 ../colors.py:126 msgid "Min: " msgstr "Min: " #: ../colors.py:83 ../colors.py:97 ../colors.py:112 ../colors.py:128 msgid " Max: " msgstr " Max: " #: ../colors.py:85 ../colors.py:99 ../colors.py:114 ../colors.py:130 msgid " Steps: " msgstr " Steps: " #. Now fill in the box for additional information in case #. the charge is used. #: ../colors.py:106 ../colors.py:122 msgid "This should not be displayed!" msgstr "This should not be displayed!" #: ../colors.py:137 msgid "Create a color scale:" msgstr "Create a colour scale:" #: ../colors.py:140 msgid "Black - white" msgstr "Black - white" #: ../colors.py:141 msgid "Black - red - yellow - white" msgstr "Black - red - yellow - white" #: ../colors.py:142 msgid "Black - green - white" msgstr "Black - green - white" #: ../colors.py:143 msgid "Black - blue - cyan" msgstr "Black - blue - cyan" #: ../colors.py:144 msgid "Blue - white - red" msgstr "Blue - white - red" #: ../colors.py:145 msgid "Hue" msgstr "Hue" #: ../colors.py:146 msgid "Named colors" msgstr "Named colours" #: ../colors.py:152 msgid "Create" msgstr "Create" #: ../colors.py:517 msgid "ERROR" msgstr "ERROR" #: ../colors.py:546 msgid "ERR" msgstr "ERR" #: ../colors.py:638 msgid "Incorrect color specification" msgstr "Incorrect colour specification" #: ../constraints.py:12 ../widgets.py:96 msgid "Constraints" msgstr "Constraints" #: ../constraints.py:14 ../constraints.py:17 ../settings.py:16 #: ../widgets.py:98 ../widgets.py:101 msgid "Constrain" msgstr "Constrain" #: ../constraints.py:15 ../settings.py:19 ../settings.py:34 ../widgets.py:99 msgid " selected atoms" msgstr " selected atoms" #: ../constraints.py:18 ../widgets.py:102 msgid " immobile atoms:" msgstr " immobile atoms:" #: ../constraints.py:20 msgid "Unconstrain" msgstr "Unconstrain" #: ../constraints.py:21 msgid " selected atoms:" msgstr " selected atoms:" #: ../constraints.py:23 msgid "Clear constraints" msgstr "Clear constraints" #: ../constraints.py:25 ../dft.py:28 ../settings.py:52 ../widgets.py:65 #: ../widgets.py:106 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 ../graphene.py:27 #, 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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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:12 msgid "Debug" msgstr "Debug" #: ../dft.py:12 msgid "DFT" msgstr "DFT" #: ../dft.py:18 msgid "XC-functional: " msgstr "XC-functional: " #: ../dft.py:22 ../repeat.py:14 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:22 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: ase-gui window python object\n" " img:\tadvanced: ase-gui 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: ase-gui window python object\n" " img:\tadvanced: ase-gui images object\n" " " #: ../execute.py:66 msgid "Expert user mode" msgstr "Expert user mode" #: ../execute.py:79 msgid "Welcome to the ASE Expert user mode" msgstr "Welcome to the ASE Expert user mode" #: ../execute.py:86 msgid "Only selected atoms (sa) " msgstr "Only selected atoms (sa) " #: ../execute.py:88 msgid "Only current frame (cf) " msgstr "Only current frame (cf) " #: ../execute.py:98 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:197 #, python-format msgid "*** WARNING: file does not exist - %s" msgstr "*** WARNING: file does not exist - %s" #: ../execute.py:202 msgid "*** WARNING: No atoms selected to work with" msgstr "*** WARNING: No atoms selected to work with" #: ../execute.py:276 msgid "*** Only working on selected atoms" msgstr "*** Only working on selected atoms" #: ../execute.py:278 msgid "*** Working on all atoms" msgstr "*** Working on all atoms" #: ../execute.py:282 msgid "*** Only working on current image" msgstr "*** Only working on current image" #: ../execute.py:284 msgid "*** Working on all images" msgstr "*** Working on all images" #: ../execute.py:300 msgid "Save Terminal text ..." msgstr "Save Terminal text ..." #: ../graphene.py:16 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:33 ../gui.py:345 msgid "Graphene" msgstr "Graphene" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "Structure: " #: ../graphene.py:42 msgid "Infinite sheet" msgstr "Infinite sheet" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "Unsaturated ribbon" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "Saturated ribbon" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "Orientation: " #: ../graphene.py:53 msgid "zigzag" msgstr "zigzag" #: ../graphene.py:53 msgid "armchair" msgstr "armchair" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 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:90 msgid "Width: " msgstr "Width: " #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr " Length: " #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "Vacuum: " #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr " No element specified!" #: ../graphene.py:194 msgid "Please specify a consistent set of atoms. " msgstr "Please specify a consistent set of atoms. " #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../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:7 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" #: ../graphs.py:50 ../graphs.py:53 msgid "Plot" msgstr "Plot" #: ../graphs.py:58 msgid "clear" msgstr "clear" #: ../graphs.py:112 msgid "Save data to file ... " msgstr "Save data to file ... " #: ../gtkexcepthook.py:118 msgid "Bug Detected" msgstr "Bug Detected" #: ../gtkexcepthook.py:122 msgid "A programming error has been detected." msgstr "A programming error has been detected." #: ../gtkexcepthook.py:125 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:141 msgid "Report..." msgstr "Report..." #: ../gtkexcepthook.py:145 msgid "Details..." msgstr "Details..." #: ../gtkexcepthook.py:161 #, 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:174 msgid "Bug Details" msgstr "Bug Details" #: ../gui.py:191 msgid "_File" msgstr "_File" #: ../gui.py:192 msgid "_Edit" msgstr "_Edit" #: ../gui.py:193 msgid "_View" msgstr "_View" #: ../gui.py:194 msgid "_Tools" msgstr "_Tools" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:196 msgid "_Setup" msgstr "_Setup" #: ../gui.py:197 msgid "_Calculate" msgstr "_Calculate" #: ../gui.py:198 msgid "_Help" msgstr "_Help" #: ../gui.py:199 msgid "_Open" msgstr "_Open" #: ../gui.py:200 msgid "Create a new file" msgstr "Create a new file" #: ../gui.py:202 msgid "_New" msgstr "_New" #: ../gui.py:203 msgid "New ase.gui window" msgstr "New ase.gui window" #: ../gui.py:205 msgid "_Save" msgstr "_Save" #: ../gui.py:206 msgid "Save current file" msgstr "Save current file" #: ../gui.py:208 msgid "_Quit" msgstr "_Quit" #: ../gui.py:209 msgid "Quit" msgstr "Quit" #: ../gui.py:211 msgid "Select _all" msgstr "Select _all" #: ../gui.py:214 msgid "_Invert selection" msgstr "_Invert selection" #: ../gui.py:217 msgid "Select _constrained atoms" msgstr "Select _constrained atoms" #: ../gui.py:220 msgid "Select _immobile atoms" msgstr "Select _immobile atoms" #: ../gui.py:223 msgid "_Copy" msgstr "_Copy" #: ../gui.py:224 msgid "Copy current selection and its orientation to clipboard" msgstr "Copy current selection and its orientation to clipboard" #: ../gui.py:226 msgid "_Paste" msgstr "_Paste" #: ../gui.py:227 msgid "Insert current clipboard selection" msgstr "Insert current clipboard selection" #: ../gui.py:229 msgid "_Modify" msgstr "_Modify" #: ../gui.py:230 msgid "Change tags, moments and atom types of the selected atoms" msgstr "Change tags, moments and atom types of the selected atoms" #: ../gui.py:232 msgid "_Add atoms" msgstr "_Add atoms" #: ../gui.py:233 msgid "Insert or import atoms and molecules" msgstr "Insert or import atoms and molecules" #: ../gui.py:235 msgid "_Delete selected atoms" msgstr "_Delete selected atoms" #: ../gui.py:236 msgid "Delete the selected atoms" msgstr "Delete the selected atoms" #: ../gui.py:238 msgid "_First image" msgstr "_First image" #: ../gui.py:241 msgid "_Previous image" msgstr "_Previous image" #: ../gui.py:244 msgid "_Next image" msgstr "_Next image" #: ../gui.py:247 msgid "_Last image" msgstr "_Last image" #: ../gui.py:250 msgid "Show _Labels" msgstr "Show _Labels" #: ../gui.py:251 msgid "Hide selected atoms" msgstr "Hide selected atoms" #: ../gui.py:254 msgid "Show selected atoms" msgstr "Show selected atoms" #: ../gui.py:257 msgid "Quick Info ..." msgstr "Quick Info ..." #: ../gui.py:260 msgid "Repeat ..." msgstr "Repeat ..." #: ../gui.py:263 msgid "Rotate ..." msgstr "Rotate ..." #: ../gui.py:266 msgid "Colors ..." msgstr "Colours ..." #. TRANSLATORS: verb #: ../gui.py:269 msgid "Focus" msgstr "Focus" #: ../gui.py:272 msgid "Zoom in" msgstr "Zoom in" #: ../gui.py:275 msgid "Zoom out" msgstr "Zoom out" #: ../gui.py:278 msgid "Change View" msgstr "Change View" #: ../gui.py:279 msgid "Reset View" msgstr "Reset View" #: ../gui.py:282 msgid "'xy' Plane" msgstr "'xy' Plane" #: ../gui.py:283 msgid "'yz' Plane" msgstr "'yz' Plane" #: ../gui.py:284 msgid "'zx' Plane" msgstr "'zx' Plane" #: ../gui.py:285 msgid "'yx' Plane" msgstr "'yx' Plane" #: ../gui.py:286 msgid "'zy' Plane" msgstr "'zy' Plane" #: ../gui.py:287 msgid "'xz' Plane" msgstr "'xz' Plane" #: ../gui.py:288 msgid "'a2 a3' Plane" msgstr "'a2 a3' Plane" #: ../gui.py:289 msgid "'a3 a1' Plane" msgstr "'a3 a1' Plane" #: ../gui.py:290 msgid "'a1 a2' Plane" msgstr "'a1 a2' Plane" #: ../gui.py:291 msgid "'a3 a2' Plane" msgstr "'a3 a2' Plane" #: ../gui.py:292 msgid "'a1 a3' Plane" msgstr "'a1 a3' Plane" #: ../gui.py:293 msgid "'a2 a1' Plane" msgstr "'a2 a1' Plane" #: ../gui.py:294 msgid "Settings ..." msgstr "Settings ..." #: ../gui.py:297 msgid "VMD" msgstr "VMD" #: ../gui.py:300 msgid "RasMol" msgstr "RasMol" #: ../gui.py:303 msgid "xmakemol" msgstr "xmakemol" #: ../gui.py:306 msgid "avogadro" msgstr "avogadro" #: ../gui.py:309 msgid "Graphs ..." msgstr "Graphs ..." #: ../gui.py:312 msgid "Movie ..." msgstr "Film ..." #: ../gui.py:315 msgid "Expert mode ..." msgstr "Expert mode ..." #: ../gui.py:318 msgid "Constraints ..." msgstr "Constraints ..." #: ../gui.py:321 msgid "Render scene ..." msgstr "Render scene ..." #: ../gui.py:324 msgid "DFT ..." msgstr "DFT ..." #: ../gui.py:327 msgid "NE_B" msgstr "NE_B" #: ../gui.py:330 msgid "B_ulk Modulus" msgstr "B_ulk Modulus" #: ../gui.py:333 msgid "_Bulk Crystal" msgstr "_Bulk Crystal" #: ../gui.py:334 msgid "Create a bulk crystal with arbitrary orientation" msgstr "Create a bulk crystal with arbitrary orientation" #: ../gui.py:336 msgid "_Surface slab" msgstr "_Surface slab" #: ../gui.py:337 msgid "Create the most common surfaces" msgstr "Create the most common surfaces" #: ../gui.py:339 msgid "_Nanoparticle" msgstr "_Nanoparticle" #: ../gui.py:340 msgid "Create a crystalline nanoparticle" msgstr "Create a crystalline nanoparticle" #: ../gui.py:342 msgid "Nano_tube" msgstr "Nano_tube" #: ../gui.py:343 msgid "Create a nanotube" msgstr "Create a nanotube" #: ../gui.py:346 msgid "Create a graphene sheet or nanoribbon" msgstr "Create a graphene sheet or nanoribbon" #: ../gui.py:348 msgid "Set _Calculator" msgstr "Set _Calculator" #: ../gui.py:349 msgid "Set a calculator used in all calculation modules" msgstr "Set a calculator used in all calculation modules" #: ../gui.py:351 msgid "_Energy and Forces" msgstr "_Energy and Forces" #: ../gui.py:352 msgid "Calculate energy and forces" msgstr "Calculate energy and forces" #: ../gui.py:354 msgid "Energy _Minimization" msgstr "Energy _Minimisation" #: ../gui.py:355 msgid "Minimize the energy" msgstr "Minimise the energy" #: ../gui.py:357 msgid "Scale system" msgstr "Scale system" #: ../gui.py:358 msgid "Deform system by scaling it" msgstr "Deform system by scaling it" #: ../gui.py:360 msgid "_About" msgstr "_About" #: ../gui.py:363 msgid "Webpage ..." msgstr "Webpage ..." #: ../gui.py:364 msgid "Debug ..." msgstr "Debug ..." #: ../gui.py:366 msgid "Show _unit cell" msgstr "Show _unit cell" #: ../gui.py:370 msgid "Show _axes" msgstr "Show _axes" #: ../gui.py:374 msgid "Show _bonds" msgstr "Show _bonds" #: ../gui.py:378 msgid "Show _velocities" msgstr "Show _velocities" #: ../gui.py:382 msgid "Show _forces" msgstr "Show _forces" #: ../gui.py:386 msgid "_Move atoms" msgstr "_Move atoms" #: ../gui.py:390 msgid "_Rotate atoms" msgstr "_Rotate atoms" #: ../gui.py:394 msgid "Orien_t atoms" msgstr "Orien_t atoms" #: ../gui.py:400 msgid "_None" msgstr "_None" #: ../gui.py:401 msgid "Atom _Index" msgstr "Atom _Index" #: ../gui.py:402 msgid "_Magnetic Moments" msgstr "_Magnetic Moments" #: ../gui.py:403 msgid "_Element Symbol" msgstr "_Element Symbol" #: ../gui.py:412 #, python-format msgid "building menus failed: %s" msgstr "building menus failed: %s" #: ../gui.py:687 ../gui.py:1093 ../gui.py:1153 msgid "Open ..." msgstr "Open ..." #: ../gui.py:691 ../gui.py:1096 msgid "<>" msgstr "<>" #: ../gui.py:824 msgid "Add atoms" msgstr "Add atoms" #: ../gui.py:827 msgid "Paste" msgstr "Paste" #: ../gui.py:833 msgid "Insert atom or molecule" msgstr "Insert atom or molecule" #: ../gui.py:834 ../gui.py:960 msgid "Tag" msgstr "Tag" #: ../gui.py:835 ../gui.py:961 msgid "Moment" msgstr "Moment" #: ../gui.py:836 msgid "Position" msgstr "Position" #: ../gui.py:861 msgid "_Load molecule" msgstr "_Load molecule" #: ../gui.py:865 ../gui.py:976 msgid "_OK" msgstr "_OK" #: ../gui.py:869 ../gui.py:980 msgid "_Cancel" msgstr "_Cancel" #: ../gui.py:953 msgid "Modify" msgstr "Modify" #: ../gui.py:959 msgid "Atom" msgstr "Atom" #: ../gui.py:1004 msgid "Confirmation" msgstr "Confirmation" #: ../gui.py:1008 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "Delete selected atom?" msgstr[1] "Delete selected atoms?" #: ../gui.py:1015 msgid "Cancel" msgstr "Cancel" #: ../gui.py:1101 msgid "Automatic" msgstr "Automatic" #: ../gui.py:1102 msgid "Dacapo netCDF output file" msgstr "Dacapo netCDF output file" #: ../gui.py:1103 msgid "Virtual Nano Lab file" msgstr "Virtual Nano Lab file" #: ../gui.py:1104 msgid "ASE pickle trajectory" msgstr "ASE pickle trajectory" #: ../gui.py:1105 msgid "ASE bundle trajectory" msgstr "ASE bundle trajectory" #: ../gui.py:1106 msgid "GPAW text output" msgstr "GPAW text output" #: ../gui.py:1107 msgid "CUBE file" msgstr "CUBE file" #: ../gui.py:1108 msgid "XCrySDen Structure File" msgstr "XCrySDen Structure File" #: ../gui.py:1109 msgid "Dacapo text output" msgstr "Dacapo text output" #: ../gui.py:1110 msgid "XYZ-file" msgstr "XYZ-file" #: ../gui.py:1111 msgid "VASP POSCAR/CONTCAR file" msgstr "VASP POSCAR/CONTCAR file" #: ../gui.py:1112 msgid "VASP OUTCAR file" msgstr "VASP OUTCAR file" #: ../gui.py:1113 msgid "Protein Data Bank" msgstr "Protein Data Bank" #: ../gui.py:1114 msgid "CIF-file" msgstr "CIF-file" #: ../gui.py:1115 msgid "FHI-aims geometry file" msgstr "FHI-aims geometry file" #: ../gui.py:1116 msgid "FHI-aims output file" msgstr "FHI-aims output file" #: ../gui.py:1117 msgid "TURBOMOLE coord file" msgstr "TURBOMOLE coord file" #: ../gui.py:1118 msgid "exciting input" msgstr "exciting input" #: ../gui.py:1119 msgid "WIEN2k structure file" msgstr "WIEN2k structure file" #: ../gui.py:1120 msgid "DftbPlus input file" msgstr "DftbPlus input file" #: ../gui.py:1121 msgid "ETSF format" msgstr "ETSF format" #: ../gui.py:1122 msgid "CASTEP geom file" msgstr "CASTEP geom file" #: ../gui.py:1123 msgid "CASTEP output file" msgstr "CASTEP output file" #: ../gui.py:1124 msgid "CASTEP trajectory file" msgstr "CASTEP trajectory file" #: ../gui.py:1125 msgid "DFTBPlus GEN format" msgstr "DFTBPlus GEN format" #: ../gui.py:1131 msgid "File type:" msgstr "File type:" #: ../gui.py:1254 msgid "Not implemented!" msgstr "Not implemented!" #: ../gui.py:1255 msgid "do you really need it?" msgstr "do you really need it?" #: ../minimize.py:21 msgid "Algorithm: " msgstr "Algorithm: " #: ../minimize.py:26 ../progress.py:68 msgid "Convergence criterion: Fmax = " msgstr "Convergence criterion: Fmax = " #: ../minimize.py:31 ../progress.py:71 msgid "Max. number of steps: " msgstr "Max. number of steps: " #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "Pseudo time step: " #: ../minimize.py:55 msgid "Energy minimization" msgstr "Energy minimisation" #: ../minimize.py:59 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:91 ../scaling.py:301 msgid "Running ..." msgstr "Running ..." #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "Minimisation CANCELLED after %i steps." #: ../minimize.py:114 ../scaling.py:352 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:121 #, python-format msgid "Minimization completed in %i steps." msgstr "Minimisation completed in %i steps." #. self.connect('delete_event', self.exit2) #: ../movie.py:13 msgid "Movie" msgstr "Film" #: ../movie.py:15 msgid "Image number:" msgstr "Image number:" #: ../movie.py:37 msgid "Play" msgstr "Play" #: ../movie.py:39 msgid "Stop" msgstr "Stop" #. TRANSLATORS: This function plays an animation forwards and backwards #. alternatingly, e.g. for displaying vibrational movement #: ../movie.py:43 msgid "Rock" msgstr "Rock" #: ../movie.py:59 msgid " Frame rate: " msgstr " Frame rate: " #: ../movie.py:60 msgid " Skip frames: " msgstr " Skip frames: " #: ../nanoparticle.py:20 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:27 #, python-brace-format 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:84 msgid "Face centered cubic (fcc)" msgstr "Face centered cubic (fcc)" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "Body centered cubic (bcc)" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "Simple cubic (sc)" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "Hexagonal closed-packed (hcp)" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "Graphite" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "Nanoparticle" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "Element: " #: ../nanoparticle.py:131 msgid "Get structure" msgstr "Get structure" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "Lattice constant: a =" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "Method: " #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "Layer specification" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "Wulff construction" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "Dummy placeholder object" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "Add new direction:" #: ../nanoparticle.py:212 msgid "Add" msgstr "Add" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "Set all directions to default values" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "Particle size: " #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:197 msgid "Number of atoms: " msgstr "Number of atoms: " #: ../nanoparticle.py:234 msgid "Volume: " msgstr "Volume: " #: ../nanoparticle.py:239 msgid "ų" msgstr "ų" #: ../nanoparticle.py:244 msgid "Rounding: If exact size is not possible, choose the size" msgstr "Rounding: If exact size is not possible, choose the size" #: ../nanoparticle.py:247 msgid "above " msgstr "above " #: ../nanoparticle.py:248 msgid "below " msgstr "below " #: ../nanoparticle.py:249 msgid "closest " msgstr "closest " #: ../nanoparticle.py:252 msgid "Smaller" msgstr "Smaller" #: ../nanoparticle.py:253 msgid "Larger" msgstr "Larger" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr " Approx. diameter: " #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "Information about the created cluster:" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "Creating a nanoparticle." #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "Automatic Apply" #: ../nanoparticle.py:333 msgid "Up" msgstr "Up" #: ../nanoparticle.py:338 msgid "Down" msgstr "Down" #: ../nanoparticle.py:343 msgid "Delete" msgstr "Delete" #: ../nanoparticle.py:384 msgid "Surface energies (as energy/area, NOT per atom):" msgstr "Surface energies (as energy/area, NOT per atom):" #: ../nanoparticle.py:390 msgid "Number of layers:" msgstr "Number of layers:" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "At least one index must be non-zero" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "Invalid hexagonal indices" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "Invalid element." #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "Unsupported or unknown structure" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "%.1f Å" #: ../nanotube.py:15 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:29 #, python-format msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: " "%(volume).3f Å3" msgstr "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: " "%(volume).3f Å3" #: ../nanotube.py:35 msgid "Nanotube" msgstr "Nanotube" #. Choose the structure. #: ../nanotube.py:59 msgid "Select roll-up vector (n,m) and tube length:" msgstr "Select roll-up vector (n,m) and tube length:" #: ../progress.py:26 msgid "Progress" msgstr "Progress" #: ../progress.py:33 msgid "Scaling deformation:" msgstr "Scaling deformation:" #: ../progress.py:39 #, python-format msgid "Step number %s of %s." msgstr "Step number %s of %s." #. Minimization progress frame #. Box containing frame and spacing #: ../progress.py:54 msgid "Energy minimization:" msgstr "Energy minimisation:" #: ../progress.py:61 msgid "Step number: " msgstr "Step number: " #: ../progress.py:63 msgid "Fmax: " msgstr "Fmax: " #: ../progress.py:103 msgid "unknown" msgstr "unknown" #: ../progress.py:180 msgid "Status: " msgstr "Status: " #: ../progress.py:182 msgid "Iteration: " msgstr "Iteration: " #: ../progress.py:185 msgid "log10(change):" msgstr "log10(change):" #: ../progress.py:188 msgid "Wave functions: " msgstr "Wave functions: " #: ../progress.py:190 msgid "Density: " msgstr "Density: " #: ../progress.py:192 msgid "Energy: " msgstr "Energy: " #: ../progress.py:195 msgid "GPAW version: " msgstr "GPAW version: " #: ../progress.py:198 msgid "N/A" msgstr "N/A" #: ../progress.py:199 msgid "Memory estimate: " msgstr "Memory estimate: " #: ../progress.py:234 msgid "No info" msgstr "No info" #: ../progress.py:244 msgid "Initializing" msgstr "Initializing" #: ../progress.py:245 msgid "Positions:" msgstr "Positions:" #: ../progress.py:249 msgid "Starting calculation" msgstr "Starting calculation" #: ../progress.py:286 msgid "unchanged" msgstr "unchanged" #: ../progress.py:296 msgid "Self-consistency loop" msgstr "Self-consistency loop" #: ../progress.py:301 msgid "Calculating forces" msgstr "Calculating forces" #: ../progress.py:302 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" "\n" "%s\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" "\n" "%s\n" "%s\n" #: ../quickinfo.py:31 msgid "Quick Info" msgstr "Quick Info" #: ../quickinfo.py:35 msgid "No atoms loaded." msgstr "No atoms loaded." #: ../quickinfo.py:56 msgid "no" msgstr "no" #: ../quickinfo.py:56 msgid "yes" msgstr "yes" #. TRANSLATORS: This has the form Periodic: no, no, yes #: ../quickinfo.py:60 #, python-format msgid "Periodic: %s, %s, %s" msgstr "Periodic: %s, %s, %s" #: ../render.py:15 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:33 msgid "Render current view in povray ... " msgstr "Render current view in povray ... " #: ../render.py:37 #, python-format msgid "Rendering %d atoms." msgstr "Rendering %d atoms." #: ../render.py:42 msgid "Render constraints" msgstr "Render constraints" #: ../render.py:45 msgid "Width" msgstr "Width" #: ../render.py:46 msgid " Height" msgstr " Height" #: ../render.py:53 msgid "Render unit cell" msgstr "Render unit cell" #: ../render.py:62 msgid "Line width" msgstr "Line width" #: ../render.py:64 msgid "Angstrom " msgstr "Angstrom " #: ../render.py:74 msgid "Set" msgstr "Set" #: ../render.py:76 msgid "Output basename: " msgstr "Output basename: " #: ../render.py:78 msgid " Filename: " msgstr " Filename: " #: ../render.py:89 msgid " Default texture for atoms: " msgstr " Default texture for atoms: " #: ../render.py:90 msgid " transparency: " msgstr " transparency: " #: ../render.py:91 msgid "Define atom selection for new texture:" msgstr "Define atom selection for new texture:" #: ../render.py:93 msgid "Select" msgstr "Select" #: ../render.py:97 msgid "Create new texture from selection" msgstr "Create new texture from selection" #: ../render.py:99 msgid "Help on textures" msgstr "Help on textures" #: ../render.py:112 msgid "Camera type: " msgstr "Camera type: " #: ../render.py:113 msgid " Camera distance" msgstr " Camera distance" #: ../render.py:114 msgid "Render current frame" msgstr "Render current frame" #: ../render.py:118 #, python-format msgid "Render all %d frames" msgstr "Render all %d frames" #: ../render.py:123 msgid "Transparent background" msgstr "Transparent background" #: ../render.py:126 msgid "Run povray " msgstr "Run povray " #: ../render.py:129 msgid "Keep povray files " msgstr "Keep povray files " #: ../render.py:132 msgid "Show output window" msgstr "Show output window" #: ../render.py:213 msgid " transparency: " msgstr " transparency: " #: ../render.py:219 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:12 msgid "Repeat" msgstr "Repeat" #: ../repeat.py:19 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:150 msgid "2nd" msgstr "2nd" #: ../scaling.py:151 msgid "3rd" msgstr "3rd" #: ../scaling.py:155 msgid "Order of fit: " msgstr "Order of fit: " #. Update display to reflect cancellation of simulation. #: ../scaling.py:348 msgid "Calculation CANCELLED." msgstr "Calculation CANCELLED." #. Update display to reflect succesful end of simulation. #: ../scaling.py:359 msgid "Calculation completed." msgstr "Calculation completed." #: ../scaling.py:382 msgid "No trustworthy minimum: Old configuration kept." msgstr "No trustworthy minimum: Old configuration kept." #: ../scaling.py:422 #, 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:426 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:442 msgid "No minimum found!" msgstr "No minimum found!" #: ../scaling.py:456 msgid "" "\n" "WARNING: Minimum is outside interval\n" msgstr "" "\n" "WARNING: Minimum is outside interval\n" #: ../scaling.py:457 msgid "It is UNRELIABLE!\n" msgstr "It is UNRELIABLE!\n" #: ../settings.py:15 msgid "Constraints:" msgstr "Constraints:" #: ../settings.py:18 msgid "release" msgstr "release" #: ../settings.py:22 msgid "Constrain immobile atoms" msgstr "Constrain immobile atoms" #: ../settings.py:24 msgid "Clear all constraints" msgstr "Clear all constraints" #: ../settings.py:30 msgid "Visibility:" msgstr "Visibility:" #: ../settings.py:31 msgid "Hide" msgstr "Hide" #: ../settings.py:33 msgid "show" msgstr "show" #: ../settings.py:37 msgid "View all atoms" msgstr "View all atoms" #: ../settings.py:43 msgid "Miscellaneous:" msgstr "Miscellaneous:" #: ../settings.py:46 msgid "Scale atomic radii:" msgstr "Scale atomic radii:" #. A close button #: ../settings.py:51 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:36 ../status.py:38 msgid "Tip for status box ..." msgstr "Tip for status box ..." #. TRANSLATORS: mom refers to magnetic moment #: ../status.py:62 #, python-format msgid " tag=%(tag)s mom=%(mom)1.2f" msgstr " tag=%(tag)s mom=%(mom)1.2f" #: ../status.py:103 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:58 ../widgets.py:87 msgid "Help" msgstr "Help" #: ../widgets.py:104 msgid "Clear constraint" msgstr "Clear constraint" #~ 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." #~ msgid "Max force: %.2f (this frame), %.2f (all frames)" #~ msgstr "Max force: %.2f (this frame), %.2f (all frames)" #~ msgid "Max force: %.2f." #~ msgstr "Max force: %.2f." #~ msgid "Max velocity: %.2f (this frame), %.2f (all frames)" #~ msgstr "Max velocity: %.2f (this frame), %.2f (all frames)" #~ msgid "Max velocity: %.2f." #~ msgstr "Max velocity: %.2f." #~ msgid "Min, max charge: %.2f, %.2f (this frame)," #~ msgstr "Min, max charge: %.2f, %.2f (this frame)," #~ msgid "Min, max charge: %.2f, %.2f." #~ msgstr "Min, max charge: %.2f, %.2f." #~ msgid "Save ..." #~ msgstr "Save ..." #~ msgid "XYZ file" #~ msgstr "XYZ file" #~ msgid "ASE trajectory" #~ msgstr "ASE trajectory" #~ msgid "PDB file" #~ msgstr "PDB file" #~ msgid "Gaussian cube file" #~ msgstr "Gaussian cube file" #~ msgid "Python script" #~ msgstr "Python script" #~ msgid "VNL file" #~ msgstr "VNL file" #~ msgid "Portable Network Graphics" #~ msgstr "Portable Network Graphics" #~ msgid "Persistence of Vision" #~ msgstr "Persistence of Vision" #~ msgid "Encapsulated PostScript" #~ msgstr "Encapsulated PostScript" #~ msgid "FHI-aims geometry input" #~ msgstr "FHI-aims geometry input" #~ msgid "VASP geometry input" #~ msgstr "VASP geometry input" #~ msgid "cif file" #~ msgstr "cif file" #~ msgid "Save current image only (#%d)" #~ msgstr "Save current image only (#%d)" #~ msgid "Slice: " #~ msgstr "Slice: " #~ msgid "Help for slice ..." #~ msgstr "Help for slice ..." #~ msgid "ase-gui INTERNAL ERROR: strange response in Save," #~ msgstr "ase-gui INTERNAL ERROR: strange response in Save," #~ msgid "Unknown output format!" #~ msgstr "Unknown output format!" #~ msgid "Use one of: %s" #~ msgstr "Use one of: %s" #~ 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.9.1.4567/ase/gui/po/makefile0000664000175000017500000000456712553425527020165 0ustar jensjjensj00000000000000# This makefile is used to update templates for internationalization ("i18n") # of ase-gui. # 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 # # After writing translations, you need to run 'make' again to generate the # binary translation files loaded by the programme. # # Then you can run 'LANG=de_DE.UTF8 ase-gui' and your translations should be # visible if you have a developer installation. # # For distutils installation, the po-files are globbed from setup.py so # they are automatically included when you run install. # 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 --msgid-bugs-address=ase-developers@listserv.fysik.dtu.dk --copyright-holder=CAMD --package-name=ase ${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 --previous --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 \ echo Checking $$DIR/ag.po ;\ msgfmt -cv --output-file=$$DIR/ag.mo $$DIR/ag.po ;\ done python-ase-3.9.1.4567/ase/gui/po/pl/0000775000175000017500000000000012553427753017067 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/pl/LC_MESSAGES/0000775000175000017500000000000012553427753020654 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/pl/LC_MESSAGES/ag.po0000664000175000017500000015132612553425527021610 0ustar jensjjensj00000000000000# Polish translations for PACKAGE package. # Copyright (C) 2012 CAMD # This file is distributed under the same license as the PACKAGE package. # Ask Hjorth Larsen , 2012. # msgid "" msgstr "" "Project-Id-Version: ase\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2012-09-10 15:12+0200\n" "PO-Revision-Date: 2012-07-23 16:20+0200\n" "Last-Translator: Ask Hjorth Larsen \n" "Language-Team: Polish\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" #: ../ag.py:136 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:452 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:470 ../calculator.py:482 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "" #: ../calculator.py:473 msgid "You must set up the GPAW parameters" msgstr "" #: ../calculator.py:514 msgid "You must set up the FHI-aims parameters" msgstr "" #: ../calculator.py:528 msgid "You must set up the VASP parameters" msgstr "" #: ../calculator.py:552 #, python-format msgid "Element %(sym)s not allowed by the '%(name)s' calculator" msgstr "" #: ../calculator.py:559 msgid "Info" msgstr "" #: ../calculator.py:575 msgid "Lennard-Jones parameters" msgstr "" #: ../calculator.py:587 msgid "Specify the Lennard-Jones parameters here" msgstr "" #: ../calculator.py:590 msgid "Epsilon (eV):" msgstr "" #: ../calculator.py:594 msgid "Sigma (Å):" msgstr "" #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:598 msgid "Shift to make smooth at cutoff" msgstr "" #: ../calculator.py:679 msgid "GPAW parameters" msgstr "" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:694 ../calculator.py:983 ../calculator.py:1471 #, python-format msgid "%i atoms.\n" msgstr "" #: ../calculator.py:696 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "" #: ../calculator.py:698 msgid "Non-orthogonal unit cell:\n" msgstr "" #: ../calculator.py:708 ../calculator.py:999 ../calculator.py:1486 msgid "Exchange-correlation functional: " msgstr "" #. Grid spacing #: ../calculator.py:712 msgid "Grid spacing" msgstr "" #: ../calculator.py:716 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "" #: ../calculator.py:717 msgid "Grid points" msgstr "" #: ../calculator.py:726 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "" #: ../calculator.py:752 ../calculator.py:1014 ../calculator.py:1522 msgid "k-points k = (" msgstr "" #: ../calculator.py:756 ../calculator.py:1018 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "" #. Spin polarized #: ../calculator.py:761 ../calculator.py:1484 msgid "Spin polarized" msgstr "" #: ../calculator.py:767 msgid "FD - Finite Difference (grid) mode" msgstr "" #: ../calculator.py:768 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "" #: ../calculator.py:771 msgid "Mode: " msgstr "" #: ../calculator.py:773 msgid "sz - Single Zeta" msgstr "" #: ../calculator.py:774 msgid "szp - Single Zeta polarized" msgstr "" #: ../calculator.py:775 msgid "dzp - Double Zeta polarized" msgstr "" #. dzp #: ../calculator.py:777 msgid "Basis functions: " msgstr "" #. Mixer #: ../calculator.py:783 msgid "Non-standard mixer parameters" msgstr "" #: ../calculator.py:979 msgid "FHI-aims parameters" msgstr "" #: ../calculator.py:986 msgid "Periodic geometry, unit cell is:\n" msgstr "" #: ../calculator.py:991 msgid "Non-periodic geometry.\n" msgstr "" #: ../calculator.py:998 msgid "Hirshfeld-based dispersion correction" msgstr "" #. Spin polarized, charge, relativity #: ../calculator.py:1024 msgid "Spin / initial moment " msgstr "" #: ../calculator.py:1042 msgid " Charge" msgstr "" #: ../calculator.py:1044 msgid " Relativity" msgstr "" #: ../calculator.py:1046 msgid " Threshold" msgstr "" #. self-consistency criteria #: ../calculator.py:1051 msgid "Self-consistency convergence:" msgstr "" #: ../calculator.py:1064 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:1075 msgid "Energy: " msgstr "" #: ../calculator.py:1077 msgid " eV Sum of eigenvalues: " msgstr "" #: ../calculator.py:1079 ../calculator.py:1557 msgid " eV" msgstr "" #: ../calculator.py:1080 msgid "Electron density: " msgstr "" #: ../calculator.py:1082 msgid " Force convergence: " msgstr "" #: ../calculator.py:1084 msgid " eV/Ang " msgstr "" #: ../calculator.py:1097 ../calculator.py:1568 msgid "Additional keywords: " msgstr "" #. run command and species defaults: #: ../calculator.py:1111 msgid "FHI-aims execution command: " msgstr "" #: ../calculator.py:1113 ../calculator.py:1585 msgid "Directory for species defaults: " msgstr "" #: ../calculator.py:1125 ../calculator.py:1593 msgid "Set Defaults" msgstr "" #: ../calculator.py:1127 msgid "Import control.in" msgstr "" #: ../calculator.py:1129 msgid "Export control.in" msgstr "" #: ../calculator.py:1315 msgid "Export parameters ... " msgstr "" #: ../calculator.py:1335 msgid "Import control.in file ... " msgstr "" #: ../calculator.py:1391 ../calculator.py:1903 #, python-format msgid "" "Please use the facilities provided in this window to manipulate the keyword: " "%s!" msgstr "" #: ../calculator.py:1394 #, 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:1467 msgid "VASP parameters" msgstr "" #: ../calculator.py:1473 msgid "Periodic geometry, unit cell is: \n" msgstr "" #: ../calculator.py:1525 msgid ") Cutoff: " msgstr "" #: ../calculator.py:1526 msgid " Precision: " msgstr "" #: ../calculator.py:1528 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "" #: ../calculator.py:1544 msgid "Smearing: " msgstr "" #: ../calculator.py:1546 msgid " order: " msgstr "" #: ../calculator.py:1548 msgid " width: " msgstr "" #: ../calculator.py:1555 msgid "Self-consistency convergence: " msgstr "" #. run command and location of POTCAR files: #: ../calculator.py:1581 msgid "VASP execution command: " msgstr "" #: ../calculator.py:1595 msgid "Import VASP files" msgstr "" #: ../calculator.py:1597 msgid "Export VASP files" msgstr "" #: ../calculator.py:1806 msgid "WARNING: cutoff energy is lower than recommended minimum!" msgstr "" #: ../calculator.py:1858 msgid "Import VASP input files: choose directory ... " msgstr "" #: ../calculator.py:1873 msgid "Export VASP input files: choose directory ... " msgstr "" #: ../calculator.py:1906 #, 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:90 msgid "Constraints" msgstr "" #: ../constraints.py:15 ../constraints.py:18 ../settings.py:17 #: ../widgets.py:92 ../widgets.py:95 msgid "Constrain" msgstr "" #: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:93 msgid " selected atoms" msgstr "" #: ../constraints.py:19 ../widgets.py:96 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:100 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 ../graphene.py:27 #, 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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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: ase-gui window python object\n" " img:\tadvanced: ase-gui 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:16 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:33 ../gui.py:316 msgid "Graphene" msgstr "" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "" #: ../graphene.py:42 msgid "Infinite sheet" msgstr "" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "" #: ../graphene.py:53 msgid "zigzag" msgstr "" #: ../graphene.py:53 msgid "armchair" msgstr "" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 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:90 msgid "Width: " msgstr "" #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr "" #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "" #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr "" #: ../graphene.py:194 msgid "Please specify a consistent set of atoms. " msgstr "" #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../pybutton.py:49 ../surfaceslab.py:249 msgid "You have not (yet) specified a consistent set of parameters." msgstr "" #: ../graphs.py:9 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" #: ../graphs.py:52 ../graphs.py:55 msgid "Plot" msgstr "" #: ../graphs.py:60 msgid "clear" msgstr "" #: ../graphs.py:114 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:175 msgid "_File" msgstr "" #: ../gui.py:176 msgid "_Edit" msgstr "" #: ../gui.py:177 msgid "_View" msgstr "" #: ../gui.py:178 msgid "_Tools" msgstr "" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:180 msgid "_Setup" msgstr "" #: ../gui.py:181 msgid "_Calculate" msgstr "" #: ../gui.py:182 msgid "_Help" msgstr "" #: ../gui.py:183 msgid "_Open" msgstr "" #: ../gui.py:184 msgid "Create a new file" msgstr "" #: ../gui.py:186 msgid "_New" msgstr "" #: ../gui.py:187 msgid "New ase.gui window" msgstr "" #: ../gui.py:189 msgid "_Save" msgstr "" #: ../gui.py:190 msgid "Save current file" msgstr "" #: ../gui.py:192 msgid "_Quit" msgstr "" #: ../gui.py:193 msgid "Quit" msgstr "" #: ../gui.py:195 msgid "Select _all" msgstr "" #: ../gui.py:198 msgid "_Invert selection" msgstr "" #: ../gui.py:201 msgid "Select _constrained atoms" msgstr "" #: ../gui.py:204 msgid "Select _immobile atoms" msgstr "" #: ../gui.py:207 msgid "_Copy" msgstr "" #: ../gui.py:208 msgid "Copy current selection and its orientation to clipboard" msgstr "" #: ../gui.py:210 msgid "_Paste" msgstr "" #: ../gui.py:211 msgid "Insert current clipboard selection" msgstr "" #: ../gui.py:213 msgid "_Modify" msgstr "" #: ../gui.py:214 msgid "Change tags, moments and atom types of the selected atoms" msgstr "" #: ../gui.py:216 msgid "_Add atoms" msgstr "" #: ../gui.py:217 msgid "Insert or import atoms and molecules" msgstr "" #: ../gui.py:219 msgid "_Delete selected atoms" msgstr "" #: ../gui.py:220 msgid "Delete the selected atoms" msgstr "" #: ../gui.py:222 msgid "_First image" msgstr "" #: ../gui.py:225 msgid "_Previous image" msgstr "" #: ../gui.py:228 msgid "_Next image" msgstr "" #: ../gui.py:231 msgid "_Last image" msgstr "" #: ../gui.py:234 msgid "Show _Labels" msgstr "" #: ../gui.py:235 msgid "Hide selected atoms" msgstr "" #: ../gui.py:238 msgid "Show selected atoms" msgstr "" #: ../gui.py:241 msgid "Quick Info ..." msgstr "" #: ../gui.py:244 msgid "Repeat ..." msgstr "" #: ../gui.py:247 msgid "Rotate ..." msgstr "" #: ../gui.py:250 msgid "Colors ..." msgstr "" #. TRANSLATORS: verb #: ../gui.py:253 msgid "Focus" msgstr "" #: ../gui.py:256 msgid "Zoom in" msgstr "" #: ../gui.py:259 msgid "Zoom out" msgstr "" #: ../gui.py:262 msgid "Reset View" msgstr "" #: ../gui.py:265 msgid "Settings ..." msgstr "" #: ../gui.py:268 msgid "VMD" msgstr "" #: ../gui.py:271 msgid "RasMol" msgstr "" #: ../gui.py:274 msgid "xmakemol" msgstr "" #: ../gui.py:277 msgid "avogadro" msgstr "" #: ../gui.py:280 msgid "Graphs ..." msgstr "" #: ../gui.py:283 msgid "Movie ..." msgstr "" #: ../gui.py:286 msgid "Expert mode ..." msgstr "" #: ../gui.py:289 msgid "Constraints ..." msgstr "" #: ../gui.py:292 msgid "Render scene ..." msgstr "" #: ../gui.py:295 msgid "DFT ..." msgstr "" #: ../gui.py:298 msgid "NE_B" msgstr "" #: ../gui.py:301 msgid "B_ulk Modulus" msgstr "" #: ../gui.py:304 msgid "_Bulk Crystal" msgstr "" #: ../gui.py:305 msgid "Create a bulk crystal with arbitrary orientation" msgstr "" #: ../gui.py:307 msgid "_Surface slab" msgstr "" #: ../gui.py:308 msgid "Create the most common surfaces" msgstr "" #: ../gui.py:310 msgid "_Nanoparticle" msgstr "" #: ../gui.py:311 msgid "Create a crystalline nanoparticle" msgstr "" #: ../gui.py:313 msgid "Nano_tube" msgstr "" #: ../gui.py:314 msgid "Create a nanotube" msgstr "" #: ../gui.py:317 msgid "Create a graphene sheet or nanoribbon" msgstr "" #: ../gui.py:319 msgid "Set _Calculator" msgstr "" #: ../gui.py:320 msgid "Set a calculator used in all calculation modules" msgstr "" #: ../gui.py:322 msgid "_Energy and Forces" msgstr "" #: ../gui.py:323 msgid "Calculate energy and forces" msgstr "" #: ../gui.py:325 msgid "Energy _Minimization" msgstr "" #: ../gui.py:326 msgid "Minimize the energy" msgstr "" #: ../gui.py:328 msgid "Scale system" msgstr "" #: ../gui.py:329 msgid "Deform system by scaling it" msgstr "" #: ../gui.py:331 msgid "_About" msgstr "" #: ../gui.py:334 msgid "Webpage ..." msgstr "" #: ../gui.py:335 msgid "Debug ..." msgstr "" #: ../gui.py:337 msgid "Show _unit cell" msgstr "" #: ../gui.py:341 msgid "Show _axes" msgstr "" #: ../gui.py:345 msgid "Show _bonds" msgstr "" #: ../gui.py:349 msgid "Show _velocities" msgstr "" #: ../gui.py:353 msgid "Show _forces" msgstr "" #: ../gui.py:357 msgid "_Move atoms" msgstr "" #: ../gui.py:361 msgid "_Rotate atoms" msgstr "" #: ../gui.py:365 msgid "Orien_t atoms" msgstr "" #: ../gui.py:371 msgid "_None" msgstr "" #: ../gui.py:372 msgid "Atom _Index" msgstr "" #: ../gui.py:373 msgid "_Magnetic Moments" msgstr "" #: ../gui.py:374 msgid "_Element Symbol" msgstr "" #: ../gui.py:383 #, python-format msgid "building menus failed: %s" msgstr "" #: ../gui.py:658 ../gui.py:1064 ../gui.py:1124 msgid "Open ..." msgstr "" #: ../gui.py:662 ../gui.py:1067 msgid "<>" msgstr "" #: ../gui.py:795 msgid "Add atoms" msgstr "" #: ../gui.py:798 msgid "Paste" msgstr "" #: ../gui.py:804 msgid "Insert atom or molecule" msgstr "" #: ../gui.py:805 ../gui.py:931 msgid "Tag" msgstr "" #: ../gui.py:806 ../gui.py:932 msgid "Moment" msgstr "" #: ../gui.py:807 msgid "Position" msgstr "" #: ../gui.py:832 msgid "_Load molecule" msgstr "" #: ../gui.py:836 ../gui.py:947 msgid "_OK" msgstr "" #: ../gui.py:840 ../gui.py:951 msgid "_Cancel" msgstr "" #: ../gui.py:924 msgid "Modify" msgstr "" #: ../gui.py:930 msgid "Atom" msgstr "" #: ../gui.py:975 msgid "Confirmation" msgstr "" #: ../gui.py:979 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: ../gui.py:986 msgid "Cancel" msgstr "" #: ../gui.py:1072 ../gui.py:1154 msgid "Automatic" msgstr "" #: ../gui.py:1073 msgid "Dacapo netCDF output file" msgstr "" #: ../gui.py:1074 msgid "Virtual Nano Lab file" msgstr "" #: ../gui.py:1075 msgid "ASE pickle trajectory" msgstr "" #: ../gui.py:1076 ../gui.py:1167 msgid "ASE bundle trajectory" msgstr "" #: ../gui.py:1077 msgid "GPAW text output" msgstr "" #: ../gui.py:1078 msgid "CUBE file" msgstr "" #: ../gui.py:1079 msgid "XCrySDen Structure File" msgstr "" #: ../gui.py:1080 msgid "Dacapo text output" msgstr "" #: ../gui.py:1081 msgid "XYZ-file" msgstr "" #: ../gui.py:1082 msgid "VASP POSCAR/CONTCAR file" msgstr "" #: ../gui.py:1083 msgid "VASP OUTCAR file" msgstr "" #: ../gui.py:1084 msgid "Protein Data Bank" msgstr "" #: ../gui.py:1085 msgid "CIF-file" msgstr "" #: ../gui.py:1086 msgid "FHI-aims geometry file" msgstr "" #: ../gui.py:1087 msgid "FHI-aims output file" msgstr "" #: ../gui.py:1088 msgid "TURBOMOLE coord file" msgstr "" #: ../gui.py:1089 msgid "exciting input" msgstr "" #: ../gui.py:1090 msgid "WIEN2k structure file" msgstr "" #: ../gui.py:1091 msgid "DftbPlus input file" msgstr "" #: ../gui.py:1092 msgid "ETSF format" msgstr "" #: ../gui.py:1093 ../gui.py:1165 msgid "CASTEP geom file" msgstr "" #: ../gui.py:1094 msgid "CASTEP output file" msgstr "" #: ../gui.py:1095 msgid "CASTEP trajectory file" msgstr "" #: ../gui.py:1096 msgid "DFTBPlus GEN format" msgstr "" #: ../gui.py:1102 msgid "File type:" msgstr "" #: ../gui.py:1142 msgid "Save ..." msgstr "" #: ../gui.py:1155 msgid "XYZ file" msgstr "" #: ../gui.py:1156 msgid "ASE trajectory" msgstr "" #: ../gui.py:1157 msgid "PDB file" msgstr "" #: ../gui.py:1158 msgid "Gaussian cube file" msgstr "" #: ../gui.py:1159 msgid "Python script" msgstr "" #: ../gui.py:1160 msgid "VNL file" msgstr "" #: ../gui.py:1161 msgid "Portable Network Graphics" msgstr "" #: ../gui.py:1162 msgid "Persistence of Vision" msgstr "" #: ../gui.py:1163 msgid "Encapsulated PostScript" msgstr "" #: ../gui.py:1164 msgid "FHI-aims geometry input" msgstr "" #: ../gui.py:1166 msgid "VASP geometry input" msgstr "" #: ../gui.py:1168 msgid "cif file" msgstr "" #: ../gui.py:1190 #, python-format msgid "Save current image only (#%d)" msgstr "" #: ../gui.py:1194 msgid "Slice: " msgstr "" #: ../gui.py:1195 msgid "Help for slice ..." msgstr "" #: ../gui.py:1207 msgid "ase-gui INTERNAL ERROR: strange response in Save," msgstr "" #: ../gui.py:1226 msgid "Unknown output format!" msgstr "" #: ../gui.py:1227 #, python-format msgid "Use one of: %s" msgstr "" #: ../gui.py:1332 msgid "Not implemented!" msgstr "" #: ../gui.py:1333 msgid "do you really need it?" msgstr "" #: ../minimize.py:21 msgid "Algorithm: " msgstr "" #: ../minimize.py:26 ../progress.py:67 msgid "Convergence criterion: Fmax = " msgstr "" #: ../minimize.py:31 ../progress.py:70 msgid "Max. number of steps: " msgstr "" #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "" #: ../minimize.py:55 msgid "Energy minimization" msgstr "" #: ../minimize.py:59 msgid "Minimize the energy with respect to the positions." msgstr "" #. Don't catch errors in the function. #. Display status message #: ../minimize.py:91 ../scaling.py:299 msgid "Running ..." msgstr "" #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "" #: ../minimize.py:114 ../scaling.py:350 msgid "Out of memory, consider using LBFGS instead" msgstr "" #. Update display to reflect succesful end of simulation. #: ../minimize.py:121 #, 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:20 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:27 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:84 msgid "Face centered cubic (fcc)" msgstr "" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "" #: ../nanoparticle.py:131 msgid "Get structure" msgstr "" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "" #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "" #: ../nanoparticle.py:212 msgid "Add" msgstr "" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "" #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:196 msgid "Number of atoms: " msgstr "" #: ../nanoparticle.py:234 msgid "Volume: " msgstr "" #: ../nanoparticle.py:239 msgid "ų" msgstr "" #: ../nanoparticle.py:244 msgid "Rounding: If exact size is not possible, choose the size" msgstr "" #: ../nanoparticle.py:247 msgid "above " msgstr "" #: ../nanoparticle.py:248 msgid "below " msgstr "" #: ../nanoparticle.py:249 msgid "closest " msgstr "" #: ../nanoparticle.py:252 msgid "Smaller" msgstr "" #: ../nanoparticle.py:253 msgid "Larger" msgstr "" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr "" #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "" #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "" #: ../nanoparticle.py:333 msgid "Up" msgstr "" #: ../nanoparticle.py:338 msgid "Down" msgstr "" #: ../nanoparticle.py:343 msgid "Delete" msgstr "" #: ../nanoparticle.py:384 msgid "Surface energies (as energy/area, NOT per atom):" msgstr "" #: ../nanoparticle.py:390 msgid "Number of layers:" msgstr "" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "" #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "" #: ../nanotube.py:15 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:29 #, python-format msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: %" "(volume).3f Å3" msgstr "" #: ../nanotube.py:35 msgid "Nanotube" msgstr "" #. Choose the structure. #: ../nanotube.py:59 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:81 msgid "Help" msgstr "" #: ../widgets.py:98 msgid "Clear constraint" msgstr "" python-ase-3.9.1.4567/ase/gui/po/zh_CN/0000775000175000017500000000000012553427753017455 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/zh_CN/LC_MESSAGES/0000775000175000017500000000000012553427753021242 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/zh_CN/LC_MESSAGES/ag.po0000664000175000017500000022143312553425527022173 0ustar jensjjensj00000000000000# Chinese translations for python-ase package. # Copyright (C) 2012 CAMD and ASE Developers # This file is distributed under the same license as the python-ase package. # # Jun Yan , 2012. # Tao Jiang , 2012. # Chengjun , 2012. # msgid "" msgstr "" "Project-Id-Version: python-ase 3.6.0.2515\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2012-09-10 15:12+0200\n" "PO-Revision-Date: 2012-07-20 09:02+0200\n" "Last-Translator: Chengjun \n" "Language-Team: Chinese (simplified)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "Language: zh_CN\n" #: ../ag.py:136 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" "发现异常! 请提交异常信息到\n" "ase-developers@listserv.fysik.dtu.dk - 谢谢! 如果这个是用户错误,也请一起提" "交,\n" "以方便我们提供更好的错误信息。" #. 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 "" "如果要进行计算,请先指定一个计算器。ASE支持多个计算器,\n" "这些计算起支持多种元素,并且有多种物理模型处理原子间的作用。" # XXX 计算器 #. Informational text about the calculators #: ../calculator.py:26 #, fuzzy #| 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.\n" 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-Jone势是描述原子间相互作用的最简单的模型之一。它适合于惰性气\n" "体和模型体系。\n" "\n" "该势使用原子间距和相互作用强度参数来描述原子间的相互作用\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 "" "有效介质理论(EMT)势是一种多体势。它能很好的描述FCC结构的后过渡金属元素。\n" "EMT所包含的元素有 (铝)Al, (镍)Ni, (铜)Cu, (钯)Pd, \n" "(银)Ag, (铂)Pt, (金)Au。但由于(铝)Al势给出错误的堆积能,\n" "其不适合材料科学计算。\n" "\n" "本软件包所提供的EMT势提供了很多参数的默认值。\n" "\n" "默认值:\n" "\n" "EMT参数的默认值来自于K. W. Jacobsen,\n" "P. Stoltze and J. K. Nørskov, Surf. Sci. 366, 394 (1996).\n" "\n" "Cu, Ag和Au的另一组参数值:\n" "\n" "Torben Rasmussen 根据实验值进行了重新优化, 得到了Cu, Ag和Au\n" "的另一组参数值(部分已发表)。这组参数很好的修正了堆积能计算值。\n" "\n" "(钌)Ru:\n" "\n" "(钌)Ru的参数来自 J. Gavnholt and\n" "J. Schiøtz, Phys. Rev. B 77, 035404 (2008).\n" "\n" "金属玻璃:\n" "\n" "MgCu 和 CuZr 金属玻璃的参数。 MgCu\n" "的参数来自于 N. P. Bailey, J. Schiøtz and\n" "K. W. Jacobsen, Phys. Rev. B 69, 144205 (2004).\n" "CuZr的参数来自于 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 "" "EMT势是一种多体势。它能很好的描述FCC结构的后过渡性金属元素。\n" "EMT所包含的元素有 (铝)Al, (镍)Ni, (铜)Cu, (钯)Pd, \n" "(银)Ag, (铂)Pt, (金)Au。另外,此版本允许用户使用(氢)H, \n" "(氮)N, (氧)O和(碳)C作为吸附原子, 但是其精度并不高。\n" "\n" "这是ASE中的所包含的EMT计算器,它仅提供测试所用的最基本的\n" "功能。如需对于大体系进行计算,请安装使用ASAP中所包含的版本。\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 "" "Brenner势是一种适用于碳材料和碳氢化合物的反应键极势。\n" "作为一种键极势, 它考虑了碳轨道的多种可能杂化形式,\n" "以及碳可以单键,双键,三重键。反应键极势中的反应意味着他能\n" "处理化学键断裂和形成过程中键极的逐步变化。\n" "\n" "ASAP 包含Brenner势, 这势是用C语言编写的。来自于http://www.rahul.net/pcm/" "brenner/ .\n" "\n" "该势能的参考文献:\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" # Here, I am not sure about how to present the name of GPAW in chinese.*** #: ../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 基于密度泛函理论(Density Functional Theory),使用实空间格点展开波函" "数,\n" "使用投射增广波方法( Projector Augmented Wave method)\n" "处理核心电子。\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 是一个外部的软件包。它基于密度泛函理论和量子化学方法,\n" "使用全电子和数值局部轨道基组。\n" "参考信息: http://www.fhi-berlin.mpg.de/aims/ \n" "或者 Comp. Phys. Comm. v180 2175 (2009). ASE \n" "的使用手册里包含关键词和功能信息。\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 "" "警告:\n" "你的计算体系的周期性大于零维但小于三维。请对此进行确认。\n" "此计算器将使用三维周期性进行计算。" #: ../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 是一个外部的软件包。它基于密度泛函理论,使用\n" "赝势或者PAW方法,波函数用平面波展开。参考信息:\n" "http://cms.mpi.univie.ac.at/vasp/vasp/\n" #: ../calculator.py:140 msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)" msgstr "默认(铝Al, 镍Ni, 铜Cu, 钯Pd,银Ag, 铂Pt, 金Au)" #: ../calculator.py:141 msgid "Alternative Cu, Ag and Au" msgstr "另外 铜Cu,银Ag, 金Au" #: ../calculator.py:142 msgid "Ruthenium" msgstr "Ruthenium" #: ../calculator.py:143 msgid "CuMg and CuZr metallic glass" msgstr "CuMg 和 CuZr 金属玻璃" #: ../calculator.py:158 #, fuzzy #| msgid "Set _Calculator" 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 "Lennard-Jones (ASAP)" #: ../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 "EMT - 有效介质理论 (ASAP)" #: ../calculator.py:192 msgid "EMT - Effective Medium Theory (ASE)" msgstr "EMT - 有效介质理论 (ASE)" #: ../calculator.py:198 msgid "Brenner Potential (ASAP)" msgstr "Brenner 势 (ASAP)" #: ../calculator.py:204 msgid "Density Functional Theory (GPAW)" msgstr "密度泛函理论 (GPAW)" #: ../calculator.py:213 msgid "Density Functional Theory (FHI-aims)" msgstr "密度泛函理论 (FHI-aims)" #: ../calculator.py:222 msgid "Density Functional Theory (VASP)" msgstr "密度泛函理论 (VASP)" #: ../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:452 msgid "ASAP is not installed. (Failed to import asap3)" msgstr "ASAP 没有安装。(加载asap3失败)" #: ../calculator.py:391 msgid "You must set up the Lennard-Jones parameters" msgstr "你必须设置Lennard-Jones参数" #: ../calculator.py:396 msgid "Could not create useful Lennard-Jones calculator." msgstr "创建Lennard-Jones 计算器失败。" #: ../calculator.py:430 msgid "Could not attach EMT calculator to the atoms." msgstr "不能将EMT计算器赋予给原子。" #: ../calculator.py:470 ../calculator.py:482 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "GPAW 没有安装。(加载gpaw失败)" #: ../calculator.py:473 msgid "You must set up the GPAW parameters" msgstr "你必须设置GPAW的参数" #: ../calculator.py:514 msgid "You must set up the FHI-aims parameters" msgstr "你必须设置FHI-aims的参数" #: ../calculator.py:528 msgid "You must set up the VASP parameters" msgstr "你必须设置VASP的参数" #: ../calculator.py:552 #, python-format msgid "Element %(sym)s not allowed by the '%(name)s' calculator" msgstr "'%(name)s'计算器中无法使用元素 %(sym)s" #: ../calculator.py:559 msgid "Info" msgstr "信息" #: ../calculator.py:575 msgid "Lennard-Jones parameters" msgstr "Lennard-Jones参数" #: ../calculator.py:587 msgid "Specify the Lennard-Jones parameters here" msgstr "请设置Lennard-Jones参数" #: ../calculator.py:590 msgid "Epsilon (eV):" msgstr "Epsilon (eV):" #: ../calculator.py:594 msgid "Sigma (Å):" msgstr "Sigma (Å):" # I am not sure about this part. What calculator is this info for?*** #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:598 msgid "Shift to make smooth at cutoff" msgstr "在阶段处进行调整,使其光滑" # XXX截断 #: ../calculator.py:679 msgid "GPAW parameters" msgstr "GPAW 参数" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:694 ../calculator.py:983 ../calculator.py:1471 #, python-format msgid "%i atoms.\n" msgstr "%i 原子.\n" #: ../calculator.py:696 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "正交原胞: %.2f x %.2f x %.2f Å." #: ../calculator.py:698 msgid "Non-orthogonal unit cell:\n" msgstr "非正交原胞:\n" #: ../calculator.py:708 ../calculator.py:999 ../calculator.py:1486 msgid "Exchange-correlation functional: " msgstr "交换-相关 势能:" #. Grid spacing #: ../calculator.py:712 msgid "Grid spacing" msgstr "格子间距" #: ../calculator.py:716 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "Å" #: ../calculator.py:717 msgid "Grid points" msgstr "格点" #: ../calculator.py:726 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "heff = (%.3f, %.3f, %.3f) Å" #: ../calculator.py:752 ../calculator.py:1014 ../calculator.py:1522 msgid "k-points k = (" msgstr "k点数 k = (" #: ../calculator.py:756 ../calculator.py:1018 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "k点数 x 尺寸: (%.1f, %.1f, %.1f) Å" #. Spin polarized #: ../calculator.py:761 ../calculator.py:1484 msgid "Spin polarized" msgstr "自旋极化" #: ../calculator.py:767 msgid "FD - Finite Difference (grid) mode" msgstr "FD - 有限差分 (格点) 模式" #: ../calculator.py:768 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "LCAO - 原子轨道线性组合" #: ../calculator.py:771 msgid "Mode: " msgstr "模式:" #: ../calculator.py:773 msgid "sz - Single Zeta" msgstr "sz - 单Zeta" #: ../calculator.py:774 msgid "szp - Single Zeta polarized" msgstr "szp - 单Zeta极化" #: ../calculator.py:775 msgid "dzp - Double Zeta polarized" msgstr "dzp - 双Zeta极化" #. dzp #: ../calculator.py:777 msgid "Basis functions: " msgstr "基组函数:" #. Mixer #: ../calculator.py:783 msgid "Non-standard mixer parameters" msgstr "非标准混合参数" #: ../calculator.py:979 msgid "FHI-aims parameters" msgstr "FHI-aims参数" #: ../calculator.py:986 msgid "Periodic geometry, unit cell is:\n" msgstr "周期性构型,原胞是:\n" #: ../calculator.py:991 msgid "Non-periodic geometry.\n" msgstr "非周期性构型\n" # Not sure about this translation. #: ../calculator.py:998 msgid "Hirshfeld-based dispersion correction" msgstr "基于Hirshfeld的分布修正" #. Spin polarized, charge, relativity #: ../calculator.py:1024 msgid "Spin / initial moment " msgstr "自旋 / 初始磁矩" #: ../calculator.py:1042 msgid " Charge" msgstr " 电荷" #: ../calculator.py:1044 msgid " Relativity" msgstr " 相对论" #: ../calculator.py:1046 msgid " Threshold" msgstr " 阈值" #. self-consistency criteria #: ../calculator.py:1051 msgid "Self-consistency convergence:" msgstr "自恰收敛:" #: ../calculator.py:1064 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:1075 msgid "Energy: " msgstr "能量: " #: ../calculator.py:1077 msgid " eV Sum of eigenvalues: " msgstr " eV 本征值之和:" #: ../calculator.py:1079 ../calculator.py:1557 msgid " eV" msgstr " eV" #: ../calculator.py:1080 msgid "Electron density: " msgstr "电子密度:" #: ../calculator.py:1082 msgid " Force convergence: " msgstr " 力的收敛:" #: ../calculator.py:1084 msgid " eV/Ang " msgstr " eV/Ang " #: ../calculator.py:1097 ../calculator.py:1568 msgid "Additional keywords: " msgstr "其他关键词:" #. run command and species defaults: #: ../calculator.py:1111 msgid "FHI-aims execution command: " msgstr "FHI-aims执行命令:" #: ../calculator.py:1113 ../calculator.py:1585 msgid "Directory for species defaults: " msgstr "默认的元素目录:" #: ../calculator.py:1125 ../calculator.py:1593 msgid "Set Defaults" msgstr "设置默认值" #: ../calculator.py:1127 msgid "Import control.in" msgstr "导入control.in" #: ../calculator.py:1129 msgid "Export control.in" msgstr "导出control.in" #: ../calculator.py:1315 msgid "Export parameters ... " msgstr "导出参数" #: ../calculator.py:1335 msgid "Import control.in file ... " msgstr "导入control.in文件 ..." #: ../calculator.py:1391 ../calculator.py:1903 #, python-format msgid "" "Please use the facilities provided in this window to manipulate the keyword: " "%s!" msgstr "请使用这个窗口里提供的工具来修改关键词:%s!" #: ../calculator.py:1394 #, 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 "" "不存在这个关键词: %s\n" "\n" "请检查!\n" "\n" "如果你觉得此关键词应当存在,请添加在 ase/calculators/aims.py的上方。" #: ../calculator.py:1467 msgid "VASP parameters" msgstr "VASP 参数" #: ../calculator.py:1473 msgid "Periodic geometry, unit cell is: \n" msgstr "周期性构型,原胞是:\n" #: ../calculator.py:1525 msgid ") Cutoff: " msgstr ") 截断: " #: ../calculator.py:1526 msgid " Precision: " msgstr " 精度:" #: ../calculator.py:1528 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "k点数 x 尺寸: (%.1f, %.1f, %.1f) Å " # don't know how to translate this term. #: ../calculator.py:1544 msgid "Smearing: " msgstr "Smearing: " # order of what?*** #: ../calculator.py:1546 msgid " order: " msgstr " order: " #: ../calculator.py:1548 msgid " width: " msgstr " 宽度: " #: ../calculator.py:1555 msgid "Self-consistency convergence: " msgstr "自恰收敛:" #. run command and location of POTCAR files: #: ../calculator.py:1581 msgid "VASP execution command: " msgstr "VASP 执行命令:" #: ../calculator.py:1595 msgid "Import VASP files" msgstr "导入 VASP 文件" #: ../calculator.py:1597 msgid "Export VASP files" msgstr "导出 VASP 文件" #: ../calculator.py:1806 msgid "WARNING: cutoff energy is lower than recommended minimum!" msgstr "警告: 截断能(E-cutoff)低于推荐值!" #: ../calculator.py:1858 msgid "Import VASP input files: choose directory ... " msgstr "导入 VASP 输入文件:选择目录 ..." #: ../calculator.py:1873 msgid "Export VASP input files: choose directory ... " msgstr "导出 VASP 输入文件:选择目录 ..." #: ../calculator.py:1906 #, 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 "" "不存在这个关键词: %s\n" "\n" "请检查!\n" "\n" "如果你觉得此关键词应当存在,请添加在 ase/calculators/vasp.py的上方。" #: ../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 "根据原子序数, 默认\"jmol\"颜色" #: ../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 "最大的受力: %.2f (这个结构), %.2f (所有结构)" #: ../colors.py:369 #, python-format msgid "Max force: %.2f." msgstr "最大受力:%.2f." #: ../colors.py:383 #, python-format msgid "Max velocity: %.2f (this frame), %.2f (all frames)" msgstr "最大速度:%.2f (这个结构), %.2f (所有结构)" #: ../colors.py:385 #, python-format msgid "Max velocity: %.2f." msgstr "最大速度:%.2f." #: ../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:90 msgid "Constraints" msgstr "限制" #: ../constraints.py:15 ../constraints.py:18 ../settings.py:17 #: ../widgets.py:92 ../widgets.py:95 msgid "Constrain" msgstr "限制" #: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:93 msgid " selected atoms" msgstr "已选择的原子" #: ../constraints.py:19 ../widgets.py:96 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:100 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 "" " 使用这个对话窗口来创建晶格。首先,从常见晶体结构或者根据空间群中选择结" "构。\n" " 然后,添加其他晶格参数。\n" "\n" " 你可以查找实验晶体结构参数,并依次设置晶格类型和晶格常数。\n" "否则你需要自己对其进行指定。" #: ../crystal.py:33 ../graphene.py:27 #, python-format msgid " %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3" msgstr " %(natoms)i 原子: %(symbols)s, 体积: %(volume).3f A3" #: ../crystal.py:58 msgid "Create Bulk Crystal by Spacegroup" msgstr "根据空间群创建晶体" #: ../crystal.py:72 msgid "Number: 1" msgstr "标号: 1" #: ../crystal.py:73 msgid "Lattice: " msgstr "晶格:" #: ../crystal.py:73 msgid "\tSpace group: " msgstr "\t空间群:" #: ../crystal.py:77 msgid "Size: x: " msgstr "尺寸大小: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 " 晶胞" #: ../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 "等于 b" #: ../crystal.py:94 ../crystal.py:98 msgid "equals c" msgstr "等于 c" #: ../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 "等于 a" #: ../crystal.py:105 ../crystal.py:114 msgid "equals beta" msgstr "等于 beta" #: ../crystal.py:106 ../crystal.py:110 msgid "equals gamma" msgstr "等于 gamma" #: ../crystal.py:109 ../crystal.py:113 msgid "equals alpha" msgstr "等于 alpha" #: ../crystal.py:119 msgid "Lattice parameters" msgstr "晶格参数" #: ../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 "从数据库读取" #: ../crystal.py:131 msgid "Basis: " msgstr "基组:" #: ../crystal.py:137 msgid " Element:\t" msgstr " 元素:\t" #: ../crystal.py:137 msgid "\tx: " msgstr "\tx: " #: ../crystal.py:157 msgid "Creating a crystal." msgstr "创建一个晶体。" #: ../crystal.py:202 #, python-format msgid "Symbol: %s" msgstr "化学符号: %s" #: ../crystal.py:207 #, python-format msgid "Number: %s" msgstr "序号: %s" #: ../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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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" #: ../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 "势能:\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/原子\n" "\n" #: ../energyforces.py:86 msgid "Forces:\n" msgstr "受力:\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: ase-gui window python object\n" " img:\tadvanced: ase-gui images object\n" " " msgstr "" "\n" " 全局命令作用于所有构型或者当前构型\n" " - 全局变量的指定可能与局域变量无关\n" " - 使用'当前构型'开关使其不应用于所有构型\n" " e:\t\t一个构型的总能\n" " fmax:\t一个构型的最大受力\n" " A:\t原胞\n" " E:\t\t所有构型的总能\n" " F:\t\t一个构型的总受力\n" " M:\t所有构型的磁矩\n" " R:\t\t所有的原子位置\n" " S:\t所有所选的原子(boolean array)\n" " D:\t所有可移动的原子 (boolean array)\n" " 例子: 构型 = 1, A[0][1] += 4, e-E[-1]\n" "\n" " Atom 命令分别作用于各个原子(或所选的原子集合)\n" " - 这些可使用全局命令作用于the RHS of an equation\n" " - 使用 '仅应用于被选择的原子' 来限制命令的应用\n" " x,y,z:\t原子的坐标\n" " r,g,b:\t要显示的原子颜色,范围是[0..1]\n" " rad:\t显示的原子半径\n" " s:\t\t已被选择的原子\n" " d:\t\t可移动的原子\n" " f:\t\t受力\n" " Z:\t原子数\n" " m:\t磁矩\n" " 例子: x -= A[0][0], s = z > 5, Z = 6\n" "\n" " 特殊命令和对象:\n" " sa,cf:\t(不)限制于所选原子/当前构型\n" " frame:\t构型序号\n" " center:\t将体系居中于当前存在的原胞中\n" " del S:\t删除选择\n" " CM:\t重心\n" " ans[-i]:\t最后第i个计算结果\n" " exec file: 执行文件中列出的命令\n" " cov[Z]:(仅仅读取): 原子数为Z的原子共价半径\n" " gui:\t高级:ase-gui 窗口 python 对象\n" " img:\t高级:ase-gui 图像 对象\n" " " #: ../execute.py:67 msgid "Expert user mode" msgstr "专家级模式" #: ../execute.py:80 msgid "Welcome to the ASE Expert user mode" msgstr "欢迎使用ASE专家级模式" #: ../execute.py:87 msgid "Only selected atoms (sa) " msgstr "仅应用于被选择的原子(sa) " #: ../execute.py:89 msgid "Only current frame (cf) " msgstr "仅应用于当前构型 (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 "" "全局: 使用 A, D, E, M, N, R, S, n, 构型; Atoms: 使用 a, f, m, s, x, y, z, " "Z " #: ../execute.py:198 #, python-format msgid "*** WARNING: file does not exist - %s" msgstr "*** 警告:文件不存在 - %s" #: ../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:16 msgid "" "Set up a graphene sheet or a graphene nanoribbon. A nanoribbon may\n" "optionally be saturated with hydrogen (or another element)." msgstr "" "建立一个石墨烯单层或者石墨烯纳米带。一个纳米带可以\n" "选择被氢(或其他元素)饱和。" #: ../graphene.py:33 ../gui.py:316 msgid "Graphene" msgstr "石墨稀" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "结构:" #: ../graphene.py:42 msgid "Infinite sheet" msgstr "无限sheet" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "未饱和的ribbon" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "饱和的ribbon" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "取向" #: ../graphene.py:53 msgid "zigzag" msgstr "zigzag" #: ../graphene.py:53 msgid "armchair" msgstr "armchair" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 msgid " Bond length: " msgstr " 健长:" #. Choose the saturation element and bond length #: ../graphene.py:72 msgid "Saturation: " msgstr "饱和:" #: ../graphene.py:75 msgid "H" msgstr "H" #. Size #: ../graphene.py:90 msgid "Width: " msgstr "宽度:" #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr "长度:" #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "真空:" #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr "未指定元素!" #: ../graphene.py:194 #, fuzzy #| msgid "Please specify a consistent set of atoms." msgid "Please specify a consistent set of atoms. " msgstr "请指定相应的原子序列。" #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../pybutton.py:49 ../surfaceslab.py:249 msgid "You have not (yet) specified a consistent set of parameters." msgstr "你没有指定合理的参数。" #: ../graphs.py:9 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" #: ../graphs.py:52 ../graphs.py:55 msgid "Plot" msgstr "画图" #: ../graphs.py:60 msgid "clear" msgstr "清空" #: ../graphs.py:114 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 "" "来自: buggy_application\"\n" "至: bad_programmer\n" "主题: Exception feedback\n" "\n" "%s" #. Show details... #: ../gtkexcepthook.py:173 msgid "Bug Details" msgstr "错误细节" #: ../gui.py:175 msgid "_File" msgstr "文件" #: ../gui.py:176 msgid "_Edit" msgstr "编辑" #: ../gui.py:177 msgid "_View" msgstr "视图" #: ../gui.py:178 msgid "_Tools" msgstr "工具" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:180 msgid "_Setup" msgstr "设置" #: ../gui.py:181 msgid "_Calculate" msgstr "计算" #: ../gui.py:182 msgid "_Help" msgstr "帮助" #: ../gui.py:183 msgid "_Open" msgstr "打开" #: ../gui.py:184 msgid "Create a new file" msgstr "创建新文件" #: ../gui.py:186 msgid "_New" msgstr "新文件" #: ../gui.py:187 msgid "New ase.gui window" msgstr "新ase.gui窗口" #: ../gui.py:189 msgid "_Save" msgstr "保存" #: ../gui.py:190 msgid "Save current file" msgstr "保存当前文件" #: ../gui.py:192 msgid "_Quit" msgstr "退出" #: ../gui.py:193 msgid "Quit" msgstr "退出" #: ../gui.py:195 msgid "Select _all" msgstr "选择所有" #: ../gui.py:198 msgid "_Invert selection" msgstr "反选" #: ../gui.py:201 msgid "Select _constrained atoms" msgstr "选择被限制的原子" #: ../gui.py:204 msgid "Select _immobile atoms" msgstr "选择固定的原子" #: ../gui.py:207 msgid "_Copy" msgstr "复制" #: ../gui.py:208 msgid "Copy current selection and its orientation to clipboard" msgstr "复制当前的选择和它的取向到剪贴板" #: ../gui.py:210 msgid "_Paste" msgstr "粘贴" #: ../gui.py:211 msgid "Insert current clipboard selection" msgstr "插入当前剪贴板的内容" #: ../gui.py:213 msgid "_Modify" msgstr "修改" #: ../gui.py:214 msgid "Change tags, moments and atom types of the selected atoms" msgstr "修改所选原子的标签,磁矩和类型" #: ../gui.py:216 msgid "_Add atoms" msgstr "添加原子" #: ../gui.py:217 msgid "Insert or import atoms and molecules" msgstr "插入或导入原子和分子" #: ../gui.py:219 msgid "_Delete selected atoms" msgstr "删除所选原子" #: ../gui.py:220 msgid "Delete the selected atoms" msgstr "删除所选原子" #: ../gui.py:222 msgid "_First image" msgstr "第一个图像" #: ../gui.py:225 msgid "_Previous image" msgstr "前一个图像" #: ../gui.py:228 msgid "_Next image" msgstr "下一个图像" #: ../gui.py:231 msgid "_Last image" msgstr "最后一个图像" #: ../gui.py:234 #, fuzzy #| msgid "Show _axes" msgid "Show _Labels" msgstr "显示坐标轴" #: ../gui.py:235 #, fuzzy #| msgid " selected atoms" msgid "Hide selected atoms" msgstr "已选择的原子" #: ../gui.py:238 #, fuzzy #| msgid " selected atoms" msgid "Show selected atoms" msgstr "已选择的原子" #: ../gui.py:241 msgid "Quick Info ..." msgstr "简要信息 ..." #: ../gui.py:244 msgid "Repeat ..." msgstr "重复 ..." #: ../gui.py:247 msgid "Rotate ..." msgstr "旋转 ..." #: ../gui.py:250 msgid "Colors ..." msgstr "颜色 ..." #. TRANSLATORS: verb #: ../gui.py:253 msgid "Focus" msgstr "聚焦" #: ../gui.py:256 msgid "Zoom in" msgstr "放大" #: ../gui.py:259 msgid "Zoom out" msgstr "缩小" #: ../gui.py:262 msgid "Reset View" msgstr "复原" #: ../gui.py:265 msgid "Settings ..." msgstr "设置 ..." #: ../gui.py:268 msgid "VMD" msgstr "VMD" #: ../gui.py:271 msgid "RasMol" msgstr "RasMol" #: ../gui.py:274 msgid "xmakemol" msgstr "xmakemol" #: ../gui.py:277 msgid "avogadro" msgstr "avogadro" #: ../gui.py:280 msgid "Graphs ..." msgstr "图片 ..." #: ../gui.py:283 msgid "Movie ..." msgstr "动画 ..." #: ../gui.py:286 msgid "Expert mode ..." msgstr "专家模式 ..." #: ../gui.py:289 msgid "Constraints ..." msgstr "限制 ..." #: ../gui.py:292 msgid "Render scene ..." msgstr "渲染场景 ..." #: ../gui.py:295 msgid "DFT ..." msgstr "DFT ..." #: ../gui.py:298 msgid "NE_B" msgstr "NEB" #: ../gui.py:301 msgid "B_ulk Modulus" msgstr "块体的模块" #: ../gui.py:304 msgid "_Bulk Crystal" msgstr "晶体" #: ../gui.py:305 msgid "Create a bulk crystal with arbitrary orientation" msgstr "创建一个任意取向的晶体" #: ../gui.py:307 msgid "_Surface slab" msgstr "表面" #: ../gui.py:308 msgid "Create the most common surfaces" msgstr "创建常用的表面" #: ../gui.py:310 msgid "_Nanoparticle" msgstr "纳米颗粒" #: ../gui.py:311 msgid "Create a crystalline nanoparticle" msgstr "创建晶体纳米颗粒" #: ../gui.py:313 msgid "Nano_tube" msgstr "纳米管" #: ../gui.py:314 msgid "Create a nanotube" msgstr "创建纳米管" #: ../gui.py:317 msgid "Create a graphene sheet or nanoribbon" msgstr "创建石墨烯单层或纳米带" #: ../gui.py:319 msgid "Set _Calculator" msgstr "设置计算器" #: ../gui.py:320 msgid "Set a calculator used in all calculation modules" msgstr "设置所有计算模块使用的计算器" #: ../gui.py:322 msgid "_Energy and Forces" msgstr "能量和受力" #: ../gui.py:323 msgid "Calculate energy and forces" msgstr "计算能量和受力" #: ../gui.py:325 msgid "Energy _Minimization" msgstr "能量最小化" #: ../gui.py:326 msgid "Minimize the energy" msgstr "最小化能量" #: ../gui.py:328 msgid "Scale system" msgstr "缩放体系" #: ../gui.py:329 msgid "Deform system by scaling it" msgstr "通过缩放改变体系形状" #: ../gui.py:331 msgid "_About" msgstr "关于" #: ../gui.py:334 msgid "Webpage ..." msgstr "网页" #: ../gui.py:335 msgid "Debug ..." msgstr "除错" #: ../gui.py:337 msgid "Show _unit cell" msgstr "显示原胞" #: ../gui.py:341 msgid "Show _axes" msgstr "显示坐标轴" #: ../gui.py:345 msgid "Show _bonds" msgstr "显示原子键" #: ../gui.py:349 #, fuzzy #| msgid "Show _axes" msgid "Show _velocities" msgstr "显示坐标轴" #: ../gui.py:353 #, fuzzy #| msgid "Show _axes" msgid "Show _forces" msgstr "显示坐标轴" #: ../gui.py:357 msgid "_Move atoms" msgstr "移动原子" #: ../gui.py:361 msgid "_Rotate atoms" msgstr "旋转原子" #: ../gui.py:365 msgid "Orien_t atoms" msgstr "取向原子" #: ../gui.py:371 #, fuzzy #| msgid "None" msgid "_None" msgstr "无" #: ../gui.py:372 msgid "Atom _Index" msgstr "" #: ../gui.py:373 msgid "_Magnetic Moments" msgstr "" #: ../gui.py:374 #, fuzzy #| msgid "Element: " msgid "_Element Symbol" msgstr "元素" #: ../gui.py:383 #, python-format msgid "building menus failed: %s" msgstr "创建菜单失败:%s" #: ../gui.py:658 ../gui.py:1064 ../gui.py:1124 msgid "Open ..." msgstr "打开 ..." #: ../gui.py:662 ../gui.py:1067 msgid "<>" msgstr "<>" #: ../gui.py:795 msgid "Add atoms" msgstr "添加原子" #: ../gui.py:798 msgid "Paste" msgstr "粘贴" #: ../gui.py:804 msgid "Insert atom or molecule" msgstr "插入原子或分子" #: ../gui.py:805 ../gui.py:931 msgid "Tag" msgstr "标签" #: ../gui.py:806 ../gui.py:932 msgid "Moment" msgstr "磁矩" #: ../gui.py:807 msgid "Position" msgstr "位置" #: ../gui.py:832 msgid "_Load molecule" msgstr "载入分子" #: ../gui.py:836 ../gui.py:947 msgid "_OK" msgstr "完成" #: ../gui.py:840 ../gui.py:951 msgid "_Cancel" msgstr "取消" #: ../gui.py:924 msgid "Modify" msgstr "修改" #: ../gui.py:930 msgid "Atom" msgstr "原子" #: ../gui.py:975 msgid "Confirmation" msgstr "确认" #: ../gui.py:979 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "删除所选原子?" #: ../gui.py:986 msgid "Cancel" msgstr "取消" #: ../gui.py:1072 ../gui.py:1154 msgid "Automatic" msgstr "自动" #: ../gui.py:1073 msgid "Dacapo netCDF output file" msgstr "Dacapo netCDF 输出文件" #: ../gui.py:1074 msgid "Virtual Nano Lab file" msgstr "Virtual Nano Lab 文件" #: ../gui.py:1075 msgid "ASE pickle trajectory" msgstr "ASE pickle 轨迹" #: ../gui.py:1076 ../gui.py:1167 msgid "ASE bundle trajectory" msgstr "ASE bundle 轨迹" #: ../gui.py:1077 msgid "GPAW text output" msgstr "GPAW 文本输出" #: ../gui.py:1078 msgid "CUBE file" msgstr "CUBE 文件" #: ../gui.py:1079 msgid "XCrySDen Structure File" msgstr "XCrySDen 结构文件" #: ../gui.py:1080 msgid "Dacapo text output" msgstr "Dacapo 文本输出" #: ../gui.py:1081 msgid "XYZ-file" msgstr "XYZ-文件" #: ../gui.py:1082 msgid "VASP POSCAR/CONTCAR file" msgstr "VASP POSCAR/CONTCAR 文件" #: ../gui.py:1083 msgid "VASP OUTCAR file" msgstr "VASP OUTCAR 文件" #: ../gui.py:1084 msgid "Protein Data Bank" msgstr "Protein Data Bank" #: ../gui.py:1085 msgid "CIF-file" msgstr "CIF-文件" #: ../gui.py:1086 msgid "FHI-aims geometry file" msgstr "FHI-aims 构型文件" #: ../gui.py:1087 msgid "FHI-aims output file" msgstr "FHI-aims 输出文件" #: ../gui.py:1088 msgid "TURBOMOLE coord file" msgstr "TURBOMOLE coord 文件" #: ../gui.py:1089 msgid "exciting input" msgstr "exciting 输入" #: ../gui.py:1090 msgid "WIEN2k structure file" msgstr "WIEN2k 结构文件" #: ../gui.py:1091 msgid "DftbPlus input file" msgstr "DftbPlus 输入文件" #: ../gui.py:1092 msgid "ETSF format" msgstr "ETSF 格式" #: ../gui.py:1093 ../gui.py:1165 msgid "CASTEP geom file" msgstr "CASTEP geom 文件" #: ../gui.py:1094 msgid "CASTEP output file" msgstr "CASTEP 输出文件" #: ../gui.py:1095 msgid "CASTEP trajectory file" msgstr "CASTEP 轨迹文件" #: ../gui.py:1096 msgid "DFTBPlus GEN format" msgstr "DFTBPlus GEN 格式" #: ../gui.py:1102 msgid "File type:" msgstr "文件类型:" #: ../gui.py:1142 msgid "Save ..." msgstr "保存 ..." #: ../gui.py:1155 msgid "XYZ file" msgstr "XYZ 文件" #: ../gui.py:1156 msgid "ASE trajectory" msgstr "ASE 轨迹" #: ../gui.py:1157 msgid "PDB file" msgstr "PDB 文件" #: ../gui.py:1158 msgid "Gaussian cube file" msgstr "Gaussian cube 文件" #: ../gui.py:1159 msgid "Python script" msgstr "Python 脚本" #: ../gui.py:1160 msgid "VNL file" msgstr "VNL 文件" #: ../gui.py:1161 msgid "Portable Network Graphics" msgstr "Portable Network Graphics" #: ../gui.py:1162 msgid "Persistence of Vision" msgstr "Persistence of Vision" #: ../gui.py:1163 msgid "Encapsulated PostScript" msgstr "Encapsulated PostScript" #: ../gui.py:1164 msgid "FHI-aims geometry input" msgstr "FHI-aims 结构输入" #: ../gui.py:1166 msgid "VASP geometry input" msgstr "VASP 结构输入" #: ../gui.py:1168 msgid "cif file" msgstr "cif 文件" #: ../gui.py:1190 #, python-format msgid "Save current image only (#%d)" msgstr "仅保存当前图像 (#%d)" #: ../gui.py:1194 msgid "Slice: " msgstr "切片:" #: ../gui.py:1195 msgid "Help for slice ..." msgstr "切片帮助" #: ../gui.py:1207 msgid "ase-gui INTERNAL ERROR: strange response in Save," msgstr "ase-gui内部错误:对保存命令的响应出错" #: ../gui.py:1226 msgid "Unknown output format!" msgstr "未知输入格式" #: ../gui.py:1227 #, python-format msgid "Use one of: %s" msgstr "使用 :%s 之一" #: ../gui.py:1332 msgid "Not implemented!" msgstr "该模块尚未加入!" #: ../gui.py:1333 msgid "do you really need it?" msgstr "你确定需要它?" #: ../minimize.py:21 msgid "Algorithm: " msgstr "算法:" #: ../minimize.py:26 ../progress.py:67 msgid "Convergence criterion: Fmax = " msgstr "收敛标准: Fmax = " #: ../minimize.py:31 ../progress.py:70 msgid "Max. number of steps: " msgstr "最多迭代次数:" #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "赝时间次数:" #: ../minimize.py:55 msgid "Energy minimization" msgstr "能量最小化" #: ../minimize.py:59 msgid "Minimize the energy with respect to the positions." msgstr "根据位置,进行能量最小化" #. Don't catch errors in the function. #. Display status message #: ../minimize.py:91 ../scaling.py:299 msgid "Running ..." msgstr "运行中 ..." #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "%i步后优化被取消。" #: ../minimize.py:114 ../scaling.py:350 msgid "Out of memory, consider using LBFGS instead" msgstr "内存不足,请改用LBFGS方法" #. Update display to reflect succesful end of simulation. #: ../minimize.py:121 #, python-format msgid "Minimization completed in %i steps." msgstr "经过%i步后,优化结束。" #. 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 "Rock" #: ../movie.py:60 msgid " Frame rate: " msgstr "帧速率" #: ../movie.py:61 msgid " Skip frames: " msgstr "略过帧数" #: ../nanoparticle.py:20 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 "" "通过指定层数或使用Wulff construction创建纳米颗粒。请按[帮助]已获取关于指定" "方向的指导。\n" "警告:目前Wulff construction仅适用于立方结构晶体\n" #: ../nanoparticle.py:27 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" "纳米颗粒模块可以根据晶体结构创建纳米颗粒或团蔟\n" "\n" "1) 选择元素,晶体结构和晶格常数。\n" " [读取结构]按钮包含指定元素的数据。\n" "\n" "2) 进行选择你想通过指定每个方向上的层数或 \n" " 使用Wulff construction。如使用后者,你必须指定各个方向上的表面能和团蔟的" "大小。\n" "\n" "怎样指定方向:\n" "------------------------------\n" "\n" "方向第一次出现时,它代表整个晶向族,\n" "就是说: (0,0,1) 包含 (1,0,0), (-1,0,0) 等. 如果被包含的任何一\n" "个方向被重新指定,那么后者会覆盖该方向的原始定义。所以先后次序很重要。你可\n" "以用[上]和[下]改变方向。你也可以添加新的方向,但是请记住\n" "点击[添加]以确认添加。例如:(1,0,0) (1,1,1), (0,0,1) 先指\n" "定了{100}晶向族,然后是{111}晶向族,最后(001)覆盖了{100}晶向族定义中改晶向\n" "的定义。\n" #. Structures: Abbreviation, name, 4-index (boolean), two lattice const (bool), factory #: ../nanoparticle.py:84 msgid "Face centered cubic (fcc)" msgstr "面心立方 (fcc)" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "体心立方 (bcc)" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "简单立方 (sc)" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "六角密堆积 (hcp)" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "石墨" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "纳米颗粒" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "元素" #: ../nanoparticle.py:131 msgid "Get structure" msgstr "读取结构" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "晶格常数: a =" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "方法:" #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "层指定" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "Wulff构造" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "虚设占位符对象" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "添加新的方向" #: ../nanoparticle.py:212 msgid "Add" msgstr "添加" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "把所有方向设置成默认值" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "纳米颗粒大小:" #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:196 msgid "Number of atoms: " msgstr "原子数目:" #: ../nanoparticle.py:234 msgid "Volume: " msgstr "体积:" #: ../nanoparticle.py:239 msgid "ų" msgstr "ų" #: ../nanoparticle.py:244 msgid "Rounding: If exact size is not possible, choose the size" msgstr "取整:如果没有具体的尺寸,请选择相近尺寸" #: ../nanoparticle.py:247 msgid "above " msgstr "上面" #: ../nanoparticle.py:248 msgid "below " msgstr "下面" #: ../nanoparticle.py:249 msgid "closest " msgstr "最近邻的" #: ../nanoparticle.py:252 msgid "Smaller" msgstr "更小" #: ../nanoparticle.py:253 msgid "Larger" msgstr "更大" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr " 近似直径:" #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "创建的团蔟信息:" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "创建纳米颗粒中。" #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "自动运行" #: ../nanoparticle.py:333 msgid "Up" msgstr "上" #: ../nanoparticle.py:338 msgid "Down" msgstr "下" #: ../nanoparticle.py:343 msgid "Delete" msgstr "删除" #: ../nanoparticle.py:384 msgid "Surface energies (as energy/area, NOT per atom):" msgstr "表面能(单位面积,不是每个原子):" #: ../nanoparticle.py:390 msgid "Number of layers:" msgstr "层数" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "至少一个指数必须不为零" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "无效的六角指数" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "无效元素" #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "不支持或未知的结构" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "%.1f Å" #: ../nanotube.py:15 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 "" "通过指定(n,m) roll-up 矢量,来创建碳纳米管\n" "请注意 m <= n.\n" "\n" "其他元素的纳米管可以通过指定元素和健长来创建。" #: ../nanotube.py:29 #, fuzzy, python-format #| msgid " %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3" msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: %" "(volume).3f Å3" msgstr " %(natoms)i 原子: %(symbols)s, 体积: %(volume).3f A3" #: ../nanotube.py:35 msgid "Nanotube" msgstr "纳米管" #. Choose the structure. #: ../nanotube.py:59 msgid "Select roll-up vector (n,m) and tube length:" msgstr "选择roll-up 矢量(n,m)和管长度:" #: ../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 " 第%s步,总共 %s步。" #. 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 "Fmax: " #: ../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 "log10(变化):" #: ../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 "GPAW 版本:" #: ../progress.py:197 msgid "N/A" msgstr "N/A" #: ../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 "Python" #: ../pybutton.py:48 msgid "No Python code" msgstr "没有Python代码" #: ../pybutton.py:52 #, python-format msgid "" "\n" "Title: %(title)s\n" "Time: %(time)s\n" msgstr "" "\n" "标题: %(title)s\n" "时间: %(time)s\n" #: ../pybutton.py:61 msgid "ag: Python code" msgstr "ag: Python代码" #: ../pybutton.py:65 msgid "Information:" msgstr "信息:" #: ../pybutton.py:72 msgid "Python code:" msgstr "Python代码:" #: ../quickinfo.py:9 msgid "Single image loaded." msgstr "加载了单个图像。" #: ../quickinfo.py:10 #, python-format msgid "Image %d loaded (0 - %d)." msgstr "加载了图像 %d (0 - %d)." #: ../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 "" "%s\n" "\n" "原子数目: %d.\n" "\n" "原胞:\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 "简单信息" #: ../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 "" " 材质可以用来标识原子结构的不同部分。这个窗口对所有\n" " 的结构使用默认的材质。你也可以用鼠标选择对指定的原子集合\n" " 使用不同的材质。也可以通过提供的boolean表达式来\n" " 进行原子选择。例如:表达式Z == 11 and x > 10 and y > 10,\n" " 这将选择x和y坐标大于10的钠原子。然后通过‘给指定\n" " 的原子集合创建新的材质’来更改材质的属性。\n" " " #: ../render.py:32 msgid "Render current view in povray ... " msgstr "在povray中渲染当前视图 ..." #: ../render.py:36 #, python-format msgid "Rendering %d atoms." msgstr "渲染%d 原子中。" #: ../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 "Angstrom " #: ../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 "渲染所有 %d 帧" #: ../render.py:122 msgid "Transparent background" msgstr "透明的背景" #: ../render.py:125 msgid "Run povray " msgstr "运行povray" #: ../render.py:128 msgid "Keep povray files " msgstr "保持vray文件" #: ../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 "" "注意:\n" "按住按钮2(通常为右键),你用鼠标\n" "进行可以自由的旋转。" #: ../scaling.py:49 msgid "Homogeneous scaling" msgstr "均匀缩放" #: ../scaling.py:59 msgid "3D deformation " msgstr "3维形变 " #: ../scaling.py:60 msgid "2D deformation " msgstr "2维形变 " #: ../scaling.py:61 msgid "1D deformation " msgstr "1维形变 " #: ../scaling.py:64 msgid "Bulk" msgstr "块体" #: ../scaling.py:66 msgid "xy-plane" msgstr "xy平面" #: ../scaling.py:68 msgid "xz-plane" msgstr "xz平面" #: ../scaling.py:70 msgid "yz-plane" msgstr "yz平面" #: ../scaling.py:72 msgid "x-axis" msgstr "x轴" #: ../scaling.py:74 msgid "y-axis" msgstr "y轴" #: ../scaling.py:76 msgid "z-axis" msgstr "z轴" #: ../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 "应力\t\t能量 [eV]" #: ../scaling.py:144 msgid "Fit:" msgstr "拟合:" #: ../scaling.py:148 msgid "2nd" msgstr "第2个" #: ../scaling.py:149 msgid "3rd" msgstr "第3个" #: ../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 "" "需要拟合的数据不够\n" "(只有 %i 个数据点)\n" #: ../scaling.py:424 msgid "" "REVERTING TO 2ND ORDER FIT\n" "(only 3 data points)\n" "\n" msgstr "" "还原到2阶拟合\n" "(只有3个数据点)\n" "\n" #: ../scaling.py:440 msgid "No minimum found!" msgstr "未发现最小值!" #: ../scaling.py:454 msgid "" "\n" "WARNING: Minimum is outside interval\n" msgstr "" "\n" "警告:最小值不再区间内\n" # XXX 在 #: ../scaling.py:455 msgid "It is UNRELIABLE!\n" msgstr "不可靠!\n" #: ../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 "\n" #: ../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 "目前加载了%i个构型。" #: ../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 "第一个构型 %s." #: ../simulation.py:43 msgid "Configuration number " msgstr "构型数目" #: ../simulation.py:49 #, python-format msgid "The last configuration %s." msgstr "最后一个构型 %s." #: ../simulation.py:85 msgid "Run" msgstr "运行" #: ../simulation.py:105 msgid "No calculator: Use Calculate/Set Calculator on the menu." msgstr "未找到计算器: 请使用菜单上的Calculate/设置计算器。" #: ../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 "标签=%(tag)s 磁矩=%(mom)1.2f" #: ../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 "" " 使用这个窗口来创建表面。通过输入化学元素或原子序号来选择\n" "元素。然后选择需要的表面结构。注意,有些结构的原胞可以是正交\n" "的或非正交的。这种情况下,非正交的原胞包含更少的原子。\n" "\n" "如果符合实验的晶体结构,你可以查找晶格常数,否则你需要自己指定。" #. 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) 非正交的" #: ../surfaceslab.py:30 msgid "FCC(111) orthogonal" msgstr "FCC(111) 正交的" #: ../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) 非正交的" #: ../surfaceslab.py:34 msgid "BCC(110) orthogonal" msgstr "BCC(110) 正交的" #: ../surfaceslab.py:35 msgid "BCC(111) non-orthogonal" msgstr "BCC(111) 非正交的" #: ../surfaceslab.py:37 msgid "BCC(111) orthogonal" msgstr "BCC(111) 正交的" #: ../surfaceslab.py:38 msgid "HCP(0001) non-orthogonal" msgstr "HCP(0001) 非正交的" #: ../surfaceslab.py:38 ../surfaceslab.py:40 ../surfaceslab.py:41 msgid "hcp" msgstr "hcp" #: ../surfaceslab.py:40 msgid "HCP(0001) orthogonal" msgstr "HCP(0001) 正交的" #: ../surfaceslab.py:41 msgid "HCP(10-10) orthogonal" msgstr "HCP(10-10) 正交的" #: ../surfaceslab.py:43 msgid "DIAMOND(100) orthogonal" msgstr "金刚石结构(100) 正交的" #: ../surfaceslab.py:43 ../surfaceslab.py:45 msgid "diamond" msgstr "金刚石" #: ../surfaceslab.py:45 msgid "DIAMOND(111) non-orthogonal" msgstr "金刚石结构(111) 非正交的" #: ../surfaceslab.py:60 msgid "Surface" msgstr "表面" #: ../surfaceslab.py:90 msgid "Lattice constant: " msgstr "晶格常数:" #: ../surfaceslab.py:97 msgid "a:" msgstr "a" #: ../surfaceslab.py:109 #, python-format msgid "(%.1f %% of ideal)" msgstr "(%.1f %% 理想的)" #: ../surfaceslab.py:126 msgid "Size: \tx: " msgstr "大小: \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 " 层, " #: ../surfaceslab.py:132 msgid " Å vacuum" msgstr "Å 真空" #: ../surfaceslab.py:133 msgid "\t\tNo size information yet." msgstr "\t\t还没有尺寸大小信息。" #. Buttons #: ../surfaceslab.py:142 msgid "Creating a surface slab." msgstr "创建表面。" #: ../surfaceslab.py:212 #, python-format msgid "%i atoms." msgstr "%i 原子" #: ../surfaceslab.py:224 msgid "No structure specified!" msgstr "未指定结构!" #: ../surfaceslab.py:233 #, python-format msgid "%(struct)s lattice constant unknown for %(element)s." msgstr "对于%(element)s, %(struct)s 晶格常数未知。" #: ../widgets.py:53 ../widgets.py:81 msgid "Help" msgstr "帮助" #: ../widgets.py:98 msgid "Clear constraint" msgstr "清空限制" #~ msgid "选择 Calculator" #~ msgstr "选择计算器" #~ msgid "Help for plot ..." #~ msgstr "画图帮助 ..." python-ase-3.9.1.4567/ase/gui/po/es/0000775000175000017500000000000012553427753017063 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/es/LC_MESSAGES/0000775000175000017500000000000012553427753020650 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/es/LC_MESSAGES/ag.po0000664000175000017500000025234012553425551021577 0ustar jensjjensj00000000000000# Spanish translations for ASE package. # Copyright (C) 2012-2015 CAMD # This file is distributed under the same license as the ASE package. # Ask Hjorth Larsen , 2012-15. # Max Ramirez , 2012. # msgid "" msgstr "" "Project-Id-Version: ase-3.5.2\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2015-07-15 17:25+0200\n" "PO-Revision-Date: 2015-07-15 17:29+0200\n" "Last-Translator: Max Ramirez \n" "Language-Team: Spanish\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../ag.py:144 msgid "To get a full traceback, use: ase-gui --verbose" msgstr "Para ver el traceback entero, use ase-gui --verbose" #. 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. \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 EAM/ADP potential is a many-body potential\n" "implementation of the Embedded Atom Method and\n" "equipotential plus the Angular Dependent Potential,\n" "which is an extension of the EAM to include\n" "directional bonds. EAM is suited for FCC metallic\n" "bonding while the ADP is suited for metallic bonds\n" "with some degree of directionality.\n" "\n" "For EAM see M.S. Daw and M.I. Baskes,\n" "Phys. Rev. Letters 50 (1983) 1285.\n" "\n" "For ADP see Y. Mishin, M.J. Mehl, and\n" "D.A. Papaconstantopoulos, Acta Materialia 53 2005\n" "4029--4041.\n" "\n" "Data for the potential is contained in a file in either LAMMPS Alloy\n" "or ADP format which need to be loaded before use. The Interatomic\n" "Potentials Repository Project at http://www.ctcms.nist.gov/potentials/\n" "contains many suitable potential files.\n" "\n" "For large simulations the LAMMPS calculator is more\n" "suitable; this implementation is mainly to make EAM\n" "available when LAMMPS is not installed or to develop\n" "new EAM/ADP poentials by matching results using ab\n" "initio.\n" msgstr "" "El potencial EAM/ADP es una implementación del método «embedded atom»\n" "(EAM) y equipotencial más el potencial direccional (ADP) como\n" "potencial de muchos cuerpos. ADP es una extensión del EAM para\n" "incluir enlaces direccionales. El EAM es adecuado para enlaces\n" "metálicos FCC mientras ADP es adecuado para enlaces metálicos con\n" "cierto carácter direccional.\n" "\n" "Para EAM véase M.S. Daw y M.I. Baskes,\n" "Phys. Rev. Letters 50 (1983) 1285.\n" "\n" "Para ADP véase Y. Mishin, M.J. Mehl, y\n" "D.A. Papaconstantopoulos, Acta Materialia 53 2005\n" "4029--4041.\n" "\n" "Los datos del potencial se encuentran en un fichero con formato LAMMPS\n" "Alloy o ADP, que necesita ser cargado antes de usarse. Muchos ficheros\n" "de potenciales adecuados están disponibles en el proyecto de\n" "potenciales interatómicos en http://www.ctcms.nist.gov/potentials/.\n" "\n" "Para simulaciones grandes el calculador LAMMPS es más eficiente; esta\n" "implementación sirve principalmente para que EAM esté disponible cuando\n" "LAMMPS no se haya instalado o para desarrollar nuevos potenciales\n" "EAM/ADP comparando los resultados con aquellos obtenidos con métodos\n" "ab-initio.\n" #: ../calculator.py:113 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:135 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:142 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:152 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:159 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:168 msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)" msgstr "Por defecto (Al, Ni, Cu, Pd, Ag, Pt, Au)" #: ../calculator.py:169 msgid "Alternative Cu, Ag and Au" msgstr "Parámetros alternativos para Cu, Ag y Au" #: ../calculator.py:170 msgid "Ruthenium" msgstr "Rutenio" #: ../calculator.py:171 msgid "CuMg and CuZr metallic glass" msgstr "Vidrios metálicos de CuMg y CuZr" #: ../calculator.py:189 msgid "Select calculator" msgstr "Seleccione Calculador (Calculator)" #: ../calculator.py:195 msgid "Calculator:" msgstr "Calculador:" #. No calculator (the default) #: ../calculator.py:198 msgid "None" msgstr "Ninguno" #: ../calculator.py:203 msgid "Lennard-Jones (ASAP)" msgstr "Lennard-Jones (ASAP)" #: ../calculator.py:204 ../calculator.py:231 ../calculator.py:246 #: ../calculator.py:255 ../calculator.py:264 msgid "Setup" msgstr "Configuración" # EMT - Effective Medium Theory (ASAP) #: ../calculator.py:211 msgid "EMT - Effective Medium Theory (ASAP)" msgstr "EMT - Teoría Media Efectiva (ASAP)" #: ../calculator.py:223 msgid "EMT - Effective Medium Theory (ASE)" msgstr "EMT - Teoría Media Efectiva (ASE)" #: ../calculator.py:230 msgid "EAM - Embedded Atom Method/Angular Dependent Potential (ASE)" msgstr "EAM - Método «embedded atom»/potencial direccional (ASE)" #: ../calculator.py:238 msgid "Brenner Potential (ASAP)" msgstr "Potencial de Brenner (ASAP)" #: ../calculator.py:244 msgid "Density Functional Theory (GPAW)" msgstr "Teoría del funcional de la densidad (GPAW)" #: ../calculator.py:253 msgid "Density Functional Theory (FHI-aims)" msgstr "Teoría del funcional de la densidad (FHI-aims)" #: ../calculator.py:262 msgid "Density Functional Theory (VASP)" msgstr "Teoría del funcional de la densidad (VASP)" #: ../calculator.py:275 msgid "Check that the calculator is reasonable." msgstr "Compruebe que el calculador sea razonable." #: ../calculator.py:345 ../simulation.py:114 msgid "No atoms present" msgstr "No hay átomos presentes" #: ../calculator.py:439 ../calculator.py:474 ../calculator.py:521 msgid "ASAP is not installed. (Failed to import asap3)" msgstr "ASAP no está instalado. (Error al importar asap3)" #: ../calculator.py:442 msgid "You must set up the Lennard-Jones parameters" msgstr "Usted debe establecer los parámetros del potencial de Lennard-Jones" #: ../calculator.py:447 msgid "Could not create useful Lennard-Jones calculator." msgstr "No se pudo crear un calculador Lennard-Jones útil." #: ../calculator.py:482 msgid "Could not attach EMT calculator to the atoms." msgstr "No se pudo adjuntar el calculador EMT a los átomos." #: ../calculator.py:503 msgid "You must set up the EAM parameters" msgstr "Debe establecer los parámetros para EAM" #: ../calculator.py:539 ../calculator.py:551 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "GPAW no está instalado (Error al importar gpaw)" #: ../calculator.py:542 msgid "You must set up the GPAW parameters" msgstr "Debe establecer los parámetros para GPAW" #: ../calculator.py:584 msgid "You must set up the FHI-aims parameters" msgstr "Debe establecer los parámetros para FHI-aims" #: ../calculator.py:599 msgid "You must set up the VASP parameters" msgstr "Debe establecer los parámetros para VASP" #: ../calculator.py:624 #, python-format msgid "Element %(sym)s not allowed by the '%(name)s' calculator" msgstr "El elemento %(sym)s no está permitido para el calculador '%(name)s'" #: ../calculator.py:632 msgid "Info" msgstr "Información" #: ../calculator.py:648 msgid "Lennard-Jones parameters" msgstr "Parámetros de Lennard-Jones" #: ../calculator.py:660 msgid "Specify the Lennard-Jones parameters here" msgstr "Especifique los parámetros de Lennard-Jones aquí" # Epsilon (eV) #: ../calculator.py:663 msgid "Epsilon (eV):" msgstr "Epsilon (eV):" #: ../calculator.py:667 msgid "Sigma (Å):" msgstr "Sigma (Å):" #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:671 msgid "Shift to make smooth at cutoff" msgstr "Cambie para que el corte sea suave" #: ../calculator.py:750 msgid "EAM parameters" msgstr "Parámetros de EAM" #: ../calculator.py:764 msgid "Import Potential" msgstr "Importar potencial" #: ../calculator.py:787 msgid "You need to import the potential file" msgstr "Se necesita importar el fichero del potencial" #: ../calculator.py:795 msgid "Import .alloy or .adp potential file ... " msgstr "Importar fichero potencial .alloy o .adp ..." #: ../calculator.py:818 msgid "GPAW parameters" msgstr "Parámetros de GPAW" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:833 ../calculator.py:1123 ../calculator.py:1612 #, python-format msgid "%i atoms.\n" msgstr "átomos %i.\n" #: ../calculator.py:835 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "Celda unitaria ortogonal: %.2f x %.2f x %.2f Å." #: ../calculator.py:837 msgid "Non-orthogonal unit cell:\n" msgstr "Celda unitaria no ortogonal:\n" #: ../calculator.py:847 ../calculator.py:1139 ../calculator.py:1627 msgid "Exchange-correlation functional: " msgstr "Funcional de intercambio y correlación: " #. Grid spacing #: ../calculator.py:851 msgid "Grid spacing" msgstr "Espacio de grilla" #: ../calculator.py:855 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "Å" #: ../calculator.py:856 msgid "Grid points" msgstr "Puntos de grilla" #: ../calculator.py:865 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "heff = (%.3f, %.3f, %.3f) Å" #: ../calculator.py:891 ../calculator.py:1154 ../calculator.py:1663 msgid "k-points k = (" msgstr "puntos k k=(" #: ../calculator.py:895 ../calculator.py:1158 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "Tamaño de los puntos k: (%.1f, %.1f, %.1f) Å" #. Spin polarized #: ../calculator.py:900 ../calculator.py:1625 msgid "Spin polarized" msgstr "Polarizado de espín" #: ../calculator.py:906 msgid "FD - Finite Difference (grid) mode" msgstr "Modo de grilla tipo diferencias finitas" #: ../calculator.py:907 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "LCAO - Combinaciones lineales de orbitales atómicos" #: ../calculator.py:910 msgid "Mode: " msgstr "Modo: " #: ../calculator.py:912 msgid "sz - Single Zeta" msgstr "sz - Single Zeta" #: ../calculator.py:913 msgid "szp - Single Zeta polarized" msgstr "szp - Single Zeta polarizado" #: ../calculator.py:914 msgid "dzp - Double Zeta polarized" msgstr "dzp - Doble Zeta polarizado" #. dzp #: ../calculator.py:916 msgid "Basis functions: " msgstr "Funciones base: " #. Mixer #: ../calculator.py:922 msgid "Non-standard mixer parameters" msgstr "Parámetros combinados no estándar" #: ../calculator.py:1119 msgid "FHI-aims parameters" msgstr "Parámetros de FHI-aims" #: ../calculator.py:1126 msgid "Periodic geometry, unit cell is:\n" msgstr "Geometría periódica, la celda unitaria es:\n" #: ../calculator.py:1131 msgid "Non-periodic geometry.\n" msgstr "Geometría no periódica\n" #: ../calculator.py:1138 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:1164 msgid "Spin / initial moment " msgstr "Spin / momento inicial" #: ../calculator.py:1182 msgid " Charge" msgstr " Carga" #: ../calculator.py:1184 msgid " Relativity" msgstr " Relatividad" #: ../calculator.py:1186 msgid " Threshold" msgstr " Umbral" #. self-consistency criteria #: ../calculator.py:1191 msgid "Self-consistency convergence:" msgstr "Convergencia auto-consistente:" #: ../calculator.py:1204 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:1215 msgid "Energy: " msgstr "Energía: " #: ../calculator.py:1217 msgid " eV Sum of eigenvalues: " msgstr " eV Suma de los autovalores: " #: ../calculator.py:1219 ../calculator.py:1698 msgid " eV" msgstr " eV" #: ../calculator.py:1220 msgid "Electron density: " msgstr "Densidad electrónica: " #: ../calculator.py:1222 msgid " Force convergence: " msgstr " Convergencia de la fuerza: " #: ../calculator.py:1224 msgid " eV/Ang " msgstr " eV/Å " #: ../calculator.py:1237 ../calculator.py:1709 msgid "Additional keywords: " msgstr "Palabras clave adicionales: " #. run command and species defaults: #: ../calculator.py:1251 msgid "FHI-aims execution command: " msgstr "Comando de ejecución por FHI-aims: " #: ../calculator.py:1253 ../calculator.py:1726 msgid "Directory for species defaults: " msgstr "Directorio para las especies por defecto: " #: ../calculator.py:1265 ../calculator.py:1734 msgid "Set Defaults" msgstr "Establecer por defecto" #: ../calculator.py:1267 msgid "Import control.in" msgstr "Importar control.in" #: ../calculator.py:1269 msgid "Export control.in" msgstr "Exportar control.in" #: ../calculator.py:1456 msgid "Export parameters ... " msgstr "Exportar parámetros ... " #: ../calculator.py:1476 msgid "Import control.in file ... " msgstr "Importar el archivo control.in ... " #: ../calculator.py:1532 ../calculator.py:2041 #, 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:1535 #, 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:1608 msgid "VASP parameters" msgstr "Parámetros de VASP" #: ../calculator.py:1614 msgid "Periodic geometry, unit cell is: \n" msgstr "Geometría periódica, la celda unitaria es: \n" #: ../calculator.py:1666 msgid ") Cutoff: " msgstr ") radio de corte: " #: ../calculator.py:1667 msgid " Precision: " msgstr " Precisión: " #: ../calculator.py:1669 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "Tamaño de los puntos k: (%.1f, %.1f, %.1f) Å " # Smearing: #: ../calculator.py:1685 msgid "Smearing: " msgstr "Smearing: " #: ../calculator.py:1687 msgid " order: " msgstr " orden: " #: ../calculator.py:1689 msgid " width: " msgstr " ancho: " #: ../calculator.py:1696 msgid "Self-consistency convergence: " msgstr "Convergencia auto-consistente: " #. run command and location of POTCAR files: #: ../calculator.py:1722 msgid "VASP execution command: " msgstr "Comando de ejecución de VASP: " #: ../calculator.py:1736 msgid "Import VASP files" msgstr "Importar archivos de VASP" #: ../calculator.py:1738 msgid "Export VASP files" msgstr "Exportar archivos de VASP" #: ../calculator.py:1945 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:1997 msgid "Import VASP input files: choose directory ... " msgstr "Importando archivos de entrada de VASP: elija directorio ... " #: ../calculator.py:2011 msgid "Export VASP input files: choose directory ... " msgstr "Exportando archivos de salida de VASP: elija directorio ... " #: ../calculator.py:2044 #, 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:27 msgid "Colors" msgstr "Colores" #. Upper left: Choose how the atoms are colored. #: ../colors.py:44 msgid "Choose how the atoms are colored:" msgstr "Elija el color de los átomos:" #: ../colors.py:46 msgid "By atomic number, default \"jmol\" colors" msgstr "Por número atómico, colores de \"jmol\" por defecto" #: ../colors.py:48 msgid "By atomic number, user specified" msgstr "Por número atómico, especificado por el usuario" #: ../colors.py:49 msgid "By tag" msgstr "Por etiqueta" #: ../colors.py:50 msgid "By force" msgstr "Por fuerza" #: ../colors.py:51 msgid "By velocity" msgstr "Por velocidad" #: ../colors.py:52 msgid "By charge" msgstr "Por carga" #: ../colors.py:54 msgid "By magnetic moment" msgstr "Por momento magnético" #: ../colors.py:56 msgid "By coordination" msgstr "Por coordinación" #: ../colors.py:57 msgid "Manually specified" msgstr "Especificado manualmente" #: ../colors.py:58 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:74 msgid "This should not be displayed in forces!" msgstr "¡Esto no debería ser mostrado en fuerzas!" #: ../colors.py:79 ../colors.py:93 ../colors.py:108 ../colors.py:124 #: ../rotate.py:25 msgid "Update" msgstr "Actualizar" #: ../colors.py:81 ../colors.py:95 ../colors.py:110 ../colors.py:126 msgid "Min: " msgstr "Mín: " #: ../colors.py:83 ../colors.py:97 ../colors.py:112 ../colors.py:128 msgid " Max: " msgstr " Máx: " #: ../colors.py:85 ../colors.py:99 ../colors.py:114 ../colors.py:130 msgid " Steps: " msgstr " Pasos: " #. Now fill in the box for additional information in case #. the charge is used. #: ../colors.py:106 ../colors.py:122 msgid "This should not be displayed!" msgstr "¡Esto no debería ser desplegado!" #: ../colors.py:137 msgid "Create a color scale:" msgstr "Crear una escala de colores:" #: ../colors.py:140 msgid "Black - white" msgstr "Negro - blanco" #: ../colors.py:141 msgid "Black - red - yellow - white" msgstr "Negro - rojo - amarillo - blanco" #: ../colors.py:142 msgid "Black - green - white" msgstr "Negro - verde - blanco" #: ../colors.py:143 msgid "Black - blue - cyan" msgstr "Negro - azul - cian" #: ../colors.py:144 msgid "Blue - white - red" msgstr "Azul - blanco - rojo" #: ../colors.py:145 msgid "Hue" msgstr "Tonalidad" #: ../colors.py:146 msgid "Named colors" msgstr "Colores con nombre" #: ../colors.py:152 msgid "Create" msgstr "Crear" #: ../colors.py:517 msgid "ERROR" msgstr "ERROR" #: ../colors.py:546 msgid "ERR" msgstr "ERR" #: ../colors.py:638 msgid "Incorrect color specification" msgstr "Especificación de color incorrecta" #: ../constraints.py:12 ../widgets.py:96 msgid "Constraints" msgstr "Restricciones" #: ../constraints.py:14 ../constraints.py:17 ../settings.py:16 #: ../widgets.py:98 ../widgets.py:101 msgid "Constrain" msgstr "Restricción" #: ../constraints.py:15 ../settings.py:19 ../settings.py:34 ../widgets.py:99 msgid " selected atoms" msgstr " átomos seleccionados" #: ../constraints.py:18 ../widgets.py:102 msgid " immobile atoms:" msgstr " átomos inamovibles:" #: ../constraints.py:20 msgid "Unconstrain" msgstr "Liberar restriccciones" #: ../constraints.py:21 msgid " selected atoms:" msgstr " átomos seleccionados:" #: ../constraints.py:23 msgid "Clear constraints" msgstr "Quitar las restricciones" #: ../constraints.py:25 ../dft.py:28 ../settings.py:52 ../widgets.py:65 #: ../widgets.py:106 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 ../graphene.py:27 #, 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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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:12 msgid "Debug" msgstr "Depurar" #: ../dft.py:12 msgid "DFT" msgstr "DFT" #: ../dft.py:18 msgid "XC-functional: " msgstr "Funcional de XC: " #: ../dft.py:22 ../repeat.py:14 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:22 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: ase-gui window python object\n" " img:\tadvanced: ase-gui 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:66 msgid "Expert user mode" msgstr "Modo de usuario experto" #: ../execute.py:79 msgid "Welcome to the ASE Expert user mode" msgstr "Bienvenido al modo de usuario experto de ASE" #: ../execute.py:86 msgid "Only selected atoms (sa) " msgstr "Sólo los átomos seleccionados (sa) " #: ../execute.py:88 msgid "Only current frame (cf) " msgstr "Sólo el cuadro actual (cf) " #: ../execute.py:98 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:197 #, python-format msgid "*** WARNING: file does not exist - %s" msgstr "*** ADVERTENCIA: el archivo no existe - %s" #: ../execute.py:202 msgid "*** WARNING: No atoms selected to work with" msgstr "***ADVERTENCIA: No hay átomos seleccionados para trabajar" #: ../execute.py:276 msgid "*** Only working on selected atoms" msgstr "*** Trabajando sólo en los átomos seleccionados" #: ../execute.py:278 msgid "*** Working on all atoms" msgstr "*** Trabajando en todos los átomos" #: ../execute.py:282 msgid "*** Only working on current image" msgstr "*** Trabajando solamente en la imagen actual" #: ../execute.py:284 msgid "*** Working on all images" msgstr "*** Trabajando en todas las imágenes" #: ../execute.py:300 msgid "Save Terminal text ..." msgstr "Guarde texto a Terminal ..." #: ../graphene.py:16 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:33 ../gui.py:345 msgid "Graphene" msgstr "Grafeno" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "Estructura: " #: ../graphene.py:42 msgid "Infinite sheet" msgstr "Sábana infinita" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "Cinta no saturada" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "Cinta saturada" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "Orientación: " #: ../graphene.py:53 msgid "zigzag" msgstr "Zigzag" #: ../graphene.py:53 msgid "armchair" msgstr "Sillón" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 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:90 msgid "Width: " msgstr "Ancho: " #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr " Largo: " #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "Vacío: " #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr " ¡No se especifica el elemento!" #: ../graphene.py:194 msgid "Please specify a consistent set of atoms. " msgstr "Por favor, especifique un conjunto consistente de átomos. " #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../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:7 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" "Ayuda para graficar ...\n" "\n" "e:\t\t\t\tenergía total\n" "epot:\t\t\tenergía potencial\n" "ekin:\t\t\tenergía cinética\n" "fmax:\t\t\tfuerza máxima\n" "fave:\t\t\tfuerza media\n" "R[n,0-2]:\t\t\tposición del átomo de número n\n" "d(n1,n2):\t\t\tdistancia entre dos átomos " "n1 y n2\n" "i:\t\t\t\tnúmero de la imagen actual\n" "E[i]:\t\t\t\tenergía del número de la imagen i\n" "F[n,0-2]:\t\t\tfuerza de en número de átomos de n\n" "V[n,0-2]:\t\t\tvelocidad de número de átomos de n\n" "M[n]:\t\t\tmomento magnético de número de átomos de n\n" "A[0-2,0-2]:\t\tcelda unitaria vectores de la base\n" "s:\t\t\t\tlongitud de la trayectoria\n" "a(n1,n2,n3):\t\tángulo entre los átomos n1, " "n2 and n3, centrado en n2\n" "dih(n1,n2,n3,n4):\tdiedro ángulo entre n1, " "n2, n3 y n4\n" "T:\t\t\t\ttemperatura (K)" #: ../graphs.py:50 ../graphs.py:53 msgid "Plot" msgstr "Graficar" #: ../graphs.py:58 msgid "clear" msgstr "Limpiar" #: ../graphs.py:112 msgid "Save data to file ... " msgstr "Salve los datos a un archivo ..." #: ../gtkexcepthook.py:118 msgid "Bug Detected" msgstr "Error detectado" #: ../gtkexcepthook.py:122 msgid "A programming error has been detected." msgstr "Un error de programación ha sido detectado." #: ../gtkexcepthook.py:125 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:141 msgid "Report..." msgstr "Reporte..." #: ../gtkexcepthook.py:145 msgid "Details..." msgstr "Detalles..." #: ../gtkexcepthook.py:161 #, 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:174 msgid "Bug Details" msgstr "Detalles del error" #: ../gui.py:191 msgid "_File" msgstr "_Archivo" #: ../gui.py:192 msgid "_Edit" msgstr "_Editar" #: ../gui.py:193 msgid "_View" msgstr "_Ver" #: ../gui.py:194 msgid "_Tools" msgstr "_Herramientas" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:196 msgid "_Setup" msgstr "_Configurar" #: ../gui.py:197 msgid "_Calculate" msgstr "_Calcular" #: ../gui.py:198 msgid "_Help" msgstr "_Ayuda" #: ../gui.py:199 msgid "_Open" msgstr "_Abrir" #: ../gui.py:200 msgid "Create a new file" msgstr "Crear un archivo nuevo" #: ../gui.py:202 msgid "_New" msgstr "_Nuevo" #: ../gui.py:203 msgid "New ase.gui window" msgstr "Nueva ventana ase.gui" #: ../gui.py:205 msgid "_Save" msgstr "_Guardar" #: ../gui.py:206 msgid "Save current file" msgstr "Guardar archivo actual" #: ../gui.py:208 msgid "_Quit" msgstr "_Salir" #: ../gui.py:209 msgid "Quit" msgstr "Salir" #: ../gui.py:211 msgid "Select _all" msgstr "Seleccionar _todo" #: ../gui.py:214 msgid "_Invert selection" msgstr "_Invertir selección" #: ../gui.py:217 msgid "Select _constrained atoms" msgstr "Seleccionar los átomos _restringidos" #: ../gui.py:220 msgid "Select _immobile atoms" msgstr "Seleccionar los átomos _inmóbiles" #: ../gui.py:223 msgid "_Copy" msgstr "_Copiar" #: ../gui.py:224 msgid "Copy current selection and its orientation to clipboard" msgstr "Copiar la selección actual y su orientación" #: ../gui.py:226 msgid "_Paste" msgstr "_Pegar" #: ../gui.py:227 msgid "Insert current clipboard selection" msgstr "Insertar selección actual" #: ../gui.py:229 msgid "_Modify" msgstr "_Modificar" #: ../gui.py:230 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:232 msgid "_Add atoms" msgstr "_Añadir átomos" #: ../gui.py:233 msgid "Insert or import atoms and molecules" msgstr "Insertar o importar átomos y moléculas" #: ../gui.py:235 msgid "_Delete selected atoms" msgstr "_Borrar átomos seleccionados" #: ../gui.py:236 msgid "Delete the selected atoms" msgstr "Borrar los átomos seleccionados" #: ../gui.py:238 msgid "_First image" msgstr "_Primera imagen" #: ../gui.py:241 msgid "_Previous image" msgstr "_Imagen previa" #: ../gui.py:244 msgid "_Next image" msgstr "_Próxima imagen" #: ../gui.py:247 msgid "_Last image" msgstr "Ú_ltima imagen" #: ../gui.py:250 msgid "Show _Labels" msgstr "Mostrar los _etiquetas" #: ../gui.py:251 msgid "Hide selected atoms" msgstr "Ocultar átomos seleccionados" #: ../gui.py:254 msgid "Show selected atoms" msgstr "Mostrar átomos seleccionados" #: ../gui.py:257 msgid "Quick Info ..." msgstr "Información rápida ..." #: ../gui.py:260 msgid "Repeat ..." msgstr "Repetir ..." #: ../gui.py:263 msgid "Rotate ..." msgstr "Rotar ..." #: ../gui.py:266 msgid "Colors ..." msgstr "Colores ..." #. TRANSLATORS: verb #: ../gui.py:269 msgid "Focus" msgstr "Enfocar" #: ../gui.py:272 msgid "Zoom in" msgstr "Ampliar" #: ../gui.py:275 msgid "Zoom out" msgstr "Alejar" #: ../gui.py:278 msgid "Change View" msgstr "Cambiar de vista" #: ../gui.py:279 msgid "Reset View" msgstr "Reiniciar la vista" #: ../gui.py:282 msgid "'xy' Plane" msgstr "Plano 'xy'" #: ../gui.py:283 msgid "'yz' Plane" msgstr "Plano 'yz'" #: ../gui.py:284 msgid "'zx' Plane" msgstr "Plano 'zx'" #: ../gui.py:285 msgid "'yx' Plane" msgstr "Plano 'yx'" #: ../gui.py:286 msgid "'zy' Plane" msgstr "Plano 'zy'" #: ../gui.py:287 msgid "'xz' Plane" msgstr "Plano 'xz'" #: ../gui.py:288 msgid "'a2 a3' Plane" msgstr "Plano 'a2 a3'" #: ../gui.py:289 msgid "'a3 a1' Plane" msgstr "Plano 'a3 a1'" #: ../gui.py:290 msgid "'a1 a2' Plane" msgstr "Plano 'a1 a2'" #: ../gui.py:291 msgid "'a3 a2' Plane" msgstr "Plano 'a3 a2'" #: ../gui.py:292 msgid "'a1 a3' Plane" msgstr "Plano 'a1 a3'" #: ../gui.py:293 msgid "'a2 a1' Plane" msgstr "Plano 'a2 a1'" #: ../gui.py:294 msgid "Settings ..." msgstr "Ajustes ..." #: ../gui.py:297 msgid "VMD" msgstr "VMD" #: ../gui.py:300 msgid "RasMol" msgstr "RasMol" #: ../gui.py:303 msgid "xmakemol" msgstr "xmakemol" #: ../gui.py:306 msgid "avogadro" msgstr "avogadro" #: ../gui.py:309 msgid "Graphs ..." msgstr "Gráficos ..." #: ../gui.py:312 msgid "Movie ..." msgstr "Película ..." #: ../gui.py:315 msgid "Expert mode ..." msgstr "Modo experto ..." #: ../gui.py:318 msgid "Constraints ..." msgstr "Restricciones ..." #: ../gui.py:321 msgid "Render scene ..." msgstr "Dibujar escena ... " #: ../gui.py:324 msgid "DFT ..." msgstr "DFT ..." #: ../gui.py:327 msgid "NE_B" msgstr "NE_B" #: ../gui.py:330 msgid "B_ulk Modulus" msgstr "Módulo de b_ulto" #: ../gui.py:333 msgid "_Bulk Crystal" msgstr "Cristal en _bulto" #: ../gui.py:334 msgid "Create a bulk crystal with arbitrary orientation" msgstr "Crear un cristal en bulto con orientación arbitraria" #: ../gui.py:336 msgid "_Surface slab" msgstr "Trozo de _superficie" #: ../gui.py:337 msgid "Create the most common surfaces" msgstr "Crear las superficies más comunes" #: ../gui.py:339 msgid "_Nanoparticle" msgstr "_Nanopartícula" #: ../gui.py:340 msgid "Create a crystalline nanoparticle" msgstr "Crear una nanoparticula cristalina" #: ../gui.py:342 msgid "Nano_tube" msgstr "Nano_tubo" #: ../gui.py:343 msgid "Create a nanotube" msgstr "Crear un nanotubo" #: ../gui.py:346 msgid "Create a graphene sheet or nanoribbon" msgstr "Crear una sábana de grafeno o una nanocinta" #: ../gui.py:348 msgid "Set _Calculator" msgstr "Fijar el _calculador" #: ../gui.py:349 msgid "Set a calculator used in all calculation modules" msgstr "Fijar un calculador utilizado en todos los módulos de cálculo" #: ../gui.py:351 msgid "_Energy and Forces" msgstr "_Energía y Fuerzas" #: ../gui.py:352 msgid "Calculate energy and forces" msgstr "Calcular energía y fuerzas" #: ../gui.py:354 msgid "Energy _Minimization" msgstr "_Minimización de energía" #: ../gui.py:355 msgid "Minimize the energy" msgstr "Minimize la energía" #: ../gui.py:357 msgid "Scale system" msgstr "Escale el sistema" #: ../gui.py:358 msgid "Deform system by scaling it" msgstr "Deforme el sistema escalándolo" #: ../gui.py:360 msgid "_About" msgstr "_Acerca de ag" #: ../gui.py:363 msgid "Webpage ..." msgstr "Página web ..." #: ../gui.py:364 msgid "Debug ..." msgstr "Quitar errores" #: ../gui.py:366 msgid "Show _unit cell" msgstr "Mostrar la celda _unitaria" #: ../gui.py:370 msgid "Show _axes" msgstr "Mostrar los _ejes" #: ../gui.py:374 msgid "Show _bonds" msgstr "Mostrar los _enlaces" #: ../gui.py:378 msgid "Show _velocities" msgstr "Mostrar las _velocidades" #: ../gui.py:382 msgid "Show _forces" msgstr "Mostrar las _fuerzas" #: ../gui.py:386 msgid "_Move atoms" msgstr "_Mover los átomos" #: ../gui.py:390 msgid "_Rotate atoms" msgstr "_Rotar los átomos" #: ../gui.py:394 msgid "Orien_t atoms" msgstr "Orien_tar los átomos" #: ../gui.py:400 msgid "_None" msgstr "_Ninguno" #: ../gui.py:401 msgid "Atom _Index" msgstr "_Índice de Atom" #: ../gui.py:402 msgid "_Magnetic Moments" msgstr "Momentos _Magnético" #: ../gui.py:403 msgid "_Element Symbol" msgstr "Símbolo _Químico" #: ../gui.py:412 #, python-format msgid "building menus failed: %s" msgstr "La construcción de los menús ha fallado: %s" #: ../gui.py:687 ../gui.py:1093 ../gui.py:1153 msgid "Open ..." msgstr "Abrir ..." #: ../gui.py:691 ../gui.py:1096 msgid "<>" msgstr "<>" #: ../gui.py:824 msgid "Add atoms" msgstr "Agregar átomos" #: ../gui.py:827 msgid "Paste" msgstr "Pegar" #: ../gui.py:833 msgid "Insert atom or molecule" msgstr "Insertar átomo o molécula" #: ../gui.py:834 ../gui.py:960 msgid "Tag" msgstr "Etiqueta" #: ../gui.py:835 ../gui.py:961 msgid "Moment" msgstr "Momento magnético" #: ../gui.py:836 msgid "Position" msgstr "Posición" #: ../gui.py:861 msgid "_Load molecule" msgstr "_Cargar molécula" #: ../gui.py:865 ../gui.py:976 msgid "_OK" msgstr "_OK" #: ../gui.py:869 ../gui.py:980 msgid "_Cancel" msgstr "_Cancelar" #: ../gui.py:953 msgid "Modify" msgstr "Modificar" #: ../gui.py:959 msgid "Atom" msgstr "Átomo" #: ../gui.py:1004 msgid "Confirmation" msgstr "Confirmación" #: ../gui.py:1008 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "¿Borrar el átomo seleccionado?" msgstr[1] "¿Borrar los átomos seleccionados?" #: ../gui.py:1015 msgid "Cancel" msgstr "Cancelar" #: ../gui.py:1101 msgid "Automatic" msgstr "Automático" #: ../gui.py:1102 msgid "Dacapo netCDF output file" msgstr "Archivo de salida Dacapo (.netCDF)" #: ../gui.py:1103 msgid "Virtual Nano Lab file" msgstr "Archivo Virtual Nano Lab" #: ../gui.py:1104 msgid "ASE pickle trajectory" msgstr "Trajectoria ASE pickle" #: ../gui.py:1105 msgid "ASE bundle trajectory" msgstr "Trajectoria ASE ligada" #: ../gui.py:1106 msgid "GPAW text output" msgstr "Archivo de salida de texto (GPAW)" #: ../gui.py:1107 msgid "CUBE file" msgstr "Archivo CUBE" #: ../gui.py:1108 msgid "XCrySDen Structure File" msgstr "Archivo de estructura XCrySDen" #: ../gui.py:1109 msgid "Dacapo text output" msgstr "Archivo de salida de texto (Dacapo)" #: ../gui.py:1110 msgid "XYZ-file" msgstr "Archivo XYZ" #: ../gui.py:1111 msgid "VASP POSCAR/CONTCAR file" msgstr "Archivo POSCAR/CONTCAR (VASP)" #: ../gui.py:1112 msgid "VASP OUTCAR file" msgstr "Archivo OUTCAR (VASP)" #: ../gui.py:1113 msgid "Protein Data Bank" msgstr "Banco de datos de proteínas" #: ../gui.py:1114 msgid "CIF-file" msgstr "Archivo CIF" #: ../gui.py:1115 msgid "FHI-aims geometry file" msgstr "Archivo de geometría (FHI-aims)" #: ../gui.py:1116 msgid "FHI-aims output file" msgstr "Archivo de salida (FHI-aims)" #: ../gui.py:1117 msgid "TURBOMOLE coord file" msgstr "Archivo de coordenadas (TURBOMOLE)" #: ../gui.py:1118 msgid "exciting input" msgstr "Archivo de entrada (exciting)" #: ../gui.py:1119 msgid "WIEN2k structure file" msgstr "Archivo de estructura (WIEN2k)" #: ../gui.py:1120 msgid "DftbPlus input file" msgstr "Archivo de entrada (DFTBPlus)" #: ../gui.py:1121 msgid "ETSF format" msgstr "Formato ETSF" #: ../gui.py:1122 msgid "CASTEP geom file" msgstr "Archivo de geometría (CASTEP)" #: ../gui.py:1123 msgid "CASTEP output file" msgstr "Archivo de salida (CASTEP)" #: ../gui.py:1124 msgid "CASTEP trajectory file" msgstr "Archivo de trajectoria (CASTEP)" #: ../gui.py:1125 msgid "DFTBPlus GEN format" msgstr "Formato GEN (DFTBPlus)" #: ../gui.py:1131 msgid "File type:" msgstr "Tipo de archivo:" #: ../gui.py:1254 msgid "Not implemented!" msgstr "No implementado!" #: ../gui.py:1255 msgid "do you really need it?" msgstr "¿realmente necesita esto?" #: ../minimize.py:21 msgid "Algorithm: " msgstr "Algoritmo: " #: ../minimize.py:26 ../progress.py:68 msgid "Convergence criterion: Fmax = " msgstr "Criterio de convergencia: Fmáx = " #: ../minimize.py:31 ../progress.py:71 msgid "Max. number of steps: " msgstr "Número máximo de pasos: " #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "Paso de pseudotiempo: " #: ../minimize.py:55 msgid "Energy minimization" msgstr "Minimización de energía" #: ../minimize.py:59 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:91 ../scaling.py:301 msgid "Running ..." msgstr "Calculando ..." #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "Minimización CANCELADO después de %i iteraciones." #: ../minimize.py:114 ../scaling.py:352 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:121 #, python-format msgid "Minimization completed in %i steps." msgstr "Minimización hecha en %i pasos." #. self.connect('delete_event', self.exit2) #: ../movie.py:13 msgid "Movie" msgstr "Película" #: ../movie.py:15 msgid "Image number:" msgstr "Imagen número:" #: ../movie.py:37 msgid "Play" msgstr "Reproducir" #: ../movie.py:39 msgid "Stop" msgstr "Detener" #. TRANSLATORS: This function plays an animation forwards and backwards #. alternatingly, e.g. for displaying vibrational movement #: ../movie.py:43 msgid "Rock" msgstr "Repetir cuadro" #: ../movie.py:59 msgid " Frame rate: " msgstr "Velocidad del cuadro: " #: ../movie.py:60 msgid " Skip frames: " msgstr "Saltar los cuadros: " #: ../nanoparticle.py:20 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:27 #, python-brace-format 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:84 msgid "Face centered cubic (fcc)" msgstr "Cúbico centrado en las caras (fcc)" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "Cúbico centrado en el cuerpo (bcc)" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "Cúbico simple (sc)" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "Empacamiento hexagonal cerrado (hcp)" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "Grafito" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "Nanopartícula" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "Elemento: " #: ../nanoparticle.py:131 msgid "Get structure" msgstr "Obtener la estructura" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "Constante de red: a =" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "Método: " #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "Especificación de capas" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "Construcción de Wulff" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "Objeto marcador de posición ficticia" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "Agregar nueva dirección:" #: ../nanoparticle.py:212 msgid "Add" msgstr "Agregar" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "Fijar en todas las direcciones los valores por defecto" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "Tamaño de la partícula: " #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:197 msgid "Number of atoms: " msgstr "Número de átomos: " #: ../nanoparticle.py:234 msgid "Volume: " msgstr "Volumen: " #: ../nanoparticle.py:239 msgid "ų" msgstr "ų" #: ../nanoparticle.py:244 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:247 msgid "above " msgstr "sobre " #: ../nanoparticle.py:248 msgid "below " msgstr "abajo " #: ../nanoparticle.py:249 msgid "closest " msgstr "más cercano " #: ../nanoparticle.py:252 msgid "Smaller" msgstr "Mas pequeño" #: ../nanoparticle.py:253 msgid "Larger" msgstr "Más largo" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr " Diámetro aproximado: " #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "Información sobre el cluster creado:" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "Creando una nanopartícula." #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "Aplicar automáticamente" #: ../nanoparticle.py:333 msgid "Up" msgstr "Arriba" #: ../nanoparticle.py:338 msgid "Down" msgstr "Abajo" #: ../nanoparticle.py:343 msgid "Delete" msgstr "Borrar" #: ../nanoparticle.py:384 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:390 msgid "Number of layers:" msgstr "Número de capas:" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "Al menos un índice debe ser distinto de cero" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "Índices hexagonales inválidos" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "Elemento inválido." #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "Estructura no soportada o desconocida" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "%.1f Å" #: ../nanotube.py:15 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 "" "Configure un nanotubo de carbono specificando el vector de roll-up.\n" "Note que m <= n.\n" "\n" "Nanotubos de otros elementos se pueden construir especificando el elemento y " "largo del enlace." #: ../nanotube.py:29 #, python-format msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: " "%(volume).3f Å3" msgstr "" " %(natoms)i átomos: %(symbols)s, diámetro: %(diameter).3f Å, volumen: " "%(volume).3f Å3" #: ../nanotube.py:35 msgid "Nanotube" msgstr "Nanotubo" #. Choose the structure. #: ../nanotube.py:59 msgid "Select roll-up vector (n,m) and tube length:" msgstr "Seleccione vector de roll-up (n,m) y largo del tubo:" #: ../progress.py:26 msgid "Progress" msgstr "Progreso" #: ../progress.py:33 msgid "Scaling deformation:" msgstr "Escala de deformación:" #: ../progress.py:39 #, 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:54 msgid "Energy minimization:" msgstr "Minimización de energía:" #: ../progress.py:61 msgid "Step number: " msgstr "Paso número: " #: ../progress.py:63 msgid "Fmax: " msgstr "Fmáx: " #: ../progress.py:103 msgid "unknown" msgstr "desconocido" #: ../progress.py:180 msgid "Status: " msgstr "Estado: " #: ../progress.py:182 msgid "Iteration: " msgstr "Iteración: " #: ../progress.py:185 msgid "log10(change):" msgstr "log10 (cambio):" #: ../progress.py:188 msgid "Wave functions: " msgstr "Funciones de onda: " #: ../progress.py:190 msgid "Density: " msgstr "Densidad: " #: ../progress.py:192 msgid "Energy: " msgstr "Energía: " #: ../progress.py:195 msgid "GPAW version: " msgstr "Versión de GPAW: " #: ../progress.py:198 msgid "N/A" msgstr "No disponible" #: ../progress.py:199 msgid "Memory estimate: " msgstr "Memoria estimada: " #: ../progress.py:234 msgid "No info" msgstr "No hay información" #: ../progress.py:244 msgid "Initializing" msgstr "Iniciando" #: ../progress.py:245 msgid "Positions:" msgstr "Posiciones:" #: ../progress.py:249 msgid "Starting calculation" msgstr "Comenzando cálculo" #: ../progress.py:286 msgid "unchanged" msgstr "sin cambios" #: ../progress.py:296 msgid "Self-consistency loop" msgstr "Bucle de auto consistencia" #: ../progress.py:301 msgid "Calculating forces" msgstr "Calculando fuerzas" #: ../progress.py:302 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" "\n" "%s\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" "\n" "%s\n" "%s\n" #: ../quickinfo.py:31 msgid "Quick Info" msgstr "Información rápida" #: ../quickinfo.py:35 msgid "No atoms loaded." msgstr "No hay átomos seleccionados." #: ../quickinfo.py:56 msgid "no" msgstr "no" #: ../quickinfo.py:56 msgid "yes" msgstr "sí" #. TRANSLATORS: This has the form Periodic: no, no, yes #: ../quickinfo.py:60 #, python-format msgid "Periodic: %s, %s, %s" msgstr "Periódico: %s, %s, %s" #: ../render.py:15 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\n" " selección alternativo, el cual está basado en expresiones\n" " booleanas. Estas se pueden fijar en la caja de entrada, utilizando\n" " las variables x, y, z ó Z. Por ejemplo, la expresión\n" " Z == 11 and x > 10 and y > 10 marcará todos los átomos de sodio\n" " con x o coordenadas mayores que 10. En cualquier caso, el botón\n" " 'Crear nueva estructura desde la selección' activará los cambios a\n" " los atributos de la selección actual.\n" " " #: ../render.py:33 msgid "Render current view in povray ... " msgstr "Dibujar vista actual en povray ... " #: ../render.py:37 #, python-format msgid "Rendering %d atoms." msgstr "Dibujando %d átomos." #: ../render.py:42 msgid "Render constraints" msgstr "Restricciones del dibujo" #: ../render.py:45 msgid "Width" msgstr "Ancho" #: ../render.py:46 msgid " Height" msgstr " Altura" #: ../render.py:53 msgid "Render unit cell" msgstr "Dibujar celda unitaria" #: ../render.py:62 msgid "Line width" msgstr "Ancho de la línea" #: ../render.py:64 msgid "Angstrom " msgstr "Angstrom " #: ../render.py:74 msgid "Set" msgstr "Fijar" #: ../render.py:76 msgid "Output basename: " msgstr "Nombre base para el archivo de salida: " #: ../render.py:78 msgid " Filename: " msgstr " Nombre de archivo: " #: ../render.py:89 msgid " Default texture for atoms: " msgstr " Textura por defecto para los átomos: " #: ../render.py:90 msgid " transparency: " msgstr " transparencia: " #: ../render.py:91 msgid "Define atom selection for new texture:" msgstr "Definir al selección del átomo para la nueva textura:" #: ../render.py:93 msgid "Select" msgstr "Seleccionar" #: ../render.py:97 msgid "Create new texture from selection" msgstr "Crear nueva textura desde selección" #: ../render.py:99 msgid "Help on textures" msgstr "Ayuda en texturas" #: ../render.py:112 msgid "Camera type: " msgstr "Tipo de cámara: " #: ../render.py:113 msgid " Camera distance" msgstr " Distancia de la cámara" #: ../render.py:114 msgid "Render current frame" msgstr "Dibujar el cuadro actual" #: ../render.py:118 #, python-format msgid "Render all %d frames" msgstr "Dibujar todos los %d cuadros" #: ../render.py:123 msgid "Transparent background" msgstr "Fondo transparente" #: ../render.py:126 msgid "Run povray " msgstr "Ejecutar povray " #: ../render.py:129 msgid "Keep povray files " msgstr "Mantener los archivos povray " #: ../render.py:132 msgid "Show output window" msgstr "Mostrar ventana de salida" #: ../render.py:213 msgid " transparency: " msgstr " transparencia: " #: ../render.py:219 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:12 msgid "Repeat" msgstr "Repetir" #: ../repeat.py:19 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:150 msgid "2nd" msgstr "Segundo" #: ../scaling.py:151 msgid "3rd" msgstr "Tercero" #: ../scaling.py:155 msgid "Order of fit: " msgstr "Grado del ajuste: " #. Update display to reflect cancellation of simulation. #: ../scaling.py:348 msgid "Calculation CANCELLED." msgstr "Cálculo CANCELADO." #. Update display to reflect succesful end of simulation. #: ../scaling.py:359 msgid "Calculation completed." msgstr "Cálculo terminado." #: ../scaling.py:382 msgid "No trustworthy minimum: Old configuration kept." msgstr "El mínimo no es confiable: se mantiene la configuración anterior." #: ../scaling.py:422 #, 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:426 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:442 msgid "No minimum found!" msgstr "¡No se encontró el mínimo!" #: ../scaling.py:456 msgid "" "\n" "WARNING: Minimum is outside interval\n" msgstr "" "\n" "ADVERTENCIA: El mínimo está fuera del intervalo\n" #: ../scaling.py:457 msgid "It is UNRELIABLE!\n" msgstr "¡Esto NO es confiable!\n" #: ../settings.py:15 msgid "Constraints:" msgstr "Restricciones:" #: ../settings.py:18 msgid "release" msgstr "Soltar" #: ../settings.py:22 msgid "Constrain immobile atoms" msgstr "Restringir los átomos inmóbiles" #: ../settings.py:24 msgid "Clear all constraints" msgstr "Eliminar todas las restricciones" #: ../settings.py:30 msgid "Visibility:" msgstr "Visibilidad:" #: ../settings.py:31 msgid "Hide" msgstr "Esconder" #: ../settings.py:33 msgid "show" msgstr "Mostrar" #: ../settings.py:37 msgid "View all atoms" msgstr "Ver todos los átomos" #: ../settings.py:43 msgid "Miscellaneous:" msgstr "Misceláneos:" #: ../settings.py:46 msgid "Scale atomic radii:" msgstr "Radio de escala atómica:" #. A close button #: ../settings.py:51 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:36 ../status.py:38 msgid "Tip for status box ..." msgstr "Consejo para la ventana de estado ..." #. TRANSLATORS: mom refers to magnetic moment #: ../status.py:62 #, python-format msgid " tag=%(tag)s mom=%(mom)1.2f" msgstr " etiqueta=%(tag)s momento magnético=%(mom)1.2f" #: ../status.py:103 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:58 ../widgets.py:87 msgid "Help" msgstr "Ayuda" #: ../widgets.py:104 msgid "Clear constraint" msgstr "Borrar restricción" #~ 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." #~ msgid "Max force: %.2f (this frame), %.2f (all frames)" #~ msgstr "Fuerza máx: %.2f (este cuadro), %.2f (todos los cuadros)" #~ msgid "Max force: %.2f." #~ msgstr "Fuerza máx: %.2f." #~ msgid "Max velocity: %.2f (this frame), %.2f (all frames)" #~ msgstr "Velocidad máxima: %.2f (este cuadro), %.2f (todos los cuadros)" #~ msgid "Max velocity: %.2f." #~ msgstr "Velocidad máxima: %.2f." #~ msgid "Min, max charge: %.2f, %.2f (this frame)," #~ msgstr "Carga mín, máx: %.2f, %.2f (este cuadro)," #~ msgid "Min, max charge: %.2f, %.2f." #~ msgstr "Carga mín, máx: %.2f, %.2f." #~ msgid "Save ..." #~ msgstr "Guardar ..." #~ msgid "XYZ file" #~ msgstr "Archivo XYZ" #~ msgid "ASE trajectory" #~ msgstr "Trajectoria ASE" #~ msgid "PDB file" #~ msgstr "Archivo PDB" #~ msgid "Gaussian cube file" #~ msgstr "Archivo cube (Gaussian)" #~ msgid "Python script" #~ msgstr "Script de Python" #~ msgid "VNL file" #~ msgstr "Archivo VNL" #~ msgid "Portable Network Graphics" #~ msgstr "Archivo PNG" #~ msgid "Persistence of Vision" #~ msgstr "Archivo POV" #~ msgid "Encapsulated PostScript" #~ msgstr "Archivo EPS" #~ msgid "FHI-aims geometry input" #~ msgstr "Geometría de entrada (FHI-aims)" #~ msgid "VASP geometry input" #~ msgstr "Geometría de entrada (VASP)" #~ msgid "cif file" #~ msgstr "Archivo cif" #~ msgid "Save current image only (#%d)" #~ msgstr "Guardar solamente la imagen actual (#%d)" #~ msgid "Slice: " #~ msgstr "Trozo: " #~ msgid "Help for slice ..." #~ msgstr "Ayuda para trozar ..." #~ msgid "ase-gui INTERNAL ERROR: strange response in Save," #~ msgstr "ERROR INTERNO DE ase-gui: respuesta extraña en guardar," #~ msgid "Unknown output format!" #~ msgstr "¡Formato de salida desconocido!" #~ msgid "Use one of: %s" #~ msgstr "Use uno de: %s" #~ 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.9.1.4567/ase/gui/po/da/0000775000175000017500000000000012553427753017040 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/da/LC_MESSAGES/0000775000175000017500000000000012553427753020625 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/da/LC_MESSAGES/ag.po0000664000175000017500000024661012553425550021556 0ustar jensjjensj00000000000000# Danish translations for ASE package # Danske oversættelser for pakken ASE. # Copyright (C) 2011-2015 CAMD # This file is distributed under the same license as the ASE package. # # Ask Hjorth Larsen , 2011-2015. # msgid "" msgstr "" "Project-Id-Version: ase-3.5.2\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2015-07-15 17:25+0200\n" "PO-Revision-Date: 2015-07-15 17:26+0200\n" "Last-Translator: Ask Hjorth Larsen \n" "Language-Team: Danish \n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../ag.py:144 msgid "To get a full traceback, use: ase-gui --verbose" msgstr "Kør ase-gui --verbose for at se det fulde traceback" #. 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, \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" "brugen 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 EAM/ADP potential is a many-body potential\n" "implementation of the Embedded Atom Method and\n" "equipotential plus the Angular Dependent Potential,\n" "which is an extension of the EAM to include\n" "directional bonds. EAM is suited for FCC metallic\n" "bonding while the ADP is suited for metallic bonds\n" "with some degree of directionality.\n" "\n" "For EAM see M.S. Daw and M.I. Baskes,\n" "Phys. Rev. Letters 50 (1983) 1285.\n" "\n" "For ADP see Y. Mishin, M.J. Mehl, and\n" "D.A. Papaconstantopoulos, Acta Materialia 53 2005\n" "4029--4041.\n" "\n" "Data for the potential is contained in a file in either LAMMPS Alloy\n" "or ADP format which need to be loaded before use. The Interatomic\n" "Potentials Repository Project at http://www.ctcms.nist.gov/potentials/\n" "contains many suitable potential files.\n" "\n" "For large simulations the LAMMPS calculator is more\n" "suitable; this implementation is mainly to make EAM\n" "available when LAMMPS is not installed or to develop\n" "new EAM/ADP poentials by matching results using ab\n" "initio.\n" msgstr "" "EAM/ADP potentialet er ee mangelegme-potential\n" "implementering af Embedded Atom Method og\n" "equipotential plus Angular Dependent Potential,\n" "hvilket er en udvidelse til EAM de inkluderer\n" "retningsafhængige bindinger. EAM er velegnet til FCC metalliske\n" "bindinger og ADP er velegnet til metalliske bindinger\n" "med nogen grad af retningsafhængighed.\n" "\n" "For EAM se M.S. Daw and M.I. Baskes,\n" "Phys. Rev. Letters 50 (1983) 1285.\n" "\n" "For ADP se Y. Mishin, M.J. Mehl, and\n" "D.A. Papaconstantopoulos, Acta Materialia 53 2005\n" "4029--4041.\n" "\n" "Data for potentialet er indeholdt i en fil i enten LAMMPS Alloy\n" "eller ADP formatet som skal indlæses før brug. Interatomic\n" "Potentials Repository Project (http://www.ctcms.nist.gov/potentials/)\n" "indeholder mange passende potential filer.\n" "\n" "For store simulationer er LAMMPS beregneren mere\n" "passende; denne implementation er hovedsageligis inkluderet for at\n" "gøre EAM tilgængelig når LAMMPS ikke er installeret eller for at udvikle\n" "nye EAM/ADP poentialer ved at matche ab initio resultater.\n" #: ../calculator.py:113 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:135 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:142 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:152 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:159 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:168 msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)" msgstr "Standard (Al, Ni, Cu, Pd, Ag, Pt, Au)" #: ../calculator.py:169 msgid "Alternative Cu, Ag and Au" msgstr "Alternativ Cu, Ag og Au" #: ../calculator.py:170 msgid "Ruthenium" msgstr "Ruthenium" #: ../calculator.py:171 msgid "CuMg and CuZr metallic glass" msgstr "Metallisk glas med CuMg og CuZr" #: ../calculator.py:189 msgid "Select calculator" msgstr "Vælg beregner" #: ../calculator.py:195 msgid "Calculator:" msgstr "Beregner:" #. No calculator (the default) #: ../calculator.py:198 msgid "None" msgstr "Ingen" #: ../calculator.py:203 msgid "Lennard-Jones (ASAP)" msgstr "Lennard-Jones (ASAP)" #: ../calculator.py:204 ../calculator.py:231 ../calculator.py:246 #: ../calculator.py:255 ../calculator.py:264 msgid "Setup" msgstr "Opsætning" #: ../calculator.py:211 msgid "EMT - Effective Medium Theory (ASAP)" msgstr "EMT - Effective Medium Theory (ASAP)" #: ../calculator.py:223 msgid "EMT - Effective Medium Theory (ASE)" msgstr "EMT - Effective Medium Theory (ASE)" #: ../calculator.py:230 msgid "EAM - Embedded Atom Method/Angular Dependent Potential (ASE)" msgstr "EAM - Embedded Atom Method/Angular Dependent Potential (ASE)" #: ../calculator.py:238 msgid "Brenner Potential (ASAP)" msgstr "Brenner-potentialet (ASAP)" #: ../calculator.py:244 msgid "Density Functional Theory (GPAW)" msgstr "Tæthedsfunktionalteori (GPAW)" #: ../calculator.py:253 msgid "Density Functional Theory (FHI-aims)" msgstr "Tæthedsfunktionalteori (FHI-aims)" #: ../calculator.py:262 msgid "Density Functional Theory (VASP)" msgstr "Tæthedsfunktionalteori (VASP)" #: ../calculator.py:275 msgid "Check that the calculator is reasonable." msgstr "Kontrollér at beregneren er rimelig." #: ../calculator.py:345 ../simulation.py:114 msgid "No atoms present" msgstr "Ingen atomer til stede" #: ../calculator.py:439 ../calculator.py:474 ../calculator.py:521 msgid "ASAP is not installed. (Failed to import asap3)" msgstr "ASAP er ikke installeret. (Kunne ikke importere asap3)" #: ../calculator.py:442 msgid "You must set up the Lennard-Jones parameters" msgstr "Du skal indstille Lennard-Jones-parametrene" #: ../calculator.py:447 msgid "Could not create useful Lennard-Jones calculator." msgstr "Kunne ikke oprette en nyttig Lennard-Jones-beregner." #: ../calculator.py:482 msgid "Could not attach EMT calculator to the atoms." msgstr "Kunne ikke knytte EMT-beregner til atomerne." #: ../calculator.py:503 msgid "You must set up the EAM parameters" msgstr "Du skal angive EAM-parametrene" #: ../calculator.py:539 ../calculator.py:551 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "GPAW er ikke installeret. (Kunne ikke importere gpaw)" #: ../calculator.py:542 msgid "You must set up the GPAW parameters" msgstr "Du skal angive GPAW-parametrene" #: ../calculator.py:584 msgid "You must set up the FHI-aims parameters" msgstr "Du skal angive FHI-aims-parametrene" #: ../calculator.py:599 msgid "You must set up the VASP parameters" msgstr "Du skal angive VASP-parametrene" #: ../calculator.py:624 #, 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:632 msgid "Info" msgstr "Info" #: ../calculator.py:648 msgid "Lennard-Jones parameters" msgstr "Lennard-Jones-parametre" #: ../calculator.py:660 msgid "Specify the Lennard-Jones parameters here" msgstr "Angiv Lennard-Jones-parametrene her" #: ../calculator.py:663 msgid "Epsilon (eV):" msgstr "Epsilon (eV):" #: ../calculator.py:667 msgid "Sigma (Å):" msgstr "Sigma (Å):" #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:671 msgid "Shift to make smooth at cutoff" msgstr "Skift for at blødgøre ved afskæring" #: ../calculator.py:750 msgid "EAM parameters" msgstr "EAM-parametre" #: ../calculator.py:764 msgid "Import Potential" msgstr "Importér potential" #: ../calculator.py:787 msgid "You need to import the potential file" msgstr "Du skal importere en potential fil" #: ../calculator.py:795 msgid "Import .alloy or .adp potential file ... " msgstr "Importér .alloy eller .adp potential-fil ... " #: ../calculator.py:818 msgid "GPAW parameters" msgstr "GPAW-parametre" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:833 ../calculator.py:1123 ../calculator.py:1612 #, python-format msgid "%i atoms.\n" msgstr "%i atomer.\n" #: ../calculator.py:835 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "Ortogonal enhedscelle: %.2f x %.2f x %.2f Å." #: ../calculator.py:837 msgid "Non-orthogonal unit cell:\n" msgstr "Ikke-ortogonal enhedscelle:\n" #: ../calculator.py:847 ../calculator.py:1139 ../calculator.py:1627 msgid "Exchange-correlation functional: " msgstr "Udvekslings- og korrelationsfunktional: " #. Grid spacing #: ../calculator.py:851 msgid "Grid spacing" msgstr "Gitterafstand" #: ../calculator.py:855 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "Å" #: ../calculator.py:856 msgid "Grid points" msgstr "Gitterpunkter" #: ../calculator.py:865 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "heff = (%.3f, %.3f, %.3f) Å" #: ../calculator.py:891 ../calculator.py:1154 ../calculator.py:1663 msgid "k-points k = (" msgstr "k-punkter k = (" #: ../calculator.py:895 ../calculator.py:1158 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "k-punkter x størrelse: (%.1f, %.1f, %.1f) Å" #. Spin polarized #: ../calculator.py:900 ../calculator.py:1625 msgid "Spin polarized" msgstr "Spinpolariseret" #: ../calculator.py:906 msgid "FD - Finite Difference (grid) mode" msgstr "FD - Finite Difference-tilstand (gitter)" #: ../calculator.py:907 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "LCAO - linearkombination af atomare orbitaler" #: ../calculator.py:910 msgid "Mode: " msgstr "Tilstand: " #: ../calculator.py:912 msgid "sz - Single Zeta" msgstr "sz - Enkelt-zeta" #: ../calculator.py:913 msgid "szp - Single Zeta polarized" msgstr "szp - Enkelt-zeta polariseret" #: ../calculator.py:914 msgid "dzp - Double Zeta polarized" msgstr "dzp - dobbelt-zeta polariseret" #. dzp #: ../calculator.py:916 msgid "Basis functions: " msgstr "Basisfunktioner: " #. Mixer #: ../calculator.py:922 msgid "Non-standard mixer parameters" msgstr "Særlige mikserparametre" #: ../calculator.py:1119 msgid "FHI-aims parameters" msgstr "FHI-aims-parametre" #: ../calculator.py:1126 msgid "Periodic geometry, unit cell is:\n" msgstr "Periodisk geometri; enhedscellen er:\n" #: ../calculator.py:1131 msgid "Non-periodic geometry.\n" msgstr "Ikke-periodisk geometri.\n" # XXX ikke Hirschfeld? #: ../calculator.py:1138 msgid "Hirshfeld-based dispersion correction" msgstr "Hirshfeld-baseret dispersionskorrektion" #. Spin polarized, charge, relativity #: ../calculator.py:1164 msgid "Spin / initial moment " msgstr "Spin / startmoment " #: ../calculator.py:1182 msgid " Charge" msgstr " Ladning" #: ../calculator.py:1184 msgid " Relativity" msgstr " Relativitet" #: ../calculator.py:1186 msgid " Threshold" msgstr " Tærskel" #. self-consistency criteria #: ../calculator.py:1191 msgid "Self-consistency convergence:" msgstr "Selfkonsistenskonvergens:" #: ../calculator.py:1204 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:1215 msgid "Energy: " msgstr "Energi: " #: ../calculator.py:1217 msgid " eV Sum of eigenvalues: " msgstr " eV Sum af egenværdier: " #: ../calculator.py:1219 ../calculator.py:1698 msgid " eV" msgstr " eV" #: ../calculator.py:1220 msgid "Electron density: " msgstr "Elektrontæthed: " #: ../calculator.py:1222 msgid " Force convergence: " msgstr " Kraftkonvergens: " #: ../calculator.py:1224 msgid " eV/Ang " msgstr " eV/Å " #: ../calculator.py:1237 ../calculator.py:1709 msgid "Additional keywords: " msgstr "Yderligere nøgleord: " #. run command and species defaults: #: ../calculator.py:1251 msgid "FHI-aims execution command: " msgstr "Kørselskommando til FHI-aims: " # ?? #: ../calculator.py:1253 ../calculator.py:1726 msgid "Directory for species defaults: " msgstr "Mappe for grundstofstandarder: " #: ../calculator.py:1265 ../calculator.py:1734 msgid "Set Defaults" msgstr "Brug standardværdier" #: ../calculator.py:1267 msgid "Import control.in" msgstr "Importér control.in" #: ../calculator.py:1269 msgid "Export control.in" msgstr "Eksportér control.in" #: ../calculator.py:1456 msgid "Export parameters ... " msgstr "Eksportér parametre ... " #: ../calculator.py:1476 msgid "Import control.in file ... " msgstr "Importér control.in-fil ... " #: ../calculator.py:1532 ../calculator.py:2041 #, 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:1535 #, 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:1608 msgid "VASP parameters" msgstr "VASP-parametre" #: ../calculator.py:1614 msgid "Periodic geometry, unit cell is: \n" msgstr "Periodisk geometri; enhedscelle er: \n" #: ../calculator.py:1666 msgid ") Cutoff: " msgstr ") Afskæring: " #: ../calculator.py:1667 msgid " Precision: " msgstr " Præcision: " #: ../calculator.py:1669 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "k-punkter x størrelse: (%.1f, %.1f, %.1f) Å " #: ../calculator.py:1685 msgid "Smearing: " msgstr "Udjævning: " #: ../calculator.py:1687 msgid " order: " msgstr " orden: " #: ../calculator.py:1689 msgid " width: " msgstr " bredde: " #: ../calculator.py:1696 msgid "Self-consistency convergence: " msgstr "Selfkonsistenskonvergens: " #. run command and location of POTCAR files: #: ../calculator.py:1722 msgid "VASP execution command: " msgstr "Kørselskommando til VASP: " #: ../calculator.py:1736 msgid "Import VASP files" msgstr "Importér VASP-filer" #: ../calculator.py:1738 msgid "Export VASP files" msgstr "Eksportér VASP-filer" #: ../calculator.py:1945 msgid "WARNING: cutoff energy is lower than recommended minimum!" msgstr "" "ADVARSEL: afskæringsenergi er lavere end det anbefalede minimum!" #: ../calculator.py:1997 msgid "Import VASP input files: choose directory ... " msgstr "Importér VASP-inputfiler: vælg mappe ... " #: ../calculator.py:2011 msgid "Export VASP input files: choose directory ... " msgstr "Eksportér VASP-inputfiler: vælg mappe ... " #: ../calculator.py:2044 #, 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:27 msgid "Colors" msgstr "Farver" #. Upper left: Choose how the atoms are colored. #: ../colors.py:44 msgid "Choose how the atoms are colored:" msgstr "Vælg hvordan atomerne farves:" #: ../colors.py:46 msgid "By atomic number, default \"jmol\" colors" msgstr "Efter atomnummer; \"jmol\"-farver som standard" #: ../colors.py:48 msgid "By atomic number, user specified" msgstr "Efter atomnummer, brugerdefineret" #: ../colors.py:49 msgid "By tag" msgstr "Efter mærke" #: ../colors.py:50 msgid "By force" msgstr "Efter kraft" #: ../colors.py:51 msgid "By velocity" msgstr "Efter hastighed" #: ../colors.py:52 msgid "By charge" msgstr "Efter ladning" #: ../colors.py:54 msgid "By magnetic moment" msgstr "Efter magnetisk moment" #: ../colors.py:56 msgid "By coordination" msgstr "Efter koordination" #: ../colors.py:57 msgid "Manually specified" msgstr "Manuelt angivet" #: ../colors.py:58 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:74 msgid "This should not be displayed in forces!" msgstr "Dette bør ikke blive vist ved kræfter!" #: ../colors.py:79 ../colors.py:93 ../colors.py:108 ../colors.py:124 #: ../rotate.py:25 msgid "Update" msgstr "Opdatér" #: ../colors.py:81 ../colors.py:95 ../colors.py:110 ../colors.py:126 msgid "Min: " msgstr "Min: " #: ../colors.py:83 ../colors.py:97 ../colors.py:112 ../colors.py:128 msgid " Max: " msgstr " Maks: " #: ../colors.py:85 ../colors.py:99 ../colors.py:114 ../colors.py:130 msgid " Steps: " msgstr " Trin: " #. Now fill in the box for additional information in case #. the charge is used. #: ../colors.py:106 ../colors.py:122 msgid "This should not be displayed!" msgstr "Dette bør ikke blive vist!" #: ../colors.py:137 msgid "Create a color scale:" msgstr "Opret en farveskala:" #: ../colors.py:140 msgid "Black - white" msgstr "Sort - hvid" #: ../colors.py:141 msgid "Black - red - yellow - white" msgstr "Sort - rød - gul - hvid" #: ../colors.py:142 msgid "Black - green - white" msgstr "Sort - grøn - hvid" #: ../colors.py:143 msgid "Black - blue - cyan" msgstr "Sort - blå - cyan" #: ../colors.py:144 msgid "Blue - white - red" msgstr "Blå - hvid - rød" #: ../colors.py:145 msgid "Hue" msgstr "Farvetone" #: ../colors.py:146 msgid "Named colors" msgstr "Navngivne farver" #: ../colors.py:152 msgid "Create" msgstr "Opret" #: ../colors.py:517 msgid "ERROR" msgstr "FEJL" #: ../colors.py:546 msgid "ERR" msgstr "FEJL" #: ../colors.py:638 msgid "Incorrect color specification" msgstr "Forkert farveangivelse" #: ../constraints.py:12 ../widgets.py:96 msgid "Constraints" msgstr "Begrænsninger" #: ../constraints.py:14 ../constraints.py:17 ../settings.py:16 #: ../widgets.py:98 ../widgets.py:101 msgid "Constrain" msgstr "Begræns" #: ../constraints.py:15 ../settings.py:19 ../settings.py:34 ../widgets.py:99 msgid " selected atoms" msgstr " markerede atomer" #: ../constraints.py:18 ../widgets.py:102 msgid " immobile atoms:" msgstr " immobile atomer:" #: ../constraints.py:20 msgid "Unconstrain" msgstr "Fjern begrænsninger" #: ../constraints.py:21 msgid " selected atoms:" msgstr " markerede atomer:" #: ../constraints.py:23 msgid "Clear constraints" msgstr "Ryd begrænsninger" #: ../constraints.py:25 ../dft.py:28 ../settings.py:52 ../widgets.py:65 #: ../widgets.py:106 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 ../graphene.py:27 #, 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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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:12 msgid "Debug" msgstr "Fejlsøgning" #: ../dft.py:12 msgid "DFT" msgstr "DFT" #: ../dft.py:18 msgid "XC-functional: " msgstr "XC-funktional: " #: ../dft.py:22 ../repeat.py:14 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:22 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: ase-gui window python object\n" " img:\tadvanced: ase-gui 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:66 msgid "Expert user mode" msgstr "Eksperttilstand" #: ../execute.py:79 msgid "Welcome to the ASE Expert user mode" msgstr "Velkommen til ASE's eksperttilstand" #: ../execute.py:86 msgid "Only selected atoms (sa) " msgstr "Kun markerede atomer (sa) " #: ../execute.py:88 msgid "Only current frame (cf) " msgstr "Kun nuværende billede (cf) " #: ../execute.py:98 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:197 #, python-format msgid "*** WARNING: file does not exist - %s" msgstr "*** ADVARSEL: filen findes ikke - %s" #: ../execute.py:202 msgid "*** WARNING: No atoms selected to work with" msgstr "*** ADVARSEL: Ingen atomer markeret til at arbejde på" #: ../execute.py:276 msgid "*** Only working on selected atoms" msgstr "*** Arbejder kun på markerede atomer" #: ../execute.py:278 msgid "*** Working on all atoms" msgstr "*** Arbejder på alle atomer" #: ../execute.py:282 msgid "*** Only working on current image" msgstr "*** Arbejder kun på nuværende billede" #: ../execute.py:284 msgid "*** Working on all images" msgstr "*** Arbejder på alle billeder" #: ../execute.py:300 msgid "Save Terminal text ..." msgstr "Gem terminaltekst ..." #: ../graphene.py:16 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:33 ../gui.py:345 msgid "Graphene" msgstr "Grafén" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "Struktur: " #: ../graphene.py:42 msgid "Infinite sheet" msgstr "Uendeligt lag" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "Umættet bånd" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "Mættet bånd" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "Orientering: " #: ../graphene.py:53 msgid "zigzag" msgstr "zigzag" #: ../graphene.py:53 msgid "armchair" msgstr "lænestol" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 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:90 msgid "Width: " msgstr "Bredde: " #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr " Længde: " #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "Vakuum: " #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr " Intet grundstof angivet!" #: ../graphene.py:194 msgid "Please specify a consistent set of atoms. " msgstr "Angiv venligst en konsistent samling atomer. " #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../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:7 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" "Hjælp til plot ...\n" "\n" "Symboler:\n" "e:\t\t\t\ttotal energi\n" "epot:\t\t\tpotentiel energi\n" "ekin:\t\t\tkinetisk energi\n" "fmax:\t\t\tmaximum kræft\n" "fave:\t\t\tmiddel kræft\n" "R[n,0-2]:\t\t\tposition af atom nummer n\n" "d(n1,n1):\t\t\tafstand mellem to atomer " "n1 og n2\n" "i:\t\t\t\tnuværende billede nummer\n" "E[i]:\t\t\t\tenergi af billede nummer i\n" "F[n,0-2]:\t\t\tkræft på atom nummer n\n" "V[n,0-2]:\t\t\thastighed af atom nummer n\n" "M[n]:\t\t\tmagnetiskt moment af atom nummer n\n" "A[0-2,0-2]:\t\tenhedscelle vektorer\n" "s:\t\t\t\tvejlængde\n" "a(n1,n2,n3):\t\tvinkel mellem atomerne n1, " "n2 and n3, centeret på n2\n" "dih(n1,n2,n3,n4):\tdihedral vinkel mellem n1, " "n2, n3 og n4\n" "T:\t\t\t\ttemperatur (K)" #: ../graphs.py:50 ../graphs.py:53 msgid "Plot" msgstr "Graf" #: ../graphs.py:58 msgid "clear" msgstr "ryd" #: ../graphs.py:112 msgid "Save data to file ... " msgstr "Gem data til fil ... " #: ../gtkexcepthook.py:118 msgid "Bug Detected" msgstr "Fejl fundet" #: ../gtkexcepthook.py:122 msgid "A programming error has been detected." msgstr "Der blev fundet en programmeringsfejl." #: ../gtkexcepthook.py:125 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:141 msgid "Report..." msgstr "Rapportér..." #: ../gtkexcepthook.py:145 msgid "Details..." msgstr "Detaljer..." #: ../gtkexcepthook.py:161 #, 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:174 msgid "Bug Details" msgstr "Detaljer om fejl" #: ../gui.py:191 msgid "_File" msgstr "_Fil" #: ../gui.py:192 msgid "_Edit" msgstr "_Redigér" #: ../gui.py:193 msgid "_View" msgstr "_Vis" #: ../gui.py:194 msgid "_Tools" msgstr "_Værktøjer" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:196 msgid "_Setup" msgstr "_Byg" #: ../gui.py:197 msgid "_Calculate" msgstr "_Beregn" #: ../gui.py:198 msgid "_Help" msgstr "_Hjælp" #: ../gui.py:199 msgid "_Open" msgstr "_Åbn" #: ../gui.py:200 msgid "Create a new file" msgstr "Opret en ny fil" #: ../gui.py:202 msgid "_New" msgstr "_Ny" #: ../gui.py:203 msgid "New ase.gui window" msgstr "Nyt ase.gui-vindue" #: ../gui.py:205 msgid "_Save" msgstr "_Gem" #: ../gui.py:206 msgid "Save current file" msgstr "Gem den aktuelle fil" #: ../gui.py:208 msgid "_Quit" msgstr "_Afslut" #: ../gui.py:209 msgid "Quit" msgstr "Afslut" #: ../gui.py:211 msgid "Select _all" msgstr "Vælg _alle" #: ../gui.py:214 msgid "_Invert selection" msgstr "_Omvend markering" #: ../gui.py:217 msgid "Select _constrained atoms" msgstr "Vælg _fastgjorte atomer" #: ../gui.py:220 msgid "Select _immobile atoms" msgstr "Vælg _immobile atomer" #: ../gui.py:223 msgid "_Copy" msgstr "_Kopiér" #: ../gui.py:224 msgid "Copy current selection and its orientation to clipboard" msgstr "Kopiér nuværende markering og dens orientering til udklipsholderen" #: ../gui.py:226 msgid "_Paste" msgstr "_Indsæt" #: ../gui.py:227 msgid "Insert current clipboard selection" msgstr "Indsæt nuværende markering fra udklipsholderen" #: ../gui.py:229 msgid "_Modify" msgstr "_Ændr" #: ../gui.py:230 msgid "Change tags, moments and atom types of the selected atoms" msgstr "Ændr mærker, impuls og atomnummer for de valgte atomer" #: ../gui.py:232 msgid "_Add atoms" msgstr "_Tilføj atomer" #: ../gui.py:233 msgid "Insert or import atoms and molecules" msgstr "Indsæt eller importér atomer og molekyler" #: ../gui.py:235 msgid "_Delete selected atoms" msgstr "_Slet markerede atomer" #: ../gui.py:236 msgid "Delete the selected atoms" msgstr "Slet de markerede atomer" #: ../gui.py:238 msgid "_First image" msgstr "_Første billede" #: ../gui.py:241 msgid "_Previous image" msgstr "_Forrige billede" #: ../gui.py:244 msgid "_Next image" msgstr "_Næste billede" #: ../gui.py:247 msgid "_Last image" msgstr "_Sidste billede" #: ../gui.py:250 msgid "Show _Labels" msgstr "Vis _Etiketter" #: ../gui.py:251 msgid "Hide selected atoms" msgstr "Skjul markerede atomer" #: ../gui.py:254 msgid "Show selected atoms" msgstr "Vis markerede atomer" #: ../gui.py:257 msgid "Quick Info ..." msgstr "Hurtig info ..." #: ../gui.py:260 msgid "Repeat ..." msgstr "Gentag ..." #: ../gui.py:263 msgid "Rotate ..." msgstr "Rotér ..." #: ../gui.py:266 msgid "Colors ..." msgstr "Farver ..." #. TRANSLATORS: verb #: ../gui.py:269 msgid "Focus" msgstr "Fokusér" #: ../gui.py:272 msgid "Zoom in" msgstr "Zoom ind" #: ../gui.py:275 msgid "Zoom out" msgstr "Zoom ud" #: ../gui.py:278 msgid "Change View" msgstr "Skift perspektiv" #: ../gui.py:279 msgid "Reset View" msgstr "Nulstil perspektiv" #: ../gui.py:282 msgid "'xy' Plane" msgstr "'xy'-plan" #: ../gui.py:283 msgid "'yz' Plane" msgstr "'yz'-plan" #: ../gui.py:284 msgid "'zx' Plane" msgstr "'zx'-plan" #: ../gui.py:285 msgid "'yx' Plane" msgstr "'yx'-plan" #: ../gui.py:286 msgid "'zy' Plane" msgstr "'zy'-plan" #: ../gui.py:287 msgid "'xz' Plane" msgstr "'xz'-plan" #: ../gui.py:288 msgid "'a2 a3' Plane" msgstr "'a2 a3'-plan" #: ../gui.py:289 msgid "'a3 a1' Plane" msgstr "'a3 a1'-plan" #: ../gui.py:290 msgid "'a1 a2' Plane" msgstr "'a1 a2'-plan" #: ../gui.py:291 msgid "'a3 a2' Plane" msgstr "'a3 a2'-plan" #: ../gui.py:292 msgid "'a1 a3' Plane" msgstr "'a1 a3'-plan" #: ../gui.py:293 msgid "'a2 a1' Plane" msgstr "'a2 a1'-plan" #: ../gui.py:294 msgid "Settings ..." msgstr "Indstillinger ..." #: ../gui.py:297 msgid "VMD" msgstr "VMD" #: ../gui.py:300 msgid "RasMol" msgstr "RasMol" #: ../gui.py:303 msgid "xmakemol" msgstr "xmakemol" #: ../gui.py:306 msgid "avogadro" msgstr "avogadro" #: ../gui.py:309 msgid "Graphs ..." msgstr "Grafer ..." #: ../gui.py:312 msgid "Movie ..." msgstr "Film ..." #: ../gui.py:315 msgid "Expert mode ..." msgstr "Eksperttilstand ..." #: ../gui.py:318 msgid "Constraints ..." msgstr "Begrænsninger ..." # gemmer et billede af atomerne #: ../gui.py:321 msgid "Render scene ..." msgstr "Tegn struktur ..." #: ../gui.py:324 msgid "DFT ..." msgstr "DFT ..." #: ../gui.py:327 msgid "NE_B" msgstr "NE_B" #: ../gui.py:330 msgid "B_ulk Modulus" msgstr "K_ompressibilitetsmodul" #: ../gui.py:333 msgid "_Bulk Crystal" msgstr "_Krystal" #: ../gui.py:334 msgid "Create a bulk crystal with arbitrary orientation" msgstr "Opret en krystalstruktur med arbitrær orientering" #: ../gui.py:336 msgid "_Surface slab" msgstr "_Overflade" #: ../gui.py:337 msgid "Create the most common surfaces" msgstr "Opret de mest almindelige overflader" #: ../gui.py:339 msgid "_Nanoparticle" msgstr "_Nanopartikel" #: ../gui.py:340 msgid "Create a crystalline nanoparticle" msgstr "Opret en krystallinsk nanopartikel" #: ../gui.py:342 msgid "Nano_tube" msgstr "Nano_rør" #: ../gui.py:343 msgid "Create a nanotube" msgstr "Opret et nanorør" #: ../gui.py:346 msgid "Create a graphene sheet or nanoribbon" msgstr "Opret et lag eller bånd af grafén" #: ../gui.py:348 msgid "Set _Calculator" msgstr "Angiv _beregner" #: ../gui.py:349 msgid "Set a calculator used in all calculation modules" msgstr "Angiv en beregner der skal bruges i alle beregningsmoduler" #: ../gui.py:351 msgid "_Energy and Forces" msgstr "_Energi og kræfter" #: ../gui.py:352 msgid "Calculate energy and forces" msgstr "Beregn energi og kræfter" #: ../gui.py:354 msgid "Energy _Minimization" msgstr "Energi_minimering" #: ../gui.py:355 msgid "Minimize the energy" msgstr "Minimér energien" #: ../gui.py:357 msgid "Scale system" msgstr "Skalér systemet" #: ../gui.py:358 msgid "Deform system by scaling it" msgstr "Deformér systemet ved skalering" #: ../gui.py:360 msgid "_About" msgstr "_Om" #: ../gui.py:363 msgid "Webpage ..." msgstr "Webside ..." #: ../gui.py:364 msgid "Debug ..." msgstr "Fejlsøgning ..." #: ../gui.py:366 msgid "Show _unit cell" msgstr "Vis _enhedscelle" #: ../gui.py:370 msgid "Show _axes" msgstr "Vis _akser" #: ../gui.py:374 msgid "Show _bonds" msgstr "Vis _bindinger" #: ../gui.py:378 msgid "Show _velocities" msgstr "Vis _hastigheder" #: ../gui.py:382 msgid "Show _forces" msgstr "Vis _kræfter" #: ../gui.py:386 msgid "_Move atoms" msgstr "_Flyt atomer" #: ../gui.py:390 msgid "_Rotate atoms" msgstr "_Rotér atomer" #: ../gui.py:394 msgid "Orien_t atoms" msgstr "Orien_tér atomer" #: ../gui.py:400 msgid "_None" msgstr "_Ingen" #: ../gui.py:401 msgid "Atom _Index" msgstr "Atom _Indeks" #: ../gui.py:402 msgid "_Magnetic Moments" msgstr "_Magnetiske Momenter" #: ../gui.py:403 msgid "_Element Symbol" msgstr "_Kemisk symbol" #: ../gui.py:412 #, python-format msgid "building menus failed: %s" msgstr "bygning af menuer mislykkedes: %s" #: ../gui.py:687 ../gui.py:1093 ../gui.py:1153 msgid "Open ..." msgstr "Åbn ..." #: ../gui.py:691 ../gui.py:1096 msgid "<>" msgstr "<>" #: ../gui.py:824 msgid "Add atoms" msgstr "Tilføj atomer" #: ../gui.py:827 msgid "Paste" msgstr "Indsæt" #: ../gui.py:833 msgid "Insert atom or molecule" msgstr "Indsæt atom eller molekyle" #: ../gui.py:834 ../gui.py:960 msgid "Tag" msgstr "Mærke" #: ../gui.py:835 ../gui.py:961 msgid "Moment" msgstr "Moment" #: ../gui.py:836 msgid "Position" msgstr "Position" #: ../gui.py:861 msgid "_Load molecule" msgstr "_Indlæs molekyle" #: ../gui.py:865 ../gui.py:976 msgid "_OK" msgstr "_O.k." #: ../gui.py:869 ../gui.py:980 msgid "_Cancel" msgstr "_Annullér" #: ../gui.py:953 msgid "Modify" msgstr "Ændr" #: ../gui.py:959 msgid "Atom" msgstr "Atom" #: ../gui.py:1004 msgid "Confirmation" msgstr "Bekræftelse" #: ../gui.py:1008 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "Slet det valgte atom?" msgstr[1] "Slet de valgte atomer?" #: ../gui.py:1015 msgid "Cancel" msgstr "Annullér" #: ../gui.py:1101 msgid "Automatic" msgstr "Automatisk" #: ../gui.py:1102 msgid "Dacapo netCDF output file" msgstr "netCDF-uddatafil fra Dacapo" #: ../gui.py:1103 msgid "Virtual Nano Lab file" msgstr "Virtual Nano Lab-fil" #: ../gui.py:1104 msgid "ASE pickle trajectory" msgstr "Pickletrajectory fra ASE" #: ../gui.py:1105 msgid "ASE bundle trajectory" msgstr "Bundletrajectory fra ASE" #: ../gui.py:1106 msgid "GPAW text output" msgstr "Textudskrift fra GPAW" #: ../gui.py:1107 msgid "CUBE file" msgstr "CUBE-fil" #: ../gui.py:1108 msgid "XCrySDen Structure File" msgstr "XCrySDen-strukturfil" #: ../gui.py:1109 msgid "Dacapo text output" msgstr "Tekstudskrift fra Dacapo" #: ../gui.py:1110 msgid "XYZ-file" msgstr "XYZ-fil" #: ../gui.py:1111 msgid "VASP POSCAR/CONTCAR file" msgstr "POSCAR/CONTCAR-fil fra VASP" #: ../gui.py:1112 msgid "VASP OUTCAR file" msgstr "OUTCAR-fil fra VASP" #: ../gui.py:1113 msgid "Protein Data Bank" msgstr "Proteindatabank" #: ../gui.py:1114 msgid "CIF-file" msgstr "CIF-fil" #: ../gui.py:1115 msgid "FHI-aims geometry file" msgstr "FHI-aims-geometrifil" #: ../gui.py:1116 msgid "FHI-aims output file" msgstr "Uddatafil fra FHI-aims" #: ../gui.py:1117 msgid "TURBOMOLE coord file" msgstr "TURBOMOLE-koordinatfil" # exciting er et program #: ../gui.py:1118 msgid "exciting input" msgstr "exciting-inddata" #: ../gui.py:1119 msgid "WIEN2k structure file" msgstr "WIEN2k-strukturfil" #: ../gui.py:1120 msgid "DftbPlus input file" msgstr "DftbPlus-inddatafil" #: ../gui.py:1121 msgid "ETSF format" msgstr "ETSF-format" #: ../gui.py:1122 msgid "CASTEP geom file" msgstr "CASTEP-geom-fil" #: ../gui.py:1123 msgid "CASTEP output file" msgstr "Uddatafil fra CASTEP" #: ../gui.py:1124 msgid "CASTEP trajectory file" msgstr "Trajectory-fil fra CASTEP" #: ../gui.py:1125 msgid "DFTBPlus GEN format" msgstr "GEN-format fra DFTBPlus" #: ../gui.py:1131 msgid "File type:" msgstr "Filtype:" #: ../gui.py:1254 msgid "Not implemented!" msgstr "Ikke implementeret!" #: ../gui.py:1255 msgid "do you really need it?" msgstr "har du virkelig brug for dette?" #: ../minimize.py:21 msgid "Algorithm: " msgstr "Algoritme: " #: ../minimize.py:26 ../progress.py:68 msgid "Convergence criterion: Fmax = " msgstr "Konvergenskriterium: Fmax = " #: ../minimize.py:31 ../progress.py:71 msgid "Max. number of steps: " msgstr "Maksimalt antal trin: " #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "Pseudotidsskridt: " #: ../minimize.py:55 msgid "Energy minimization" msgstr "Energiminimering" #: ../minimize.py:59 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:91 ../scaling.py:301 msgid "Running ..." msgstr "Kører ..." #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "Minimering AFBRUDT efter %i trin." #: ../minimize.py:114 ../scaling.py:352 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:121 #, python-format msgid "Minimization completed in %i steps." msgstr "Minimering fuldført på %i trin." #. self.connect('delete_event', self.exit2) #: ../movie.py:13 msgid "Movie" msgstr "Film" #: ../movie.py:15 msgid "Image number:" msgstr "Billednummer:" #: ../movie.py:37 msgid "Play" msgstr "Afspil" #: ../movie.py:39 msgid "Stop" msgstr "Stop" #. TRANSLATORS: This function plays an animation forwards and backwards #. alternatingly, e.g. for displaying vibrational movement #: ../movie.py:43 msgid "Rock" msgstr "Pendul" #: ../movie.py:59 msgid " Frame rate: " msgstr " Billedrate: " #: ../movie.py:60 msgid " Skip frames: " msgstr " Overspring billeder: " #: ../nanoparticle.py:20 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:27 #, python-brace-format 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:84 msgid "Face centered cubic (fcc)" msgstr "Face centered cubic (fcc)" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "Body centered cubic (bcc)" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "Simpel kubisk (sc)" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "Heksagonal tætpakket (hcp)" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "Grafit" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "Nanopartikel" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "Grundstof: " #: ../nanoparticle.py:131 msgid "Get structure" msgstr "Hent struktur" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "Gitterkonstant: a =" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "Metode: " #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "Lagspecifikation" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "Wulffkonstruktion" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "Stedfortræderobjekt" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "Tilføj ny retning:" #: ../nanoparticle.py:212 msgid "Add" msgstr "Tilføj" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "Sæt alle retninger til standardværdier" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "Partikelstørrelse: " #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:197 msgid "Number of atoms: " msgstr "Antal atomer: " #: ../nanoparticle.py:234 msgid "Volume: " msgstr "Volumen: " #: ../nanoparticle.py:239 msgid "ų" msgstr "ų" #: ../nanoparticle.py:244 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:247 msgid "above " msgstr "over " #: ../nanoparticle.py:248 msgid "below " msgstr "under " #: ../nanoparticle.py:249 msgid "closest " msgstr "tættest på " #: ../nanoparticle.py:252 msgid "Smaller" msgstr "Mindre" #: ../nanoparticle.py:253 msgid "Larger" msgstr "Større" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr " Diameter omtrent: " #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "Information om den konstruerede klynge:" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "Konstruktion af nanopartikel." #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "Anvend automatisk" #: ../nanoparticle.py:333 msgid "Up" msgstr "Op" #: ../nanoparticle.py:338 msgid "Down" msgstr "Ned" #: ../nanoparticle.py:343 msgid "Delete" msgstr "Slet" #: ../nanoparticle.py:384 msgid "Surface energies (as energy/area, NOT per atom):" msgstr "Overfladeenergier (som energi/areal, IKKE per atom):" #: ../nanoparticle.py:390 msgid "Number of layers:" msgstr "Antal lag:" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "Mindst et indeks skal være forskelligt fra nul" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "Ugyldige heksagonale indeks" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "Ugyldigt grundstof." #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "Uunderstøttet eller ukendt struktur" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "%.1f Å" #: ../nanotube.py:15 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:29 #, python-format msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: " "%(volume).3f Å3" msgstr "" " %(natoms)i atomer: %(symbols)s, diameter: %(diameter).3f Å, cellevolumen: " "%(volume).3f Å3" #: ../nanotube.py:35 msgid "Nanotube" msgstr "Nanorør" #. Choose the structure. #: ../nanotube.py:59 msgid "Select roll-up vector (n,m) and tube length:" msgstr "Vælg oprulningsvektor (n,m) og rørlængde:" #: ../progress.py:26 msgid "Progress" msgstr "Fremgang" #: ../progress.py:33 msgid "Scaling deformation:" msgstr "Skaleringsdeformation:" #: ../progress.py:39 #, python-format msgid "Step number %s of %s." msgstr "Trin nummer %s af %s." #. Minimization progress frame #. Box containing frame and spacing #: ../progress.py:54 msgid "Energy minimization:" msgstr "Energiminimering:" #: ../progress.py:61 msgid "Step number: " msgstr "Trinnummer: " #: ../progress.py:63 msgid "Fmax: " msgstr "Fmax: " #: ../progress.py:103 msgid "unknown" msgstr "ukendt" #: ../progress.py:180 msgid "Status: " msgstr "Status: " #: ../progress.py:182 msgid "Iteration: " msgstr "Iteration: " #: ../progress.py:185 msgid "log10(change):" msgstr "log10(skift):" #: ../progress.py:188 msgid "Wave functions: " msgstr "Bølgefunktioner: " #: ../progress.py:190 msgid "Density: " msgstr "Tæthed: " #: ../progress.py:192 msgid "Energy: " msgstr "Energi: " #: ../progress.py:195 msgid "GPAW version: " msgstr "GPAW-version: " #: ../progress.py:198 msgid "N/A" msgstr "-" #: ../progress.py:199 msgid "Memory estimate: " msgstr "Hukommelsesestimat: " #: ../progress.py:234 msgid "No info" msgstr "Ingen info" #: ../progress.py:244 msgid "Initializing" msgstr "Klargør" #: ../progress.py:245 msgid "Positions:" msgstr "Positioner:" #: ../progress.py:249 msgid "Starting calculation" msgstr "Starter beregning" #: ../progress.py:286 msgid "unchanged" msgstr "uændret" #: ../progress.py:296 msgid "Self-consistency loop" msgstr "Selvkonsistensløkke" #: ../progress.py:301 msgid "Calculating forces" msgstr "Beregner kræfter" #: ../progress.py:302 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" "\n" "%s\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" "\n" "%s\n" "%s\n" #: ../quickinfo.py:31 msgid "Quick Info" msgstr "Hurtig info" #: ../quickinfo.py:35 msgid "No atoms loaded." msgstr "Ingen atomer indlæst." #: ../quickinfo.py:56 msgid "no" msgstr "nej" #: ../quickinfo.py:56 msgid "yes" msgstr "ja" #. TRANSLATORS: This has the form Periodic: no, no, yes #: ../quickinfo.py:60 #, python-format msgid "Periodic: %s, %s, %s" msgstr "Periodisk: %s, %s, %s" #: ../render.py:15 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:33 msgid "Render current view in povray ... " msgstr "Tegn nuværende struktur i povray ... " #: ../render.py:37 #, python-format msgid "Rendering %d atoms." msgstr "Tegner %d atomer." #: ../render.py:42 msgid "Render constraints" msgstr "Tegn begrænsninger" #: ../render.py:45 msgid "Width" msgstr "Bredde" #: ../render.py:46 msgid " Height" msgstr " Højde" #: ../render.py:53 msgid "Render unit cell" msgstr "Tegn _enhedscelle" #: ../render.py:62 msgid "Line width" msgstr "Linjebredde" #: ../render.py:64 msgid "Angstrom " msgstr "Ångström " #: ../render.py:74 msgid "Set" msgstr "Angiv" #: ../render.py:76 msgid "Output basename: " msgstr "Basisnavn for output: " #: ../render.py:78 msgid " Filename: " msgstr " Filnavn: " #: ../render.py:89 msgid " Default texture for atoms: " msgstr " Standardtekstur for atomer: " #: ../render.py:90 msgid " transparency: " msgstr " gennemsigtighed: " #: ../render.py:91 msgid "Define atom selection for new texture:" msgstr "Definér atommarkering til ny tekstur:" #: ../render.py:93 msgid "Select" msgstr "Vælg" #: ../render.py:97 msgid "Create new texture from selection" msgstr "Opret ny tekstur fra markering" #: ../render.py:99 msgid "Help on textures" msgstr "Hjælp til teksturer" #: ../render.py:112 msgid "Camera type: " msgstr "Kameratype: " #: ../render.py:113 msgid " Camera distance" msgstr " Kameraafstand" #: ../render.py:114 msgid "Render current frame" msgstr "Tegn det aktuelle billede" #: ../render.py:118 #, python-format msgid "Render all %d frames" msgstr "Tegn alle %d billeder" #: ../render.py:123 msgid "Transparent background" msgstr "Gennemsigtig baggrund" #: ../render.py:126 msgid "Run povray " msgstr "Kør povray " #: ../render.py:129 msgid "Keep povray files " msgstr "Behold povray-filer " #: ../render.py:132 msgid "Show output window" msgstr "Vis outputvindue" #: ../render.py:213 msgid " transparency: " msgstr " gennemsigtighed: " #: ../render.py:219 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:12 msgid "Repeat" msgstr "Gentag" #: ../repeat.py:19 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:150 msgid "2nd" msgstr "2." #: ../scaling.py:151 msgid "3rd" msgstr "3." #: ../scaling.py:155 msgid "Order of fit: " msgstr "Orden for fit: " #. Update display to reflect cancellation of simulation. #: ../scaling.py:348 msgid "Calculation CANCELLED." msgstr "Beregning AFBRUDT." #. Update display to reflect succesful end of simulation. #: ../scaling.py:359 msgid "Calculation completed." msgstr "Beregning fuldført." #: ../scaling.py:382 msgid "No trustworthy minimum: Old configuration kept." msgstr "Intet troværdigt minimum: Gammel konfiguration beholdt." #: ../scaling.py:422 #, 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:426 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:442 msgid "No minimum found!" msgstr "Intet minimum fundet!" #: ../scaling.py:456 msgid "" "\n" "WARNING: Minimum is outside interval\n" msgstr "" "\n" "ADVARSEL: Minimum ligger uden for interval\n" #: ../scaling.py:457 msgid "It is UNRELIABLE!\n" msgstr "Det er UTILREGNELIGT!\n" #: ../settings.py:15 msgid "Constraints:" msgstr "Begrænsninger:" #: ../settings.py:18 msgid "release" msgstr "frigiv" # I dette tilfælde er constrain = fastgøre #: ../settings.py:22 msgid "Constrain immobile atoms" msgstr "Fastgør immobile atomer" #: ../settings.py:24 msgid "Clear all constraints" msgstr "Ryd alle begrænsninger" #: ../settings.py:30 msgid "Visibility:" msgstr "Synlighed:" #: ../settings.py:31 msgid "Hide" msgstr "Skjul" #: ../settings.py:33 msgid "show" msgstr "vis" #: ../settings.py:37 msgid "View all atoms" msgstr "Vis alle atomer" #: ../settings.py:43 msgid "Miscellaneous:" msgstr "Diverse:" #: ../settings.py:46 msgid "Scale atomic radii:" msgstr "Skalér atomradier:" #. A close button #: ../settings.py:51 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:36 ../status.py:38 msgid "Tip for status box ..." msgstr "Fif til statusboks ..." #. TRANSLATORS: mom refers to magnetic moment #: ../status.py:62 #, python-format msgid " tag=%(tag)s mom=%(mom)1.2f" msgstr " mærke=%(tag)s mom=%(mom)1.2f" #: ../status.py:103 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:58 ../widgets.py:87 msgid "Help" msgstr "Hjælp" #: ../widgets.py:104 msgid "Clear constraint" msgstr "Ryd begrænsninger" #~ 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." #~ msgid "Max force: %.2f (this frame), %.2f (all frames)" #~ msgstr "Maks. kraft: %.2f (dette billede), %.2f (alle billeder)" #~ msgid "Max force: %.2f." #~ msgstr "Maks. kraft: %.2f." #~ msgid "Max velocity: %.2f (this frame), %.2f (all frames)" #~ msgstr "Maks. hastighed: %.2f (dette billede), %.2f (alle billeder)" #~ msgid "Max velocity: %.2f." #~ msgstr "Maks. hastighed: %.2f." #~ msgid "Min, max charge: %.2f, %.2f (this frame)," #~ msgstr "Min., maks. ladning: %.2f, %.2f (dette billede)," #~ msgid "Min, max charge: %.2f, %.2f." #~ msgstr "Min., maks. ladning: %.2f, %.2f." #~ msgid "Save ..." #~ msgstr "Gem ..." #~ msgid "XYZ file" #~ msgstr "XYZ-fil" #~ msgid "ASE trajectory" #~ msgstr "Trajectory fra ASE" #~ msgid "PDB file" #~ msgstr "PDB-fil" #~ msgid "Gaussian cube file" #~ msgstr "Cube-fil fra Gaussian" #~ msgid "Python script" #~ msgstr "Pythonscript" #~ msgid "VNL file" #~ msgstr "VNL-fil" #~ msgid "Portable Network Graphics" #~ msgstr "Portable Network Graphics" #~ msgid "Persistence of Vision" #~ msgstr "Persistence of Vision" #~ msgid "Encapsulated PostScript" #~ msgstr "Encapsulated PostScript" #~ msgid "FHI-aims geometry input" #~ msgstr "Geometriinddata til FHI-aims" #~ msgid "VASP geometry input" #~ msgstr "Geometriinddata til VASP" #~ msgid "cif file" #~ msgstr "cif-fil" #~ msgid "Save current image only (#%d)" #~ msgstr "Gem kun nuværende billede (#%d)" # slice ~ opdel #~ msgid "Slice: " #~ msgstr "Del: " #~ msgid "Help for slice ..." #~ msgstr "Hjælp til opdeling ..." #~ msgid "ase-gui INTERNAL ERROR: strange response in Save," #~ msgstr "INTERN FEJL I ase-gui: mystisk svar i Save," #~ msgid "Unknown output format!" #~ msgstr "Ukendt uddataformat!" #~ msgid "Use one of: %s" #~ msgstr "Brug et af: %s" #~ 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.9.1.4567/ase/gui/po/ag.pot0000664000175000017500000015423312553425527017574 0ustar jensjjensj00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR CAMD # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: ase\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2014-10-07 21:29+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "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:140 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 EAM/ADP potential is a many-body potential\n" "implementation of the Embedded Atom Method and\n" "equipotential plus the Angular Dependent Potential,\n" "which is an extension of the EAM to include\n" "directional bonds. EAM is suited for FCC metallic\n" "bonding while the ADP is suited for metallic bonds\n" "with some degree of directionality.\n" "\n" "For EAM see M.S. Daw and M.I. Baskes,\n" "Phys. Rev. Letters 50 (1983) 1285.\n" "\n" "For ADP see Y. Mishin, M.J. Mehl, and\n" "D.A. Papaconstantopoulos, Acta Materialia 53 2005\n" "4029--4041.\n" "\n" "Data for the potential is contained in a file in either LAMMPS Alloy\n" "or ADP format which need to be loaded before use. The Interatomic\n" "Potentials Repository Project at http://www.ctcms.nist.gov/potentials/\n" "contains many suitable potential files.\n" "\n" "For large simulations the LAMMPS calculator is more\n" "suitable; this implementation is mainly to make EAM\n" "available when LAMMPS is not installed or to develop\n" "new EAM/ADP poentials by matching results using ab\n" "initio.\n" msgstr "" #: ../calculator.py:113 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:135 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:142 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:152 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:159 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:168 msgid "Default (Al, Ni, Cu, Pd, Ag, Pt, Au)" msgstr "" #: ../calculator.py:169 msgid "Alternative Cu, Ag and Au" msgstr "" #: ../calculator.py:170 msgid "Ruthenium" msgstr "" #: ../calculator.py:171 msgid "CuMg and CuZr metallic glass" msgstr "" #: ../calculator.py:189 msgid "Select calculator" msgstr "" #: ../calculator.py:195 msgid "Calculator:" msgstr "" #. No calculator (the default) #: ../calculator.py:198 msgid "None" msgstr "" #: ../calculator.py:203 msgid "Lennard-Jones (ASAP)" msgstr "" #: ../calculator.py:204 ../calculator.py:231 ../calculator.py:246 #: ../calculator.py:255 ../calculator.py:264 msgid "Setup" msgstr "" #: ../calculator.py:211 msgid "EMT - Effective Medium Theory (ASAP)" msgstr "" #: ../calculator.py:223 msgid "EMT - Effective Medium Theory (ASE)" msgstr "" #: ../calculator.py:230 msgid "EAM - Embedded Atom Method/Angular Dependent Potential (ASE)" msgstr "" #: ../calculator.py:238 msgid "Brenner Potential (ASAP)" msgstr "" #: ../calculator.py:244 msgid "Density Functional Theory (GPAW)" msgstr "" #: ../calculator.py:253 msgid "Density Functional Theory (FHI-aims)" msgstr "" #: ../calculator.py:262 msgid "Density Functional Theory (VASP)" msgstr "" #: ../calculator.py:275 msgid "Check that the calculator is reasonable." msgstr "" #: ../calculator.py:345 ../simulation.py:114 msgid "No atoms present" msgstr "" #: ../calculator.py:439 ../calculator.py:474 ../calculator.py:521 msgid "ASAP is not installed. (Failed to import asap3)" msgstr "" #: ../calculator.py:442 msgid "You must set up the Lennard-Jones parameters" msgstr "" #: ../calculator.py:447 msgid "Could not create useful Lennard-Jones calculator." msgstr "" #: ../calculator.py:482 msgid "Could not attach EMT calculator to the atoms." msgstr "" #: ../calculator.py:503 msgid "You must set up the EAM parameters" msgstr "" #: ../calculator.py:539 ../calculator.py:551 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "" #: ../calculator.py:542 msgid "You must set up the GPAW parameters" msgstr "" #: ../calculator.py:584 msgid "You must set up the FHI-aims parameters" msgstr "" #: ../calculator.py:599 msgid "You must set up the VASP parameters" msgstr "" #: ../calculator.py:624 #, python-format msgid "Element %(sym)s not allowed by the '%(name)s' calculator" msgstr "" #: ../calculator.py:632 msgid "Info" msgstr "" #: ../calculator.py:648 msgid "Lennard-Jones parameters" msgstr "" #: ../calculator.py:660 msgid "Specify the Lennard-Jones parameters here" msgstr "" #: ../calculator.py:663 msgid "Epsilon (eV):" msgstr "" #: ../calculator.py:667 msgid "Sigma (Å):" msgstr "" #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:671 msgid "Shift to make smooth at cutoff" msgstr "" #: ../calculator.py:750 msgid "EAM parameters" msgstr "" #: ../calculator.py:764 msgid "Import Potential" msgstr "" #: ../calculator.py:787 msgid "You need to import the potential file" msgstr "" #: ../calculator.py:795 msgid "Import .alloy or .adp potential file ... " msgstr "" #: ../calculator.py:818 msgid "GPAW parameters" msgstr "" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:833 ../calculator.py:1123 ../calculator.py:1612 #, python-format msgid "%i atoms.\n" msgstr "" #: ../calculator.py:835 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "" #: ../calculator.py:837 msgid "Non-orthogonal unit cell:\n" msgstr "" #: ../calculator.py:847 ../calculator.py:1139 ../calculator.py:1627 msgid "Exchange-correlation functional: " msgstr "" #. Grid spacing #: ../calculator.py:851 msgid "Grid spacing" msgstr "" #: ../calculator.py:855 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "" #: ../calculator.py:856 msgid "Grid points" msgstr "" #: ../calculator.py:865 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "" #: ../calculator.py:891 ../calculator.py:1154 ../calculator.py:1663 msgid "k-points k = (" msgstr "" #: ../calculator.py:895 ../calculator.py:1158 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "" #. Spin polarized #: ../calculator.py:900 ../calculator.py:1625 msgid "Spin polarized" msgstr "" #: ../calculator.py:906 msgid "FD - Finite Difference (grid) mode" msgstr "" #: ../calculator.py:907 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "" #: ../calculator.py:910 msgid "Mode: " msgstr "" #: ../calculator.py:912 msgid "sz - Single Zeta" msgstr "" #: ../calculator.py:913 msgid "szp - Single Zeta polarized" msgstr "" #: ../calculator.py:914 msgid "dzp - Double Zeta polarized" msgstr "" #. dzp #: ../calculator.py:916 msgid "Basis functions: " msgstr "" #. Mixer #: ../calculator.py:922 msgid "Non-standard mixer parameters" msgstr "" #: ../calculator.py:1119 msgid "FHI-aims parameters" msgstr "" #: ../calculator.py:1126 msgid "Periodic geometry, unit cell is:\n" msgstr "" #: ../calculator.py:1131 msgid "Non-periodic geometry.\n" msgstr "" #: ../calculator.py:1138 msgid "Hirshfeld-based dispersion correction" msgstr "" #. Spin polarized, charge, relativity #: ../calculator.py:1164 msgid "Spin / initial moment " msgstr "" #: ../calculator.py:1182 msgid " Charge" msgstr "" #: ../calculator.py:1184 msgid " Relativity" msgstr "" #: ../calculator.py:1186 msgid " Threshold" msgstr "" #. self-consistency criteria #: ../calculator.py:1191 msgid "Self-consistency convergence:" msgstr "" #: ../calculator.py:1204 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:1215 msgid "Energy: " msgstr "" #: ../calculator.py:1217 msgid " eV Sum of eigenvalues: " msgstr "" #: ../calculator.py:1219 ../calculator.py:1698 msgid " eV" msgstr "" #: ../calculator.py:1220 msgid "Electron density: " msgstr "" #: ../calculator.py:1222 msgid " Force convergence: " msgstr "" #: ../calculator.py:1224 msgid " eV/Ang " msgstr "" #: ../calculator.py:1237 ../calculator.py:1709 msgid "Additional keywords: " msgstr "" #. run command and species defaults: #: ../calculator.py:1251 msgid "FHI-aims execution command: " msgstr "" #: ../calculator.py:1253 ../calculator.py:1726 msgid "Directory for species defaults: " msgstr "" #: ../calculator.py:1265 ../calculator.py:1734 msgid "Set Defaults" msgstr "" #: ../calculator.py:1267 msgid "Import control.in" msgstr "" #: ../calculator.py:1269 msgid "Export control.in" msgstr "" #: ../calculator.py:1456 msgid "Export parameters ... " msgstr "" #: ../calculator.py:1476 msgid "Import control.in file ... " msgstr "" #: ../calculator.py:1532 ../calculator.py:2041 #, python-format msgid "" "Please use the facilities provided in this window to manipulate the keyword: " "%s!" msgstr "" #: ../calculator.py:1535 #, 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:1608 msgid "VASP parameters" msgstr "" #: ../calculator.py:1614 msgid "Periodic geometry, unit cell is: \n" msgstr "" #: ../calculator.py:1666 msgid ") Cutoff: " msgstr "" #: ../calculator.py:1667 msgid " Precision: " msgstr "" #: ../calculator.py:1669 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "" #: ../calculator.py:1685 msgid "Smearing: " msgstr "" #: ../calculator.py:1687 msgid " order: " msgstr "" #: ../calculator.py:1689 msgid " width: " msgstr "" #: ../calculator.py:1696 msgid "Self-consistency convergence: " msgstr "" #. run command and location of POTCAR files: #: ../calculator.py:1722 msgid "VASP execution command: " msgstr "" #: ../calculator.py:1736 msgid "Import VASP files" msgstr "" #: ../calculator.py:1738 msgid "Export VASP files" msgstr "" #: ../calculator.py:1945 msgid "WARNING: cutoff energy is lower than recommended minimum!" msgstr "" #: ../calculator.py:1997 msgid "Import VASP input files: choose directory ... " msgstr "" #: ../calculator.py:2011 msgid "Export VASP input files: choose directory ... " msgstr "" #: ../calculator.py:2044 #, 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 "By charge" msgstr "" #: ../colors.py:50 msgid "Manually specified" msgstr "" #: ../colors.py:51 msgid "All the same color" msgstr "" #. Now fill in the box for additional information in case the force is used. #. Now fill in the box for additional information in case #. the charge is used. #: ../colors.py:63 ../colors.py:98 msgid "This should not be displayed!" msgstr "" #: ../colors.py:68 ../colors.py:85 ../colors.py:103 ../rotate.py:25 msgid "Update" msgstr "" #: ../colors.py:70 ../colors.py:87 ../colors.py:105 msgid "Min: " msgstr "" #: ../colors.py:72 ../colors.py:89 ../colors.py:107 msgid " Max: " msgstr "" #: ../colors.py:74 ../colors.py:91 ../colors.py:109 msgid " Steps: " msgstr "" #: ../colors.py:116 msgid "Create a color scale:" msgstr "" #: ../colors.py:119 msgid "Black - white" msgstr "" #: ../colors.py:120 msgid "Black - red - yellow - white" msgstr "" #: ../colors.py:121 msgid "Black - green - white" msgstr "" #: ../colors.py:122 msgid "Black - blue - cyan" msgstr "" #: ../colors.py:123 msgid "Blue - white - red" msgstr "" #: ../colors.py:124 msgid "Hue" msgstr "" #: ../colors.py:125 msgid "Named colors" msgstr "" #: ../colors.py:131 msgid "Create" msgstr "" #: ../colors.py:428 #, python-format msgid "Max force: %.2f (this frame), %.2f (all frames)" msgstr "" #: ../colors.py:430 #, python-format msgid "Max force: %.2f." msgstr "" #: ../colors.py:444 #, python-format msgid "Max velocity: %.2f (this frame), %.2f (all frames)" msgstr "" #: ../colors.py:446 #, python-format msgid "Max velocity: %.2f." msgstr "" #: ../colors.py:460 #, python-format msgid "Min, max charge: %.2f, %.2f (this frame)," msgstr "" #: ../colors.py:464 #, python-format msgid "Min, max charge: %.2f, %.2f." msgstr "" #: ../colors.py:505 msgid "ERROR" msgstr "" #: ../colors.py:534 msgid "ERR" msgstr "" #: ../colors.py:626 msgid "Incorrect color specification" msgstr "" #: ../constraints.py:12 ../widgets.py:91 msgid "Constraints" msgstr "" #: ../constraints.py:14 ../constraints.py:17 ../settings.py:16 #: ../widgets.py:93 ../widgets.py:96 msgid "Constrain" msgstr "" #: ../constraints.py:15 ../settings.py:19 ../settings.py:34 ../widgets.py:94 msgid " selected atoms" msgstr "" #: ../constraints.py:18 ../widgets.py:97 msgid " immobile atoms:" msgstr "" #: ../constraints.py:20 msgid "Unconstrain" msgstr "" #: ../constraints.py:21 msgid " selected atoms:" msgstr "" #: ../constraints.py:23 msgid "Clear constraints" msgstr "" #: ../constraints.py:25 ../dft.py:28 ../settings.py:52 ../widgets.py:61 #: ../widgets.py:101 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 ../graphene.py:27 #, 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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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:12 msgid "DFT" msgstr "" #: ../dft.py:18 msgid "XC-functional: " msgstr "" #: ../dft.py:22 ../repeat.py:15 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:22 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: ase-gui window python object\n" " img:\tadvanced: ase-gui images object\n" " " msgstr "" #: ../execute.py:66 msgid "Expert user mode" msgstr "" #: ../execute.py:79 msgid "Welcome to the ASE Expert user mode" msgstr "" #: ../execute.py:86 msgid "Only selected atoms (sa) " msgstr "" #: ../execute.py:88 msgid "Only current frame (cf) " msgstr "" #: ../execute.py:98 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:197 #, python-format msgid "*** WARNING: file does not exist - %s" msgstr "" #: ../execute.py:202 msgid "*** WARNING: No atoms selected to work with" msgstr "" #: ../execute.py:276 msgid "*** Only working on selected atoms" msgstr "" #: ../execute.py:278 msgid "*** Working on all atoms" msgstr "" #: ../execute.py:282 msgid "*** Only working on current image" msgstr "" #: ../execute.py:284 msgid "*** Working on all images" msgstr "" #: ../execute.py:300 msgid "Save Terminal text ..." msgstr "" #: ../graphene.py:16 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:33 ../gui.py:344 msgid "Graphene" msgstr "" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "" #: ../graphene.py:42 msgid "Infinite sheet" msgstr "" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "" #: ../graphene.py:53 msgid "zigzag" msgstr "" #: ../graphene.py:53 msgid "armchair" msgstr "" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 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:90 msgid "Width: " msgstr "" #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr "" #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "" #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr "" #: ../graphene.py:194 msgid "Please specify a consistent set of atoms. " msgstr "" #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../pybutton.py:49 ../surfaceslab.py:249 msgid "You have not (yet) specified a consistent set of parameters." msgstr "" #: ../graphs.py:7 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" #: ../graphs.py:50 ../graphs.py:53 msgid "Plot" msgstr "" #: ../graphs.py:58 msgid "clear" msgstr "" #: ../graphs.py:112 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:190 msgid "_File" msgstr "" #: ../gui.py:191 msgid "_Edit" msgstr "" #: ../gui.py:192 msgid "_View" msgstr "" #: ../gui.py:193 msgid "_Tools" msgstr "" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:195 msgid "_Setup" msgstr "" #: ../gui.py:196 msgid "_Calculate" msgstr "" #: ../gui.py:197 msgid "_Help" msgstr "" #: ../gui.py:198 msgid "_Open" msgstr "" #: ../gui.py:199 msgid "Create a new file" msgstr "" #: ../gui.py:201 msgid "_New" msgstr "" #: ../gui.py:202 msgid "New ase-gui window" msgstr "" #: ../gui.py:204 msgid "_Save" msgstr "" #: ../gui.py:205 msgid "Save current file" msgstr "" #: ../gui.py:207 msgid "_Quit" msgstr "" #: ../gui.py:208 msgid "Quit" msgstr "" #: ../gui.py:210 msgid "Select _all" msgstr "" #: ../gui.py:213 msgid "_Invert selection" msgstr "" #: ../gui.py:216 msgid "Select _constrained atoms" msgstr "" #: ../gui.py:219 msgid "Select _immobile atoms" msgstr "" #: ../gui.py:222 msgid "_Copy" msgstr "" #: ../gui.py:223 msgid "Copy current selection and its orientation to clipboard" msgstr "" #: ../gui.py:225 msgid "_Paste" msgstr "" #: ../gui.py:226 msgid "Insert current clipboard selection" msgstr "" #: ../gui.py:228 msgid "_Modify" msgstr "" #: ../gui.py:229 msgid "Change tags, moments and atom types of the selected atoms" msgstr "" #: ../gui.py:231 msgid "_Add atoms" msgstr "" #: ../gui.py:232 msgid "Insert or import atoms and molecules" msgstr "" #: ../gui.py:234 msgid "_Delete selected atoms" msgstr "" #: ../gui.py:235 msgid "Delete the selected atoms" msgstr "" #: ../gui.py:237 msgid "_First image" msgstr "" #: ../gui.py:240 msgid "_Previous image" msgstr "" #: ../gui.py:243 msgid "_Next image" msgstr "" #: ../gui.py:246 msgid "_Last image" msgstr "" #: ../gui.py:249 msgid "Show _Labels" msgstr "" #: ../gui.py:250 msgid "Hide selected atoms" msgstr "" #: ../gui.py:253 msgid "Show selected atoms" msgstr "" #: ../gui.py:256 msgid "Quick Info ..." msgstr "" #: ../gui.py:259 msgid "Repeat ..." msgstr "" #: ../gui.py:262 msgid "Rotate ..." msgstr "" #: ../gui.py:265 msgid "Colors ..." msgstr "" #. TRANSLATORS: verb #: ../gui.py:268 msgid "Focus" msgstr "" #: ../gui.py:271 msgid "Zoom in" msgstr "" #: ../gui.py:274 msgid "Zoom out" msgstr "" #: ../gui.py:277 msgid "Change View" msgstr "" #: ../gui.py:278 msgid "Reset View" msgstr "" #: ../gui.py:281 msgid "'xy' Plane" msgstr "" #: ../gui.py:282 msgid "'yz' Plane" msgstr "" #: ../gui.py:283 msgid "'zx' Plane" msgstr "" #: ../gui.py:284 msgid "'yx' Plane" msgstr "" #: ../gui.py:285 msgid "'zy' Plane" msgstr "" #: ../gui.py:286 msgid "'xz' Plane" msgstr "" #: ../gui.py:287 msgid "'a2 a3' Plane" msgstr "" #: ../gui.py:288 msgid "'a3 a1' Plane" msgstr "" #: ../gui.py:289 msgid "'a1 a2' Plane" msgstr "" #: ../gui.py:290 msgid "'a3 a2' Plane" msgstr "" #: ../gui.py:291 msgid "'a1 a3' Plane" msgstr "" #: ../gui.py:292 msgid "'a2 a1' Plane" msgstr "" #: ../gui.py:293 msgid "Settings ..." msgstr "" #: ../gui.py:296 msgid "VMD" msgstr "" #: ../gui.py:299 msgid "RasMol" msgstr "" #: ../gui.py:302 msgid "xmakemol" msgstr "" #: ../gui.py:305 msgid "avogadro" msgstr "" #: ../gui.py:308 msgid "Graphs ..." msgstr "" #: ../gui.py:311 msgid "Movie ..." msgstr "" #: ../gui.py:314 msgid "Expert mode ..." msgstr "" #: ../gui.py:317 msgid "Constraints ..." msgstr "" #: ../gui.py:320 msgid "Render scene ..." msgstr "" #: ../gui.py:323 msgid "DFT ..." msgstr "" #: ../gui.py:326 msgid "NE_B" msgstr "" #: ../gui.py:329 msgid "B_ulk Modulus" msgstr "" #: ../gui.py:332 msgid "_Bulk Crystal" msgstr "" #: ../gui.py:333 msgid "Create a bulk crystal with arbitrary orientation" msgstr "" #: ../gui.py:335 msgid "_Surface slab" msgstr "" #: ../gui.py:336 msgid "Create the most common surfaces" msgstr "" #: ../gui.py:338 msgid "_Nanoparticle" msgstr "" #: ../gui.py:339 msgid "Create a crystalline nanoparticle" msgstr "" #: ../gui.py:341 msgid "Nano_tube" msgstr "" #: ../gui.py:342 msgid "Create a nanotube" msgstr "" #: ../gui.py:345 msgid "Create a graphene sheet or nanoribbon" msgstr "" #: ../gui.py:347 msgid "Set _Calculator" msgstr "" #: ../gui.py:348 msgid "Set a calculator used in all calculation modules" msgstr "" #: ../gui.py:350 msgid "_Energy and Forces" msgstr "" #: ../gui.py:351 msgid "Calculate energy and forces" msgstr "" #: ../gui.py:353 msgid "Energy _Minimization" msgstr "" #: ../gui.py:354 msgid "Minimize the energy" msgstr "" #: ../gui.py:356 msgid "Scale system" msgstr "" #: ../gui.py:357 msgid "Deform system by scaling it" msgstr "" #: ../gui.py:359 msgid "_About" msgstr "" #: ../gui.py:362 msgid "Webpage ..." msgstr "" #: ../gui.py:363 msgid "Debug ..." msgstr "" #: ../gui.py:365 msgid "Show _unit cell" msgstr "" #: ../gui.py:369 msgid "Show _axes" msgstr "" #: ../gui.py:373 msgid "Show _bonds" msgstr "" #: ../gui.py:377 msgid "Show _velocities" msgstr "" #: ../gui.py:381 msgid "Show _forces" msgstr "" #: ../gui.py:385 msgid "_Move atoms" msgstr "" #: ../gui.py:389 msgid "_Rotate atoms" msgstr "" #: ../gui.py:393 msgid "Orien_t atoms" msgstr "" #: ../gui.py:399 msgid "_None" msgstr "" #: ../gui.py:400 msgid "Atom _Index" msgstr "" #: ../gui.py:401 msgid "_Magnetic Moments" msgstr "" #: ../gui.py:402 msgid "_Element Symbol" msgstr "" #: ../gui.py:411 #, python-format msgid "building menus failed: %s" msgstr "" #: ../gui.py:686 ../gui.py:1092 ../gui.py:1152 msgid "Open ..." msgstr "" #: ../gui.py:690 ../gui.py:1095 msgid "<>" msgstr "" #: ../gui.py:823 msgid "Add atoms" msgstr "" #: ../gui.py:826 msgid "Paste" msgstr "" #: ../gui.py:832 msgid "Insert atom or molecule" msgstr "" #: ../gui.py:833 ../gui.py:959 msgid "Tag" msgstr "" #: ../gui.py:834 ../gui.py:960 msgid "Moment" msgstr "" #: ../gui.py:835 msgid "Position" msgstr "" #: ../gui.py:860 msgid "_Load molecule" msgstr "" #: ../gui.py:864 ../gui.py:975 msgid "_OK" msgstr "" #: ../gui.py:868 ../gui.py:979 msgid "_Cancel" msgstr "" #: ../gui.py:952 msgid "Modify" msgstr "" #: ../gui.py:958 msgid "Atom" msgstr "" #: ../gui.py:1003 msgid "Confirmation" msgstr "" #: ../gui.py:1007 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "" msgstr[1] "" #: ../gui.py:1014 msgid "Cancel" msgstr "" #: ../gui.py:1100 msgid "Automatic" msgstr "" #: ../gui.py:1101 msgid "Dacapo netCDF output file" msgstr "" #: ../gui.py:1102 msgid "Virtual Nano Lab file" msgstr "" #: ../gui.py:1103 msgid "ASE pickle trajectory" msgstr "" #: ../gui.py:1104 msgid "ASE bundle trajectory" msgstr "" #: ../gui.py:1105 msgid "GPAW text output" msgstr "" #: ../gui.py:1106 msgid "CUBE file" msgstr "" #: ../gui.py:1107 msgid "XCrySDen Structure File" msgstr "" #: ../gui.py:1108 msgid "Dacapo text output" msgstr "" #: ../gui.py:1109 msgid "XYZ-file" msgstr "" #: ../gui.py:1110 msgid "VASP POSCAR/CONTCAR file" msgstr "" #: ../gui.py:1111 msgid "VASP OUTCAR file" msgstr "" #: ../gui.py:1112 msgid "Protein Data Bank" msgstr "" #: ../gui.py:1113 msgid "CIF-file" msgstr "" #: ../gui.py:1114 msgid "FHI-aims geometry file" msgstr "" #: ../gui.py:1115 msgid "FHI-aims output file" msgstr "" #: ../gui.py:1116 msgid "TURBOMOLE coord file" msgstr "" #: ../gui.py:1117 msgid "exciting input" msgstr "" #: ../gui.py:1118 msgid "WIEN2k structure file" msgstr "" #: ../gui.py:1119 msgid "DftbPlus input file" msgstr "" #: ../gui.py:1120 msgid "ETSF format" msgstr "" #: ../gui.py:1121 msgid "CASTEP geom file" msgstr "" #: ../gui.py:1122 msgid "CASTEP output file" msgstr "" #: ../gui.py:1123 msgid "CASTEP trajectory file" msgstr "" #: ../gui.py:1124 msgid "DFTBPlus GEN format" msgstr "" #: ../gui.py:1130 msgid "File type:" msgstr "" #: ../gui.py:1253 msgid "Not implemented!" msgstr "" #: ../gui.py:1254 msgid "do you really need it?" msgstr "" #: ../minimize.py:21 msgid "Algorithm: " msgstr "" #: ../minimize.py:26 ../progress.py:67 msgid "Convergence criterion: Fmax = " msgstr "" #: ../minimize.py:31 ../progress.py:70 msgid "Max. number of steps: " msgstr "" #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "" #: ../minimize.py:55 msgid "Energy minimization" msgstr "" #: ../minimize.py:59 msgid "Minimize the energy with respect to the positions." msgstr "" #. Don't catch errors in the function. #. Display status message #: ../minimize.py:91 ../scaling.py:301 msgid "Running ..." msgstr "" #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "" #: ../minimize.py:114 ../scaling.py:352 msgid "Out of memory, consider using LBFGS instead" msgstr "" #. Update display to reflect succesful end of simulation. #: ../minimize.py:121 #, python-format msgid "Minimization completed in %i steps." msgstr "" #. self.connect('delete_event', self.exit2) #: ../movie.py:13 msgid "Movie" msgstr "" #: ../movie.py:15 msgid "Image number:" msgstr "" #: ../movie.py:37 msgid "Play" msgstr "" #: ../movie.py:39 msgid "Stop" msgstr "" #. TRANSLATORS: This function plays an animation forwards and backwards #. alternatingly, e.g. for displaying vibrational movement #: ../movie.py:43 msgid "Rock" msgstr "" #: ../movie.py:59 msgid " Frame rate: " msgstr "" #: ../movie.py:60 msgid " Skip frames: " msgstr "" #: ../nanoparticle.py:20 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:27 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:84 msgid "Face centered cubic (fcc)" msgstr "" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "" #: ../nanoparticle.py:131 msgid "Get structure" msgstr "" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "" #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "" #: ../nanoparticle.py:212 msgid "Add" msgstr "" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "" #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:196 msgid "Number of atoms: " msgstr "" #: ../nanoparticle.py:234 msgid "Volume: " msgstr "" #: ../nanoparticle.py:239 msgid "ų" msgstr "" #: ../nanoparticle.py:244 msgid "Rounding: If exact size is not possible, choose the size" msgstr "" #: ../nanoparticle.py:247 msgid "above " msgstr "" #: ../nanoparticle.py:248 msgid "below " msgstr "" #: ../nanoparticle.py:249 msgid "closest " msgstr "" #: ../nanoparticle.py:252 msgid "Smaller" msgstr "" #: ../nanoparticle.py:253 msgid "Larger" msgstr "" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr "" #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "" #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "" #: ../nanoparticle.py:333 msgid "Up" msgstr "" #: ../nanoparticle.py:338 msgid "Down" msgstr "" #: ../nanoparticle.py:343 msgid "Delete" msgstr "" #: ../nanoparticle.py:384 msgid "Surface energies (as energy/area, NOT per atom):" msgstr "" #: ../nanoparticle.py:390 msgid "Number of layers:" msgstr "" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "" #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "" #: ../nanotube.py:15 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:29 #, python-format msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: " "%(volume).3f Å3" msgstr "" #: ../nanotube.py:35 msgid "Nanotube" msgstr "" #. Choose the structure. #: ../nanotube.py:59 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:13 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:31 msgid "Render current view in povray ... " msgstr "" #: ../render.py:35 #, python-format msgid "Rendering %d atoms." msgstr "" #: ../render.py:40 msgid "Render constraints" msgstr "" #: ../render.py:43 msgid "Width" msgstr "" #: ../render.py:44 msgid " Height" msgstr "" #: ../render.py:51 msgid "Render unit cell" msgstr "" #: ../render.py:60 msgid "Line width" msgstr "" #: ../render.py:62 msgid "Angstrom " msgstr "" #: ../render.py:72 msgid "Set" msgstr "" #: ../render.py:74 msgid "Output basename: " msgstr "" #: ../render.py:76 msgid " Filename: " msgstr "" #: ../render.py:87 msgid " Default texture for atoms: " msgstr "" #: ../render.py:88 msgid " transparency: " msgstr "" #: ../render.py:89 msgid "Define atom selection for new texture:" msgstr "" #: ../render.py:91 msgid "Select" msgstr "" #: ../render.py:95 msgid "Create new texture from selection" msgstr "" #: ../render.py:97 msgid "Help on textures" msgstr "" #: ../render.py:110 msgid "Camera type: " msgstr "" #: ../render.py:111 msgid " Camera distance" msgstr "" #: ../render.py:112 msgid "Render current frame" msgstr "" #: ../render.py:116 #, python-format msgid "Render all %d frames" msgstr "" #: ../render.py:121 msgid "Transparent background" msgstr "" #: ../render.py:124 msgid "Run povray " msgstr "" #: ../render.py:127 msgid "Keep povray files " msgstr "" #: ../render.py:130 msgid "Show output window" msgstr "" #: ../render.py:211 msgid " transparency: " msgstr "" #: ../render.py:217 msgid "" "Can not create new texture! Must have some atoms selected to create a new " "material!" msgstr "" #: ../repeat.py:13 msgid "Repeat" msgstr "" #: ../repeat.py:20 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:150 msgid "2nd" msgstr "" #: ../scaling.py:151 msgid "3rd" msgstr "" #: ../scaling.py:155 msgid "Order of fit: " msgstr "" #. Update display to reflect cancellation of simulation. #: ../scaling.py:348 msgid "Calculation CANCELLED." msgstr "" #. Update display to reflect succesful end of simulation. #: ../scaling.py:359 msgid "Calculation completed." msgstr "" #: ../scaling.py:382 msgid "No trustworthy minimum: Old configuration kept." msgstr "" #: ../scaling.py:422 #, python-format msgid "" "Insufficent data for a fit\n" "(only %i data points)\n" msgstr "" #: ../scaling.py:426 msgid "" "REVERTING TO 2ND ORDER FIT\n" "(only 3 data points)\n" "\n" msgstr "" #: ../scaling.py:442 msgid "No minimum found!" msgstr "" #: ../scaling.py:456 msgid "" "\n" "WARNING: Minimum is outside interval\n" msgstr "" #: ../scaling.py:457 msgid "It is UNRELIABLE!\n" msgstr "" #: ../settings.py:15 msgid "Constraints:" msgstr "" #: ../settings.py:18 msgid "release" msgstr "" #: ../settings.py:22 msgid "Constrain immobile atoms" msgstr "" #: ../settings.py:24 msgid "Clear all constraints" msgstr "" #: ../settings.py:30 msgid "Visibility:" msgstr "" #: ../settings.py:31 msgid "Hide" msgstr "" #: ../settings.py:33 msgid "show" msgstr "" #: ../settings.py:37 msgid "View all atoms" msgstr "" #: ../settings.py:43 msgid "Miscellaneous:" msgstr "" #: ../settings.py:46 msgid "Scale atomic radii:" msgstr "" #. A close button #: ../settings.py:51 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:54 ../widgets.py:82 msgid "Help" msgstr "" #: ../widgets.py:99 msgid "Clear constraint" msgstr "" python-ase-3.9.1.4567/ase/gui/po/fr/0000775000175000017500000000000012553427753017063 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/fr/LC_MESSAGES/0000775000175000017500000000000012553427753020650 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/fr/LC_MESSAGES/ag.po0000664000175000017500000015121312553425527021577 0ustar jensjjensj00000000000000# French translations for PACKAGE package. # Copyright (C) 2012 CAMD # This file is distributed under the same license as the PACKAGE package. # Ask Hjorth Larsen , 2012. # msgid "" msgstr "" "Project-Id-Version: ase\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2012-09-10 15:12+0200\n" "PO-Revision-Date: 2012-07-23 16:21+0200\n" "Last-Translator: Ask Hjorth Larsen \n" "Language-Team: French\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ../ag.py:136 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:452 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:470 ../calculator.py:482 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "" #: ../calculator.py:473 msgid "You must set up the GPAW parameters" msgstr "" #: ../calculator.py:514 msgid "You must set up the FHI-aims parameters" msgstr "" #: ../calculator.py:528 msgid "You must set up the VASP parameters" msgstr "" #: ../calculator.py:552 #, python-format msgid "Element %(sym)s not allowed by the '%(name)s' calculator" msgstr "" #: ../calculator.py:559 msgid "Info" msgstr "" #: ../calculator.py:575 msgid "Lennard-Jones parameters" msgstr "" #: ../calculator.py:587 msgid "Specify the Lennard-Jones parameters here" msgstr "" #: ../calculator.py:590 msgid "Epsilon (eV):" msgstr "" #: ../calculator.py:594 msgid "Sigma (Å):" msgstr "" #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:598 msgid "Shift to make smooth at cutoff" msgstr "" #: ../calculator.py:679 msgid "GPAW parameters" msgstr "" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:694 ../calculator.py:983 ../calculator.py:1471 #, python-format msgid "%i atoms.\n" msgstr "" #: ../calculator.py:696 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "" #: ../calculator.py:698 msgid "Non-orthogonal unit cell:\n" msgstr "" #: ../calculator.py:708 ../calculator.py:999 ../calculator.py:1486 msgid "Exchange-correlation functional: " msgstr "" #. Grid spacing #: ../calculator.py:712 msgid "Grid spacing" msgstr "" #: ../calculator.py:716 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "" #: ../calculator.py:717 msgid "Grid points" msgstr "" #: ../calculator.py:726 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "" #: ../calculator.py:752 ../calculator.py:1014 ../calculator.py:1522 msgid "k-points k = (" msgstr "" #: ../calculator.py:756 ../calculator.py:1018 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "" #. Spin polarized #: ../calculator.py:761 ../calculator.py:1484 msgid "Spin polarized" msgstr "" #: ../calculator.py:767 msgid "FD - Finite Difference (grid) mode" msgstr "" #: ../calculator.py:768 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "" #: ../calculator.py:771 msgid "Mode: " msgstr "" #: ../calculator.py:773 msgid "sz - Single Zeta" msgstr "" #: ../calculator.py:774 msgid "szp - Single Zeta polarized" msgstr "" #: ../calculator.py:775 msgid "dzp - Double Zeta polarized" msgstr "" #. dzp #: ../calculator.py:777 msgid "Basis functions: " msgstr "" #. Mixer #: ../calculator.py:783 msgid "Non-standard mixer parameters" msgstr "" #: ../calculator.py:979 msgid "FHI-aims parameters" msgstr "" #: ../calculator.py:986 msgid "Periodic geometry, unit cell is:\n" msgstr "" #: ../calculator.py:991 msgid "Non-periodic geometry.\n" msgstr "" #: ../calculator.py:998 msgid "Hirshfeld-based dispersion correction" msgstr "" #. Spin polarized, charge, relativity #: ../calculator.py:1024 msgid "Spin / initial moment " msgstr "" #: ../calculator.py:1042 msgid " Charge" msgstr "" #: ../calculator.py:1044 msgid " Relativity" msgstr "" #: ../calculator.py:1046 msgid " Threshold" msgstr "" #. self-consistency criteria #: ../calculator.py:1051 msgid "Self-consistency convergence:" msgstr "" #: ../calculator.py:1064 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:1075 msgid "Energy: " msgstr "" #: ../calculator.py:1077 msgid " eV Sum of eigenvalues: " msgstr "" #: ../calculator.py:1079 ../calculator.py:1557 msgid " eV" msgstr "" #: ../calculator.py:1080 msgid "Electron density: " msgstr "" #: ../calculator.py:1082 msgid " Force convergence: " msgstr "" #: ../calculator.py:1084 msgid " eV/Ang " msgstr "" #: ../calculator.py:1097 ../calculator.py:1568 msgid "Additional keywords: " msgstr "" #. run command and species defaults: #: ../calculator.py:1111 msgid "FHI-aims execution command: " msgstr "" #: ../calculator.py:1113 ../calculator.py:1585 msgid "Directory for species defaults: " msgstr "" #: ../calculator.py:1125 ../calculator.py:1593 msgid "Set Defaults" msgstr "" #: ../calculator.py:1127 msgid "Import control.in" msgstr "" #: ../calculator.py:1129 msgid "Export control.in" msgstr "" #: ../calculator.py:1315 msgid "Export parameters ... " msgstr "" #: ../calculator.py:1335 msgid "Import control.in file ... " msgstr "" #: ../calculator.py:1391 ../calculator.py:1903 #, python-format msgid "" "Please use the facilities provided in this window to manipulate the keyword: " "%s!" msgstr "" #: ../calculator.py:1394 #, 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:1467 msgid "VASP parameters" msgstr "" #: ../calculator.py:1473 msgid "Periodic geometry, unit cell is: \n" msgstr "" #: ../calculator.py:1525 msgid ") Cutoff: " msgstr "" #: ../calculator.py:1526 msgid " Precision: " msgstr "" #: ../calculator.py:1528 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "" #: ../calculator.py:1544 msgid "Smearing: " msgstr "" #: ../calculator.py:1546 msgid " order: " msgstr "" #: ../calculator.py:1548 msgid " width: " msgstr "" #: ../calculator.py:1555 msgid "Self-consistency convergence: " msgstr "" #. run command and location of POTCAR files: #: ../calculator.py:1581 msgid "VASP execution command: " msgstr "" #: ../calculator.py:1595 msgid "Import VASP files" msgstr "" #: ../calculator.py:1597 msgid "Export VASP files" msgstr "" #: ../calculator.py:1806 msgid "WARNING: cutoff energy is lower than recommended minimum!" msgstr "" #: ../calculator.py:1858 msgid "Import VASP input files: choose directory ... " msgstr "" #: ../calculator.py:1873 msgid "Export VASP input files: choose directory ... " msgstr "" #: ../calculator.py:1906 #, 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:90 msgid "Constraints" msgstr "" #: ../constraints.py:15 ../constraints.py:18 ../settings.py:17 #: ../widgets.py:92 ../widgets.py:95 msgid "Constrain" msgstr "" #: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:93 msgid " selected atoms" msgstr "" #: ../constraints.py:19 ../widgets.py:96 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:100 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 ../graphene.py:27 #, 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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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: ase-gui window python object\n" " img:\tadvanced: ase-gui 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:16 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:33 ../gui.py:316 msgid "Graphene" msgstr "" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "" #: ../graphene.py:42 msgid "Infinite sheet" msgstr "" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "" #: ../graphene.py:53 msgid "zigzag" msgstr "" #: ../graphene.py:53 msgid "armchair" msgstr "" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 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:90 msgid "Width: " msgstr "" #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr "" #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "" #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr "" #: ../graphene.py:194 msgid "Please specify a consistent set of atoms. " msgstr "" #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../pybutton.py:49 ../surfaceslab.py:249 msgid "You have not (yet) specified a consistent set of parameters." msgstr "" #: ../graphs.py:9 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" #: ../graphs.py:52 ../graphs.py:55 msgid "Plot" msgstr "" #: ../graphs.py:60 msgid "clear" msgstr "" #: ../graphs.py:114 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:175 msgid "_File" msgstr "" #: ../gui.py:176 msgid "_Edit" msgstr "" #: ../gui.py:177 msgid "_View" msgstr "" #: ../gui.py:178 msgid "_Tools" msgstr "" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:180 msgid "_Setup" msgstr "" #: ../gui.py:181 msgid "_Calculate" msgstr "" #: ../gui.py:182 msgid "_Help" msgstr "" #: ../gui.py:183 msgid "_Open" msgstr "" #: ../gui.py:184 msgid "Create a new file" msgstr "" #: ../gui.py:186 msgid "_New" msgstr "" #: ../gui.py:187 msgid "New ase.gui window" msgstr "" #: ../gui.py:189 msgid "_Save" msgstr "" #: ../gui.py:190 msgid "Save current file" msgstr "" #: ../gui.py:192 msgid "_Quit" msgstr "" #: ../gui.py:193 msgid "Quit" msgstr "" #: ../gui.py:195 msgid "Select _all" msgstr "" #: ../gui.py:198 msgid "_Invert selection" msgstr "" #: ../gui.py:201 msgid "Select _constrained atoms" msgstr "" #: ../gui.py:204 msgid "Select _immobile atoms" msgstr "" #: ../gui.py:207 msgid "_Copy" msgstr "" #: ../gui.py:208 msgid "Copy current selection and its orientation to clipboard" msgstr "" #: ../gui.py:210 msgid "_Paste" msgstr "" #: ../gui.py:211 msgid "Insert current clipboard selection" msgstr "" #: ../gui.py:213 msgid "_Modify" msgstr "" #: ../gui.py:214 msgid "Change tags, moments and atom types of the selected atoms" msgstr "" #: ../gui.py:216 msgid "_Add atoms" msgstr "" #: ../gui.py:217 msgid "Insert or import atoms and molecules" msgstr "" #: ../gui.py:219 msgid "_Delete selected atoms" msgstr "" #: ../gui.py:220 msgid "Delete the selected atoms" msgstr "" #: ../gui.py:222 msgid "_First image" msgstr "" #: ../gui.py:225 msgid "_Previous image" msgstr "" #: ../gui.py:228 msgid "_Next image" msgstr "" #: ../gui.py:231 msgid "_Last image" msgstr "" #: ../gui.py:234 msgid "Show _Labels" msgstr "" #: ../gui.py:235 msgid "Hide selected atoms" msgstr "" #: ../gui.py:238 msgid "Show selected atoms" msgstr "" #: ../gui.py:241 msgid "Quick Info ..." msgstr "" #: ../gui.py:244 msgid "Repeat ..." msgstr "" #: ../gui.py:247 msgid "Rotate ..." msgstr "" #: ../gui.py:250 msgid "Colors ..." msgstr "" #. TRANSLATORS: verb #: ../gui.py:253 msgid "Focus" msgstr "" #: ../gui.py:256 msgid "Zoom in" msgstr "" #: ../gui.py:259 msgid "Zoom out" msgstr "" #: ../gui.py:262 msgid "Reset View" msgstr "" #: ../gui.py:265 msgid "Settings ..." msgstr "" #: ../gui.py:268 msgid "VMD" msgstr "" #: ../gui.py:271 msgid "RasMol" msgstr "" #: ../gui.py:274 msgid "xmakemol" msgstr "" #: ../gui.py:277 msgid "avogadro" msgstr "" #: ../gui.py:280 msgid "Graphs ..." msgstr "" #: ../gui.py:283 msgid "Movie ..." msgstr "" #: ../gui.py:286 msgid "Expert mode ..." msgstr "" #: ../gui.py:289 msgid "Constraints ..." msgstr "" #: ../gui.py:292 msgid "Render scene ..." msgstr "" #: ../gui.py:295 msgid "DFT ..." msgstr "" #: ../gui.py:298 msgid "NE_B" msgstr "" #: ../gui.py:301 msgid "B_ulk Modulus" msgstr "" #: ../gui.py:304 msgid "_Bulk Crystal" msgstr "" #: ../gui.py:305 msgid "Create a bulk crystal with arbitrary orientation" msgstr "" #: ../gui.py:307 msgid "_Surface slab" msgstr "" #: ../gui.py:308 msgid "Create the most common surfaces" msgstr "" #: ../gui.py:310 msgid "_Nanoparticle" msgstr "" #: ../gui.py:311 msgid "Create a crystalline nanoparticle" msgstr "" #: ../gui.py:313 msgid "Nano_tube" msgstr "" #: ../gui.py:314 msgid "Create a nanotube" msgstr "" #: ../gui.py:317 msgid "Create a graphene sheet or nanoribbon" msgstr "" #: ../gui.py:319 msgid "Set _Calculator" msgstr "" #: ../gui.py:320 msgid "Set a calculator used in all calculation modules" msgstr "" #: ../gui.py:322 msgid "_Energy and Forces" msgstr "" #: ../gui.py:323 msgid "Calculate energy and forces" msgstr "" #: ../gui.py:325 msgid "Energy _Minimization" msgstr "" #: ../gui.py:326 msgid "Minimize the energy" msgstr "" #: ../gui.py:328 msgid "Scale system" msgstr "" #: ../gui.py:329 msgid "Deform system by scaling it" msgstr "" #: ../gui.py:331 msgid "_About" msgstr "" #: ../gui.py:334 msgid "Webpage ..." msgstr "" #: ../gui.py:335 msgid "Debug ..." msgstr "" #: ../gui.py:337 msgid "Show _unit cell" msgstr "" #: ../gui.py:341 msgid "Show _axes" msgstr "" #: ../gui.py:345 msgid "Show _bonds" msgstr "" #: ../gui.py:349 msgid "Show _velocities" msgstr "" #: ../gui.py:353 msgid "Show _forces" msgstr "" #: ../gui.py:357 msgid "_Move atoms" msgstr "" #: ../gui.py:361 msgid "_Rotate atoms" msgstr "" #: ../gui.py:365 msgid "Orien_t atoms" msgstr "" #: ../gui.py:371 msgid "_None" msgstr "" #: ../gui.py:372 msgid "Atom _Index" msgstr "" #: ../gui.py:373 msgid "_Magnetic Moments" msgstr "" #: ../gui.py:374 msgid "_Element Symbol" msgstr "" #: ../gui.py:383 #, python-format msgid "building menus failed: %s" msgstr "" #: ../gui.py:658 ../gui.py:1064 ../gui.py:1124 msgid "Open ..." msgstr "" #: ../gui.py:662 ../gui.py:1067 msgid "<>" msgstr "" #: ../gui.py:795 msgid "Add atoms" msgstr "" #: ../gui.py:798 msgid "Paste" msgstr "" #: ../gui.py:804 msgid "Insert atom or molecule" msgstr "" #: ../gui.py:805 ../gui.py:931 msgid "Tag" msgstr "" #: ../gui.py:806 ../gui.py:932 msgid "Moment" msgstr "" #: ../gui.py:807 msgid "Position" msgstr "" #: ../gui.py:832 msgid "_Load molecule" msgstr "" #: ../gui.py:836 ../gui.py:947 msgid "_OK" msgstr "" #: ../gui.py:840 ../gui.py:951 msgid "_Cancel" msgstr "" #: ../gui.py:924 msgid "Modify" msgstr "" #: ../gui.py:930 msgid "Atom" msgstr "" #: ../gui.py:975 msgid "Confirmation" msgstr "" #: ../gui.py:979 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "" msgstr[1] "" #: ../gui.py:986 msgid "Cancel" msgstr "" #: ../gui.py:1072 ../gui.py:1154 msgid "Automatic" msgstr "" #: ../gui.py:1073 msgid "Dacapo netCDF output file" msgstr "" #: ../gui.py:1074 msgid "Virtual Nano Lab file" msgstr "" #: ../gui.py:1075 msgid "ASE pickle trajectory" msgstr "" #: ../gui.py:1076 ../gui.py:1167 msgid "ASE bundle trajectory" msgstr "" #: ../gui.py:1077 msgid "GPAW text output" msgstr "" #: ../gui.py:1078 msgid "CUBE file" msgstr "" #: ../gui.py:1079 msgid "XCrySDen Structure File" msgstr "" #: ../gui.py:1080 msgid "Dacapo text output" msgstr "" #: ../gui.py:1081 msgid "XYZ-file" msgstr "" #: ../gui.py:1082 msgid "VASP POSCAR/CONTCAR file" msgstr "" #: ../gui.py:1083 msgid "VASP OUTCAR file" msgstr "" #: ../gui.py:1084 msgid "Protein Data Bank" msgstr "" #: ../gui.py:1085 msgid "CIF-file" msgstr "" #: ../gui.py:1086 msgid "FHI-aims geometry file" msgstr "" #: ../gui.py:1087 msgid "FHI-aims output file" msgstr "" #: ../gui.py:1088 msgid "TURBOMOLE coord file" msgstr "" #: ../gui.py:1089 msgid "exciting input" msgstr "" #: ../gui.py:1090 msgid "WIEN2k structure file" msgstr "" #: ../gui.py:1091 msgid "DftbPlus input file" msgstr "" #: ../gui.py:1092 msgid "ETSF format" msgstr "" #: ../gui.py:1093 ../gui.py:1165 msgid "CASTEP geom file" msgstr "" #: ../gui.py:1094 msgid "CASTEP output file" msgstr "" #: ../gui.py:1095 msgid "CASTEP trajectory file" msgstr "" #: ../gui.py:1096 msgid "DFTBPlus GEN format" msgstr "" #: ../gui.py:1102 msgid "File type:" msgstr "" #: ../gui.py:1142 msgid "Save ..." msgstr "" #: ../gui.py:1155 msgid "XYZ file" msgstr "" #: ../gui.py:1156 msgid "ASE trajectory" msgstr "" #: ../gui.py:1157 msgid "PDB file" msgstr "" #: ../gui.py:1158 msgid "Gaussian cube file" msgstr "" #: ../gui.py:1159 msgid "Python script" msgstr "" #: ../gui.py:1160 msgid "VNL file" msgstr "" #: ../gui.py:1161 msgid "Portable Network Graphics" msgstr "" #: ../gui.py:1162 msgid "Persistence of Vision" msgstr "" #: ../gui.py:1163 msgid "Encapsulated PostScript" msgstr "" #: ../gui.py:1164 msgid "FHI-aims geometry input" msgstr "" #: ../gui.py:1166 msgid "VASP geometry input" msgstr "" #: ../gui.py:1168 msgid "cif file" msgstr "" #: ../gui.py:1190 #, python-format msgid "Save current image only (#%d)" msgstr "" #: ../gui.py:1194 msgid "Slice: " msgstr "" #: ../gui.py:1195 msgid "Help for slice ..." msgstr "" #: ../gui.py:1207 msgid "ase-gui INTERNAL ERROR: strange response in Save," msgstr "" #: ../gui.py:1226 msgid "Unknown output format!" msgstr "" #: ../gui.py:1227 #, python-format msgid "Use one of: %s" msgstr "" #: ../gui.py:1332 msgid "Not implemented!" msgstr "" #: ../gui.py:1333 msgid "do you really need it?" msgstr "" #: ../minimize.py:21 msgid "Algorithm: " msgstr "" #: ../minimize.py:26 ../progress.py:67 msgid "Convergence criterion: Fmax = " msgstr "" #: ../minimize.py:31 ../progress.py:70 msgid "Max. number of steps: " msgstr "" #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "" #: ../minimize.py:55 msgid "Energy minimization" msgstr "" #: ../minimize.py:59 msgid "Minimize the energy with respect to the positions." msgstr "" #. Don't catch errors in the function. #. Display status message #: ../minimize.py:91 ../scaling.py:299 msgid "Running ..." msgstr "" #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "" #: ../minimize.py:114 ../scaling.py:350 msgid "Out of memory, consider using LBFGS instead" msgstr "" #. Update display to reflect succesful end of simulation. #: ../minimize.py:121 #, 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:20 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:27 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:84 msgid "Face centered cubic (fcc)" msgstr "" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "" #: ../nanoparticle.py:131 msgid "Get structure" msgstr "" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "" #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "" #: ../nanoparticle.py:212 msgid "Add" msgstr "" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "" #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:196 msgid "Number of atoms: " msgstr "" #: ../nanoparticle.py:234 msgid "Volume: " msgstr "" #: ../nanoparticle.py:239 msgid "ų" msgstr "" #: ../nanoparticle.py:244 msgid "Rounding: If exact size is not possible, choose the size" msgstr "" #: ../nanoparticle.py:247 msgid "above " msgstr "" #: ../nanoparticle.py:248 msgid "below " msgstr "" #: ../nanoparticle.py:249 msgid "closest " msgstr "" #: ../nanoparticle.py:252 msgid "Smaller" msgstr "" #: ../nanoparticle.py:253 msgid "Larger" msgstr "" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr "" #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "" #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "" #: ../nanoparticle.py:333 msgid "Up" msgstr "" #: ../nanoparticle.py:338 msgid "Down" msgstr "" #: ../nanoparticle.py:343 msgid "Delete" msgstr "" #: ../nanoparticle.py:384 msgid "Surface energies (as energy/area, NOT per atom):" msgstr "" #: ../nanoparticle.py:390 msgid "Number of layers:" msgstr "" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "" #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "" #: ../nanotube.py:15 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:29 #, python-format msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: %" "(volume).3f Å3" msgstr "" #: ../nanotube.py:35 msgid "Nanotube" msgstr "" #. Choose the structure. #: ../nanotube.py:59 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:81 msgid "Help" msgstr "" #: ../widgets.py:98 msgid "Clear constraint" msgstr "" python-ase-3.9.1.4567/ase/gui/po/it_IT/0000775000175000017500000000000012553427753017464 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/it_IT/LC_MESSAGES/0000775000175000017500000000000012553427753021251 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/po/it_IT/LC_MESSAGES/ag.po0000664000175000017500000015126512553425527022207 0ustar jensjjensj00000000000000# Italian translations for ASE package # Traduzioni italiane per il pacchetto ASE # Copyright (C) 2012 CAMD # This file is distributed under the same license as the ASE package. # Ivano Castelli , 2012. # msgid "" msgstr "" "Project-Id-Version: ase-3.5.2\n" "Report-Msgid-Bugs-To: ase-developers@listserv.fysik.dtu.dk\n" "POT-Creation-Date: 2012-09-10 15:12+0200\n" "PO-Revision-Date: 2012-02-15 15:24+0100\n" "Last-Translator: Ivano Castelli \n" "Language-Team: Italian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../ag.py:136 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:452 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:470 ../calculator.py:482 msgid "GPAW is not installed. (Failed to import gpaw)" msgstr "" #: ../calculator.py:473 msgid "You must set up the GPAW parameters" msgstr "" #: ../calculator.py:514 msgid "You must set up the FHI-aims parameters" msgstr "" #: ../calculator.py:528 msgid "You must set up the VASP parameters" msgstr "" #: ../calculator.py:552 #, python-format msgid "Element %(sym)s not allowed by the '%(name)s' calculator" msgstr "" #: ../calculator.py:559 msgid "Info" msgstr "" #: ../calculator.py:575 msgid "Lennard-Jones parameters" msgstr "" #: ../calculator.py:587 msgid "Specify the Lennard-Jones parameters here" msgstr "" #: ../calculator.py:590 msgid "Epsilon (eV):" msgstr "" #: ../calculator.py:594 msgid "Sigma (Å):" msgstr "" #. TRANSLATORS: Shift roughly means adjust (about a potential) #: ../calculator.py:598 msgid "Shift to make smooth at cutoff" msgstr "" #: ../calculator.py:679 msgid "GPAW parameters" msgstr "" #. label = gtk.Label("Specify the GPAW parameters here") #. pack(vbox, [label]) #. Print some info #: ../calculator.py:694 ../calculator.py:983 ../calculator.py:1471 #, python-format msgid "%i atoms.\n" msgstr "" #: ../calculator.py:696 #, python-format msgid "Orthogonal unit cell: %.2f x %.2f x %.2f Å." msgstr "" #: ../calculator.py:698 msgid "Non-orthogonal unit cell:\n" msgstr "" #: ../calculator.py:708 ../calculator.py:999 ../calculator.py:1486 msgid "Exchange-correlation functional: " msgstr "" #. Grid spacing #: ../calculator.py:712 msgid "Grid spacing" msgstr "" #: ../calculator.py:716 ../graphene.py:67 ../graphene.py:78 ../graphene.py:101 #: ../nanotube.py:49 ../surfaceslab.py:97 msgid "Å" msgstr "" #: ../calculator.py:717 msgid "Grid points" msgstr "" #: ../calculator.py:726 #, python-format msgid "heff = (%.3f, %.3f, %.3f) Å" msgstr "" #: ../calculator.py:752 ../calculator.py:1014 ../calculator.py:1522 msgid "k-points k = (" msgstr "" #: ../calculator.py:756 ../calculator.py:1018 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å" msgstr "" #. Spin polarized #: ../calculator.py:761 ../calculator.py:1484 msgid "Spin polarized" msgstr "" #: ../calculator.py:767 msgid "FD - Finite Difference (grid) mode" msgstr "" #: ../calculator.py:768 msgid "LCAO - Linear Combination of Atomic Orbitals" msgstr "" #: ../calculator.py:771 msgid "Mode: " msgstr "" #: ../calculator.py:773 msgid "sz - Single Zeta" msgstr "" #: ../calculator.py:774 msgid "szp - Single Zeta polarized" msgstr "" #: ../calculator.py:775 msgid "dzp - Double Zeta polarized" msgstr "" #. dzp #: ../calculator.py:777 msgid "Basis functions: " msgstr "" #. Mixer #: ../calculator.py:783 msgid "Non-standard mixer parameters" msgstr "" #: ../calculator.py:979 msgid "FHI-aims parameters" msgstr "" #: ../calculator.py:986 msgid "Periodic geometry, unit cell is:\n" msgstr "" #: ../calculator.py:991 msgid "Non-periodic geometry.\n" msgstr "" #: ../calculator.py:998 msgid "Hirshfeld-based dispersion correction" msgstr "" #. Spin polarized, charge, relativity #: ../calculator.py:1024 msgid "Spin / initial moment " msgstr "" #: ../calculator.py:1042 msgid " Charge" msgstr "" #: ../calculator.py:1044 msgid " Relativity" msgstr "" #: ../calculator.py:1046 msgid " Threshold" msgstr "" #. self-consistency criteria #: ../calculator.py:1051 msgid "Self-consistency convergence:" msgstr "" #: ../calculator.py:1064 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:1075 msgid "Energy: " msgstr "" #: ../calculator.py:1077 msgid " eV Sum of eigenvalues: " msgstr "" #: ../calculator.py:1079 ../calculator.py:1557 msgid " eV" msgstr "" #: ../calculator.py:1080 msgid "Electron density: " msgstr "" #: ../calculator.py:1082 msgid " Force convergence: " msgstr "" #: ../calculator.py:1084 msgid " eV/Ang " msgstr "" #: ../calculator.py:1097 ../calculator.py:1568 msgid "Additional keywords: " msgstr "" #. run command and species defaults: #: ../calculator.py:1111 msgid "FHI-aims execution command: " msgstr "" #: ../calculator.py:1113 ../calculator.py:1585 msgid "Directory for species defaults: " msgstr "" #: ../calculator.py:1125 ../calculator.py:1593 msgid "Set Defaults" msgstr "" #: ../calculator.py:1127 msgid "Import control.in" msgstr "" #: ../calculator.py:1129 msgid "Export control.in" msgstr "" #: ../calculator.py:1315 msgid "Export parameters ... " msgstr "" #: ../calculator.py:1335 msgid "Import control.in file ... " msgstr "" #: ../calculator.py:1391 ../calculator.py:1903 #, python-format msgid "" "Please use the facilities provided in this window to manipulate the keyword: " "%s!" msgstr "" #: ../calculator.py:1394 #, 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:1467 msgid "VASP parameters" msgstr "" #: ../calculator.py:1473 msgid "Periodic geometry, unit cell is: \n" msgstr "" #: ../calculator.py:1525 msgid ") Cutoff: " msgstr "" #: ../calculator.py:1526 msgid " Precision: " msgstr "" #: ../calculator.py:1528 #, python-format msgid "k-points x size: (%.1f, %.1f, %.1f) Å " msgstr "" #: ../calculator.py:1544 msgid "Smearing: " msgstr "" #: ../calculator.py:1546 msgid " order: " msgstr "" #: ../calculator.py:1548 msgid " width: " msgstr "" #: ../calculator.py:1555 msgid "Self-consistency convergence: " msgstr "" #. run command and location of POTCAR files: #: ../calculator.py:1581 msgid "VASP execution command: " msgstr "" #: ../calculator.py:1595 msgid "Import VASP files" msgstr "" #: ../calculator.py:1597 msgid "Export VASP files" msgstr "" #: ../calculator.py:1806 msgid "WARNING: cutoff energy is lower than recommended minimum!" msgstr "" #: ../calculator.py:1858 msgid "Import VASP input files: choose directory ... " msgstr "" #: ../calculator.py:1873 msgid "Export VASP input files: choose directory ... " msgstr "" #: ../calculator.py:1906 #, 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:90 msgid "Constraints" msgstr "" #: ../constraints.py:15 ../constraints.py:18 ../settings.py:17 #: ../widgets.py:92 ../widgets.py:95 msgid "Constrain" msgstr "" #: ../constraints.py:16 ../settings.py:20 ../settings.py:35 ../widgets.py:93 msgid " selected atoms" msgstr "" #: ../constraints.py:19 ../widgets.py:96 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:100 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 ../graphene.py:27 #, 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:254 ../nanoparticle.py:614 #: ../nanotube.py:160 ../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: ase-gui window python object\n" " img:\tadvanced: ase-gui 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:16 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:33 ../gui.py:316 msgid "Graphene" msgstr "" #. Choose structure #. The structure and lattice constant #. Choose the surface structure #: ../graphene.py:40 ../nanoparticle.py:139 ../surfaceslab.py:78 msgid "Structure: " msgstr "" #: ../graphene.py:42 msgid "Infinite sheet" msgstr "" #: ../graphene.py:42 msgid "Unsaturated ribbon" msgstr "" #: ../graphene.py:43 msgid "Saturated ribbon" msgstr "" #. Orientation #: ../graphene.py:50 msgid "Orientation: " msgstr "" #: ../graphene.py:53 msgid "zigzag" msgstr "" #: ../graphene.py:53 msgid "armchair" msgstr "" #: ../graphene.py:66 ../graphene.py:77 ../nanotube.py:48 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:90 msgid "Width: " msgstr "" #: ../graphene.py:91 ../nanotube.py:67 msgid " Length: " msgstr "" #. Vacuum #: ../graphene.py:99 msgid "Vacuum: " msgstr "" #: ../graphene.py:148 ../nanotube.py:107 ../setupwindow.py:32 msgid " No element specified!" msgstr "" #: ../graphene.py:194 msgid "Please specify a consistent set of atoms. " msgstr "" #: ../graphene.py:255 ../nanoparticle.py:615 ../nanotube.py:161 #: ../pybutton.py:49 ../surfaceslab.py:249 msgid "You have not (yet) specified a consistent set of parameters." msgstr "" #: ../graphs.py:9 msgid "" "Help for plot ...\n" "\n" "Symbols:\n" "e:\t\t\t\ttotal energy\n" "epot:\t\t\tpotential energy\n" "ekin:\t\t\tkinetic energy\n" "fmax:\t\t\tmaximum force\n" "fave:\t\t\taverage force\n" "R[n,0-2]:\t\t\tposition of atom number n\n" "d(n1,n2):\t\t\tdistance between two atoms " "n1 and n2\n" "i:\t\t\t\tcurrent image number\n" "E[i]:\t\t\t\tenergy of image number i\n" "F[n,0-2]:\t\t\tforce on atom number n\n" "V[n,0-2]:\t\t\tvelocity of atom number n\n" "M[n]:\t\t\tmagnetic moment of atom number n\n" "A[0-2,0-2]:\t\tunit-cell basis vectors\n" "s:\t\t\t\tpath length\n" "a(n1,n2,n3):\t\tangle between atoms n1, n2 and n3, centered on n2\n" "dih(n1,n2,n3,n4):\tdihedral angle between n1, " "n2, n3 and n4\n" "T:\t\t\t\ttemperature (K)" msgstr "" #: ../graphs.py:52 ../graphs.py:55 msgid "Plot" msgstr "" #: ../graphs.py:60 msgid "clear" msgstr "" #: ../graphs.py:114 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:175 msgid "_File" msgstr "" #: ../gui.py:176 msgid "_Edit" msgstr "_Modifica" #: ../gui.py:177 msgid "_View" msgstr "" #: ../gui.py:178 msgid "_Tools" msgstr "" #. TRANSLATORS: Set up (i.e. build) surfaces, nanoparticles, ... #: ../gui.py:180 msgid "_Setup" msgstr "" #: ../gui.py:181 msgid "_Calculate" msgstr "" #: ../gui.py:182 msgid "_Help" msgstr "" #: ../gui.py:183 msgid "_Open" msgstr "" #: ../gui.py:184 msgid "Create a new file" msgstr "" #: ../gui.py:186 msgid "_New" msgstr "" #: ../gui.py:187 msgid "New ase.gui window" msgstr "" #: ../gui.py:189 msgid "_Save" msgstr "" #: ../gui.py:190 msgid "Save current file" msgstr "" #: ../gui.py:192 msgid "_Quit" msgstr "" #: ../gui.py:193 msgid "Quit" msgstr "" #: ../gui.py:195 msgid "Select _all" msgstr "" #: ../gui.py:198 msgid "_Invert selection" msgstr "" #: ../gui.py:201 msgid "Select _constrained atoms" msgstr "" #: ../gui.py:204 msgid "Select _immobile atoms" msgstr "" #: ../gui.py:207 msgid "_Copy" msgstr "" #: ../gui.py:208 msgid "Copy current selection and its orientation to clipboard" msgstr "" #: ../gui.py:210 msgid "_Paste" msgstr "" #: ../gui.py:211 msgid "Insert current clipboard selection" msgstr "" #: ../gui.py:213 msgid "_Modify" msgstr "" #: ../gui.py:214 msgid "Change tags, moments and atom types of the selected atoms" msgstr "" #: ../gui.py:216 msgid "_Add atoms" msgstr "" #: ../gui.py:217 msgid "Insert or import atoms and molecules" msgstr "" #: ../gui.py:219 msgid "_Delete selected atoms" msgstr "" #: ../gui.py:220 msgid "Delete the selected atoms" msgstr "" #: ../gui.py:222 msgid "_First image" msgstr "" #: ../gui.py:225 msgid "_Previous image" msgstr "" #: ../gui.py:228 msgid "_Next image" msgstr "" #: ../gui.py:231 msgid "_Last image" msgstr "" #: ../gui.py:234 msgid "Show _Labels" msgstr "" #: ../gui.py:235 msgid "Hide selected atoms" msgstr "" #: ../gui.py:238 msgid "Show selected atoms" msgstr "" #: ../gui.py:241 msgid "Quick Info ..." msgstr "" #: ../gui.py:244 msgid "Repeat ..." msgstr "" #: ../gui.py:247 msgid "Rotate ..." msgstr "" #: ../gui.py:250 msgid "Colors ..." msgstr "" #. TRANSLATORS: verb #: ../gui.py:253 msgid "Focus" msgstr "" #: ../gui.py:256 msgid "Zoom in" msgstr "" #: ../gui.py:259 msgid "Zoom out" msgstr "" #: ../gui.py:262 msgid "Reset View" msgstr "" #: ../gui.py:265 msgid "Settings ..." msgstr "" #: ../gui.py:268 msgid "VMD" msgstr "" #: ../gui.py:271 msgid "RasMol" msgstr "" #: ../gui.py:274 msgid "xmakemol" msgstr "" #: ../gui.py:277 msgid "avogadro" msgstr "" #: ../gui.py:280 msgid "Graphs ..." msgstr "" #: ../gui.py:283 msgid "Movie ..." msgstr "" #: ../gui.py:286 msgid "Expert mode ..." msgstr "" #: ../gui.py:289 msgid "Constraints ..." msgstr "" #: ../gui.py:292 msgid "Render scene ..." msgstr "" #: ../gui.py:295 msgid "DFT ..." msgstr "" #: ../gui.py:298 msgid "NE_B" msgstr "" #: ../gui.py:301 msgid "B_ulk Modulus" msgstr "" #: ../gui.py:304 msgid "_Bulk Crystal" msgstr "" #: ../gui.py:305 msgid "Create a bulk crystal with arbitrary orientation" msgstr "" #: ../gui.py:307 msgid "_Surface slab" msgstr "" #: ../gui.py:308 msgid "Create the most common surfaces" msgstr "" #: ../gui.py:310 msgid "_Nanoparticle" msgstr "" #: ../gui.py:311 msgid "Create a crystalline nanoparticle" msgstr "" #: ../gui.py:313 msgid "Nano_tube" msgstr "" #: ../gui.py:314 msgid "Create a nanotube" msgstr "" #: ../gui.py:317 msgid "Create a graphene sheet or nanoribbon" msgstr "" #: ../gui.py:319 msgid "Set _Calculator" msgstr "" #: ../gui.py:320 msgid "Set a calculator used in all calculation modules" msgstr "" #: ../gui.py:322 msgid "_Energy and Forces" msgstr "" #: ../gui.py:323 msgid "Calculate energy and forces" msgstr "" #: ../gui.py:325 msgid "Energy _Minimization" msgstr "" #: ../gui.py:326 msgid "Minimize the energy" msgstr "" #: ../gui.py:328 msgid "Scale system" msgstr "" #: ../gui.py:329 msgid "Deform system by scaling it" msgstr "" #: ../gui.py:331 msgid "_About" msgstr "" #: ../gui.py:334 msgid "Webpage ..." msgstr "" #: ../gui.py:335 msgid "Debug ..." msgstr "" #: ../gui.py:337 msgid "Show _unit cell" msgstr "" #: ../gui.py:341 msgid "Show _axes" msgstr "" #: ../gui.py:345 msgid "Show _bonds" msgstr "" #: ../gui.py:349 msgid "Show _velocities" msgstr "" #: ../gui.py:353 msgid "Show _forces" msgstr "" #: ../gui.py:357 msgid "_Move atoms" msgstr "" #: ../gui.py:361 msgid "_Rotate atoms" msgstr "" #: ../gui.py:365 msgid "Orien_t atoms" msgstr "" #: ../gui.py:371 msgid "_None" msgstr "" #: ../gui.py:372 msgid "Atom _Index" msgstr "" #: ../gui.py:373 msgid "_Magnetic Moments" msgstr "" #: ../gui.py:374 msgid "_Element Symbol" msgstr "" #: ../gui.py:383 #, python-format msgid "building menus failed: %s" msgstr "" #: ../gui.py:658 ../gui.py:1064 ../gui.py:1124 msgid "Open ..." msgstr "" #: ../gui.py:662 ../gui.py:1067 msgid "<>" msgstr "" #: ../gui.py:795 msgid "Add atoms" msgstr "" #: ../gui.py:798 msgid "Paste" msgstr "" #: ../gui.py:804 msgid "Insert atom or molecule" msgstr "" #: ../gui.py:805 ../gui.py:931 msgid "Tag" msgstr "" #: ../gui.py:806 ../gui.py:932 msgid "Moment" msgstr "" #: ../gui.py:807 msgid "Position" msgstr "" #: ../gui.py:832 msgid "_Load molecule" msgstr "" #: ../gui.py:836 ../gui.py:947 msgid "_OK" msgstr "" #: ../gui.py:840 ../gui.py:951 msgid "_Cancel" msgstr "" #: ../gui.py:924 msgid "Modify" msgstr "" #: ../gui.py:930 msgid "Atom" msgstr "" #: ../gui.py:975 msgid "Confirmation" msgstr "" #: ../gui.py:979 msgid "Delete selected atom?" msgid_plural "Delete selected atoms?" msgstr[0] "" msgstr[1] "" #: ../gui.py:986 msgid "Cancel" msgstr "" #: ../gui.py:1072 ../gui.py:1154 msgid "Automatic" msgstr "" #: ../gui.py:1073 msgid "Dacapo netCDF output file" msgstr "" #: ../gui.py:1074 msgid "Virtual Nano Lab file" msgstr "" #: ../gui.py:1075 msgid "ASE pickle trajectory" msgstr "" #: ../gui.py:1076 ../gui.py:1167 msgid "ASE bundle trajectory" msgstr "" #: ../gui.py:1077 msgid "GPAW text output" msgstr "" #: ../gui.py:1078 msgid "CUBE file" msgstr "" #: ../gui.py:1079 msgid "XCrySDen Structure File" msgstr "" #: ../gui.py:1080 msgid "Dacapo text output" msgstr "" #: ../gui.py:1081 msgid "XYZ-file" msgstr "" #: ../gui.py:1082 msgid "VASP POSCAR/CONTCAR file" msgstr "" #: ../gui.py:1083 msgid "VASP OUTCAR file" msgstr "" #: ../gui.py:1084 msgid "Protein Data Bank" msgstr "" #: ../gui.py:1085 msgid "CIF-file" msgstr "" #: ../gui.py:1086 msgid "FHI-aims geometry file" msgstr "" #: ../gui.py:1087 msgid "FHI-aims output file" msgstr "" #: ../gui.py:1088 msgid "TURBOMOLE coord file" msgstr "" #: ../gui.py:1089 msgid "exciting input" msgstr "" #: ../gui.py:1090 msgid "WIEN2k structure file" msgstr "" #: ../gui.py:1091 msgid "DftbPlus input file" msgstr "" #: ../gui.py:1092 msgid "ETSF format" msgstr "" #: ../gui.py:1093 ../gui.py:1165 msgid "CASTEP geom file" msgstr "" #: ../gui.py:1094 msgid "CASTEP output file" msgstr "" #: ../gui.py:1095 msgid "CASTEP trajectory file" msgstr "" #: ../gui.py:1096 msgid "DFTBPlus GEN format" msgstr "" #: ../gui.py:1102 msgid "File type:" msgstr "" #: ../gui.py:1142 msgid "Save ..." msgstr "" #: ../gui.py:1155 msgid "XYZ file" msgstr "" #: ../gui.py:1156 msgid "ASE trajectory" msgstr "" #: ../gui.py:1157 msgid "PDB file" msgstr "" #: ../gui.py:1158 msgid "Gaussian cube file" msgstr "" #: ../gui.py:1159 msgid "Python script" msgstr "" #: ../gui.py:1160 msgid "VNL file" msgstr "" #: ../gui.py:1161 msgid "Portable Network Graphics" msgstr "" #: ../gui.py:1162 msgid "Persistence of Vision" msgstr "" #: ../gui.py:1163 msgid "Encapsulated PostScript" msgstr "" #: ../gui.py:1164 msgid "FHI-aims geometry input" msgstr "" #: ../gui.py:1166 msgid "VASP geometry input" msgstr "" #: ../gui.py:1168 msgid "cif file" msgstr "" #: ../gui.py:1190 #, python-format msgid "Save current image only (#%d)" msgstr "" #: ../gui.py:1194 msgid "Slice: " msgstr "" #: ../gui.py:1195 msgid "Help for slice ..." msgstr "" #: ../gui.py:1207 msgid "ase-gui INTERNAL ERROR: strange response in Save," msgstr "" #: ../gui.py:1226 msgid "Unknown output format!" msgstr "" #: ../gui.py:1227 #, python-format msgid "Use one of: %s" msgstr "" #: ../gui.py:1332 msgid "Not implemented!" msgstr "" #: ../gui.py:1333 msgid "do you really need it?" msgstr "" #: ../minimize.py:21 msgid "Algorithm: " msgstr "" #: ../minimize.py:26 ../progress.py:67 msgid "Convergence criterion: Fmax = " msgstr "" #: ../minimize.py:31 ../progress.py:70 msgid "Max. number of steps: " msgstr "" #. Special stuff for MDMin #: ../minimize.py:34 msgid "Pseudo time step: " msgstr "" #: ../minimize.py:55 msgid "Energy minimization" msgstr "" #: ../minimize.py:59 msgid "Minimize the energy with respect to the positions." msgstr "" #. Don't catch errors in the function. #. Display status message #: ../minimize.py:91 ../scaling.py:299 msgid "Running ..." msgstr "" #. Update display to reflect cancellation of simulation. #: ../minimize.py:108 #, python-format msgid "Minimization CANCELLED after %i steps." msgstr "" #: ../minimize.py:114 ../scaling.py:350 msgid "Out of memory, consider using LBFGS instead" msgstr "" #. Update display to reflect succesful end of simulation. #: ../minimize.py:121 #, 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:20 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:27 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:84 msgid "Face centered cubic (fcc)" msgstr "" #: ../nanoparticle.py:85 msgid "Body centered cubic (bcc)" msgstr "" #: ../nanoparticle.py:86 msgid "Simple cubic (sc)" msgstr "" #: ../nanoparticle.py:87 msgid "Hexagonal closed-packed (hcp)" msgstr "" #: ../nanoparticle.py:88 msgid "Graphite" msgstr "" #: ../nanoparticle.py:117 msgid "Nanoparticle" msgstr "" #. Choose the element #. Choose the element and bond length #. Choose the element #: ../nanoparticle.py:127 ../nanotube.py:42 ../surfaceslab.py:69 msgid "Element: " msgstr "" #: ../nanoparticle.py:131 msgid "Get structure" msgstr "" #: ../nanoparticle.py:155 msgid "Lattice constant: a =" msgstr "" #. Choose specification method #: ../nanoparticle.py:172 msgid "Method: " msgstr "" #: ../nanoparticle.py:174 msgid "Layer specification" msgstr "" #: ../nanoparticle.py:174 msgid "Wulff construction" msgstr "" #: ../nanoparticle.py:194 msgid "Dummy placeholder object" msgstr "" #: ../nanoparticle.py:196 msgid "Add new direction:" msgstr "" #: ../nanoparticle.py:212 msgid "Add" msgstr "" #: ../nanoparticle.py:220 msgid "Set all directions to default values" msgstr "" #: ../nanoparticle.py:228 msgid "Particle size: " msgstr "" #: ../nanoparticle.py:229 ../nanoparticle.py:266 ../progress.py:196 msgid "Number of atoms: " msgstr "" #: ../nanoparticle.py:234 msgid "Volume: " msgstr "" #: ../nanoparticle.py:239 msgid "ų" msgstr "" #: ../nanoparticle.py:244 msgid "Rounding: If exact size is not possible, choose the size" msgstr "" #: ../nanoparticle.py:247 msgid "above " msgstr "" #: ../nanoparticle.py:248 msgid "below " msgstr "" #: ../nanoparticle.py:249 msgid "closest " msgstr "" #: ../nanoparticle.py:252 msgid "Smaller" msgstr "" #: ../nanoparticle.py:253 msgid "Larger" msgstr "" #: ../nanoparticle.py:268 msgid " Approx. diameter: " msgstr "" #: ../nanoparticle.py:272 msgid "Information about the created cluster:" msgstr "" #. Buttons #: ../nanoparticle.py:278 ../nanotube.py:81 msgid "Creating a nanoparticle." msgstr "" #: ../nanoparticle.py:285 msgid "Automatic Apply" msgstr "" #: ../nanoparticle.py:333 msgid "Up" msgstr "" #: ../nanoparticle.py:338 msgid "Down" msgstr "" #: ../nanoparticle.py:343 msgid "Delete" msgstr "" #: ../nanoparticle.py:384 msgid "Surface energies (as energy/area, NOT per atom):" msgstr "" #: ../nanoparticle.py:390 msgid "Number of layers:" msgstr "" #: ../nanoparticle.py:419 msgid "At least one index must be non-zero" msgstr "" #: ../nanoparticle.py:422 msgid "Invalid hexagonal indices" msgstr "" #: ../nanoparticle.py:477 ../surfaceslab.py:218 msgid "Invalid element." msgstr "" #: ../nanoparticle.py:487 msgid "Unsupported or unknown structure" msgstr "" #: ../nanoparticle.py:604 #, python-format msgid "%.1f Å" msgstr "" #: ../nanotube.py:15 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:29 #, python-format msgid "" " %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: %" "(volume).3f Å3" msgstr "" #: ../nanotube.py:35 msgid "Nanotube" msgstr "" #. Choose the structure. #: ../nanotube.py:59 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:81 msgid "Help" msgstr "" #: ../widgets.py:98 msgid "Clear constraint" msgstr "" python-ase-3.9.1.4567/ase/gui/rotate.py0000664000175000017500000000306412553425527017706 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/gui/dft.py0000664000175000017500000000265312553425527017170 0ustar jensjjensj00000000000000from 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.9.1.4567/ase/gui/nanotube.py0000664000175000017500000001413412553425527020223 0ustar jensjjensj00000000000000# 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.gui.status import formula 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') """ label_template = _(u""" %(natoms)i atoms: %(symbols)s, diameter: %(diameter).3f Å, cell volume: %(volume).3f Å3""") 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.makeatoms) self.bondlength = gtk.Adjustment(1.42, 0.0, 1000.0, 0.01) label2 = gtk.Label(_(" Bond length: ")) label3 = gtk.Label(_(u"Å")) 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("")) self.status = gtk.Label("") pack(vbox,[self.status]) 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.makeatoms() self.bondlength.connect('value-changed', self.makeatoms) self.m.connect('value-changed', self.makeatoms) self.n.connect('value-changed', self.makeatoms) self.length.connect('value-changed', self.makeatoms) 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} 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])) label = label_template % {'natoms' : self.atoms.get_number_of_atoms(), 'symbols' : formula(self.atoms.get_atomic_numbers()), 'volume' : self.atoms.get_volume(), 'diameter' : self.atoms.get_cell()[0][0]/2.0} self.status.set_markup(label) 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.9.1.4567/ase/gui/simulation.py0000664000175000017500000001265612553425527020603 0ustar jensjjensj00000000000000"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 'progress' in self.gui.simulation: self.gui.simulation['progress'].begin(**kwargs) def end(self): if 'progress' in self.gui.simulation: 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.9.1.4567/ase/gui/ag.py0000664000175000017500000001262312553425527017000 0ustar jensjjensj00000000000000from __future__ import print_function # Copyright 2008, 2009 # CAMd (see accompanying license files for details). from __future__ import print_function import sys from optparse import OptionParser 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/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/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.') parser.add_option('-s', '--scale', dest='radii_scale', metavar='FLOAT', default=None, type=float, help='Scale covalent radii.') parser.add_option('-v', '--verbose', action='store_true', help='Verbose mode.') return parser def main(): parser = build_parser() opt, args = parser.parse_args() try: import ase except ImportError: 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 try: images.read(args, string2index(opt.image_number)) except IOError as e: if len(e.args) == 1: parser.error(e.args[0]) else: parser.error(e.args[1] + ': ' + e.filename) 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.radii_scale: images.set_radii(opt.radii_scale) 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, end=' ') 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) try: run(opt, args) except KeyboardInterrupt: pass except Exception as x: if opt.verbose: raise else: print('{0}: {1}'.format(x.__class__.__name__, x), file=sys.stderr) print(_('To get a full traceback, use: ase-gui --verbose'), file=sys.stderr) python-ase-3.9.1.4567/ase/gui/scaling.py0000664000175000017500000004647612553425527020046 0ustar jensjjensj00000000000000# 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:")) fitframe.set_size_request(100,150) 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 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 'progress' in self.gui.simulation: 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 'progress' in self.gui.simulation: 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.9.1.4567/ase/gui/gtkexcepthook.py0000664000175000017500000002276412553425527021277 0ustar jensjjensj00000000000000from __future__ import print_function # 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 io 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 isinstance(builtins, 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 [a for a in context if a.strip()]])) 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.9.1.4567/ase/gui/widgets.py0000664000175000017500000001300612553425527020053 0ustar jensjjensj00000000000000from __future__ import print_function import sys from gettext import gettext as _ import gtk import re 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 without all the markup tags plaintext = ''.join(re.split('<[^>]+>', text)) linelen = max([len(x) for x in plaintext.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: # isinstance does not work here 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(message, file=sys.stderr) print(message2, file=sys.stderr) dialog.connect('response', lambda x, y, dialog=dialog: dialog.destroy()) dialog.show() class AseGuiCancelException(Exception): pass python-ase-3.9.1.4567/ase/gui/rot_tools.py0000664000175000017500000000312112553425527020426 0ustar jensjjensj00000000000000# 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.9.1.4567/ase/gui/movie.py0000664000175000017500000001072212553425527017526 0ustar jensjjensj00000000000000import 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_coordinates(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.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.9.1.4567/ase/gui/bulk_modulus.py0000664000175000017500000000202412553425527021110 0ustar jensjjensj00000000000000# -*- 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.9.1.4567/ase/gui/languages/0000775000175000017500000000000012553427753020004 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/gui/languages/__init__.py0000664000175000017500000000131712553425527022114 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/gui/languages/da.py0000664000175000017500000000122012553425527020732 0ustar jensjjensj00000000000000# -*- 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""", 'Slice: ': 'Udsnit: ' } python-ase-3.9.1.4567/ase/gui/languages/en.py0000664000175000017500000000071312553425527020756 0ustar jensjjensj00000000000000translation = { '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 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.9.1.4567/ase/gui/debug.py0000664000175000017500000000101712553425527017472 0ustar jensjjensj00000000000000from __future__ import print_function 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(eval(entry.get_text()), file=sys.stderr) python-ase-3.9.1.4567/ase/gui/constraints.py0000664000175000017500000000273112553425527020757 0ustar jensjjensj00000000000000from 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.9.1.4567/ase/gui/setupwindow.py0000664000175000017500000000413112553425527020774 0ustar jensjjensj00000000000000# 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.9.1.4567/ase/gui/pybutton.py0000664000175000017500000000463512553425527020301 0ustar jensjjensj00000000000000 """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.9.1.4567/ase/gui/graphene.py0000664000175000017500000002366012553425527020205 0ustar jensjjensj00000000000000# 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.gui.status import formula 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) """ label_template = _(""" %(natoms)i atoms: %(symbols)s, Volume: %(volume).3f A3""") 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) 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) 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.bondlength = gtk.Adjustment(1.42, 0.0, 1000.0, 0.01) label2 = gtk.Label(_(" Bond length: ")) label3 = gtk.Label(_(u"Å")) 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.bondlength2 = gtk.Adjustment(1.12, 0.0, 1000.0, 0.01) self.sat_label2 = gtk.Label(_(" Bond length: ")) self.sat_label3 = gtk.Label(_(u"Å")) 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(_(u"Å")) vac_box = gtk.SpinButton(self.vacuum, 10.0, 2) pack(vbox, [label1, vac_box, label2]) pack(vbox, gtk.Label("")) self.status = gtk.Label("") pack(vbox,[self.status]) pack(vbox,[gtk.Label("")]) # Buttons 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.makeatoms() self.struct.connect('changed', self.makeatoms) self.orient.connect('changed', self.makeatoms) self.element.connect('activate', self.makeatoms) self.bondlength.connect('value-changed', self.makeatoms) self.element2.connect('activate', self.makeatoms) self.bondlength2.connect('value-changed', self.makeatoms) self.n.connect('value-changed', self.makeatoms) self.m.connect('value-changed', self.makeatoms) self.vacuum.connect('value-changed', self.makeatoms) 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() self.update_gui() 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 self.status.set_markup(_("Please specify a consistent set of atoms. ")) 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]]) # 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])) 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_markup(label) 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.9.1.4567/ase/gui/settings.py0000664000175000017500000000641312553425527020251 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/gui/surfaceslab.py0000664000175000017500000002411112553425527020676 0ustar jensjjensj00000000000000# 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(_(u"Å"))]) 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(u"Å")]) 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(_(u" Å 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 as 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.data.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.9.1.4567/ase/gui/i18n.py0000664000175000017500000000076212553425527017171 0ustar jensjjensj00000000000000import os import sys 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) if sys.version_info[0] == 2: translation.install(unicode=True) else: translation.install() python-ase-3.9.1.4567/ase/gui/minimize.py0000664000175000017500000001257312553425527020236 0ustar jensjjensj00000000000000# 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 ase.optimize 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.9.1.4567/ase/gui/calculator.py0000664000175000017500000024557512553425527020560 0ustar jensjjensj00000000000000# 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. """) eam_info_txt = _("""\ The EAM/ADP potential is a many-body potential implementation of the Embedded Atom Method and equipotential plus the Angular Dependent Potential, which is an extension of the EAM to include directional bonds. EAM is suited for FCC metallic bonding while the ADP is suited for metallic bonds with some degree of directionality. For EAM see M.S. Daw and M.I. Baskes, Phys. Rev. Letters 50 (1983) 1285. For ADP see Y. Mishin, M.J. Mehl, and D.A. Papaconstantopoulos, Acta Materialia 53 2005 4029--4041. Data for the potential is contained in a file in either LAMMPS Alloy or ADP format which need to be loaded before use. The Interatomic Potentials Repository Project at http://www.ctcms.nist.gov/potentials/ contains many suitable potential files. For large simulations the LAMMPS calculator is more suitable; this implementation is mainly to make EAM available when LAMMPS is not installed or to develop new EAM/ADP poentials by matching results using ab initio. """) 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", "eam", "brenner", "gpaw", "aims", "vasp") # List the names of the parameter dictionaries paramdicts = ("lj_parameters", "eam_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) # EAM self.eam_radio = gtk.RadioButton( self.none_radio, _("EAM - Embedded Atom Method/Angular Dependent Potential (ASE)")) self.eam_setup = gtk.Button(_("Setup")) self.eam_setup.connect("clicked", self.eam_setup_window) self.eam_info = InfoButton(eam_info_txt) self.pack_line(vbox, self.eam_radio, self.eam_setup, self.eam_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 eam_setup_window(self, widget): if not self.get_atoms(): return eam_param = getattr(self, "eam_parameters", None) EAM_Window(self, eam_param, "eam_parameters") # When control is retuned, self.eam_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.eam_radio.get_active(): if nochk or self.eam_check(): self.choose_eam() 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 p in state: 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) as 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) as 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 eam_check(self): from ase.calculators.eam import EAM if not hasattr(self, "eam_parameters"): oops(_("You must set up the EAM parameters")) return False self.atoms.set_calculator(EAM(**self.eam_parameters)) return self.element_check("EAM", self.atoms.get_calculator().elements) def choose_eam(self): from ase.calculators.eam import EAM def eam_factory(p=self.eam_parameters): calc = EAM(**p) return calc self.gui.simulation["calc"] = eam_factory 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): import ase.calculators.emt self.gui.simulation["calc"] = ase.calculators.emt.EMT # In case Asap has been imported ase.calculators.emt.EMT.disabled = False 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(_(u"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 EAM_Window(gtk.Window): def __init__(self, owner, param, attrname): gtk.Window.__init__(self) self.set_title(_("EAM parameters")) self.owner = owner self.attrname = attrname self.owner = owner atoms = owner.atoms self.natoms = len(atoms) vbox = gtk.VBox() vbox.show() self.add(vbox) pack(vbox, gtk.Label("")) butbox = gtk.HButtonBox() import_potential_but = gtk.Button(_("Import Potential")) import_potential_but.connect("clicked", self.import_potential) 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(import_potential_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() # Now, set the parameters if param: self.eam_file = param['potential'] self.show() self.grab_add() # Lock all other windows def ok(self, *args): if not hasattr(self.owner, "eam_parameters"): oops(_("You need to import the potential file")) self.destroy() def import_potential(self, *args): dirname = "." filename = "Al99.eam.alloy" chooser = gtk.FileChooserDialog( _('Import .alloy or .adp potential file ... '), None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) chooser.set_filename(dirname + filename) openr = chooser.run() if openr == gtk.RESPONSE_OK: param = {} filename = chooser.get_filename() param['potential'] = filename setattr(self.owner, self.attrname, param) chooser.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 += _(u"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(_(u"Å"))]) 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 = _(u"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 = _(u"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 = _(u"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 'AIMS_COMMAND' in os.environ: text = os.environ['AIMS_COMMAND'] else: text = "" self.run_command.set_text(text) if 'AIMS_SPECIES_DIR' in os.environ: 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 'output' in param: 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 'VASP_PP_PATH' in os.environ: 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 = _(u"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 'VASP_COMMAND' in os.environ: 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 'VASP_PP_PATH' in os.environ: 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 or key in special_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.9.1.4567/ase/gui/progress.py0000664000175000017500000003164612553425527020263 0ustar jensjjensj00000000000000from __future__ import print_function # 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.9.1.4567/ase/gui/save.py0000664000175000017500000002376412553425527017357 0ustar jensjjensj00000000000000# encoding: utf-8 """save.py - Window for saving one or more configurations.""" import gtk from gettext import gettext as _ from ase.gui.widgets import pack, cancel_apply_ok, oops, help from ase.io import string2index, write import numpy as np import sys import os class SaveWindow(gtk.Window): # List of valid file types - translation occurs when *using* this list! # Name, suffix, is_graphics, multiimage filetypes = [('Automatic', None, None, None), ('XYZ file', 'xyz', False, True), ('ASE trajectory', 'traj', False, True), ('PDB file', 'pdb', False, True), ('Gaussian cube file', 'cube', False, False), ('Python script', 'py', False, True), ('VNL file', 'vnl', False, False), ('Portable Network Graphics', 'png', True, False), ('Persistence of Vision', 'pov', True, False), ('Encapsulated PostScript', 'eps', True, False), ('FHI-aims geometry input', 'in', False, False), ('CASTEP geom file', 'cell', False, True), ('VASP geometry input', 'POSCAR', False, False), ('ASE bundle trajectory', 'bundle', False, True), ('cif file', 'cif', False, True), ] def __init__(self, gui): gtk.Window.__init__(self) self.gui = gui self.setup() self.show() def setup(self): self.set_title(_('Save ...')) vbox = gtk.VBox() self.add(vbox) confframe = gtk.Frame() # For selecting which configs to save pack(vbox, confframe) vbox2 = gtk.VBox() confframe.add(vbox2) vbox2.show() self.radio_thisconf = gtk.RadioButton( None, _('Save this configuration only (#%s).') % self.frame) self.radio_allconf = gtk.RadioButton(self.radio_thisconf, _('Save all configurations.')) self.radio_someconf = gtk.RadioButton(self.radio_thisconf, _('Save some configurations: ')) self.whichconf = gtk.Entry(max=20) pack(vbox2, [self.radio_thisconf]) pack(vbox2, [self.radio_allconf]) pack(vbox2, [self.radio_someconf, self.whichconf]) if self.gui.images.nimages <= 1: self.radio_thisconf.set_active(True) self.radio_allconf.set_sensitive(False) self.radio_someconf.set_sensitive(False) self.whichconf.set_sensitive(False) else: self.radio_allconf.set_active(True) self.chooser = gtk.FileChooserWidget(gtk.FILE_CHOOSER_ACTION_SAVE) try: fname = sys.argv[1] except IndexError: fname = "" self.chooser.set_current_folder(os.getcwd()) self.chooser.set_current_name(fname) self.add_filters(self.chooser) self.old_chooser_name = self.chooser.get_filter().get_name() self.chooser.connect('notify::filter', self.filter_changed) pack(vbox, self.chooser, expand=True) # Add buttons self.buttons = gtk.HButtonBox() savebut = gtk.Button(stock=gtk.STOCK_SAVE) savebut.connect('clicked', self.save) cancelbut = gtk.Button(stock=gtk.STOCK_CANCEL) cancelbut.connect('clicked', lambda x: self.destroy()) for w in (savebut, cancelbut): self.buttons.pack_start(w, 0, 0) w.show() pack(vbox, [self.buttons], end=True, bottom=True) vbox.show() def filter_changed(self, *args): #print "notify::filter called: " + str(args) newname = self.chooser.get_filter().get_name() if newname == self.old_chooser_name: return # Nothing has happened. oldsuffix = self.name_to_suffix[self.old_chooser_name] self.old_chooser_name = newname # Remember it. newsuffix = self.name_to_suffix[newname] if newsuffix is None: # Change to Automatic - do nothing return filename = self.chooser.get_filename() fileprefix, filesuffix = os.path.splitext(filename) if oldsuffix is None: # Change away from Automatic, any valid suffix will be changed. if filesuffix == '': # No old suffix, append new suffix newfilename = filename + '.' + newsuffix elif filesuffix[1:] in self.name_to_suffix.values(): # Old suffix is valid, replace with new. newfilename = fileprefix + '.' + newsuffix else: # Old suffix is weird, perhaps a . in filename. Append the right suffix newfilename = filename + '.' + newsuffix elif oldsuffix == filesuffix[1:]: # Change away from valid suffix, replace old with new. newfilename = fileprefix + '.' + newsuffix else: # Old suffix does not match old file type - do nothing, perhaps user knows # what he is doing... return # Change the filename self.chooser.set_current_name(newfilename) def save(self, dummy): "The user has pressed the SAVE button." filename = self.chooser.get_filename() if not filename or filename == "<>": oops("Please specify a file name") return # Check file type suffix = os.path.splitext(filename)[1][1:] if 'POSCAR' in filename or 'CONTCAR' in filename: suffix = 'POSCAR' if suffix == '': # No suffix chosen filt = self.chooser.get_filter().get_name() suffix = self.name_to_suffix[filt] if suffix is None: oops("Specify file type by giving a suffix or selecting a file type.") return else: filename = filename + '.' + suffix else: # Suffix given - check that it is not in conflict with selected file type. filt = self.chooser.get_filter().get_name() suffix2 = self.name_to_suffix[filt] if suffix2 is not None and suffix != suffix2: oops("Your filename suffix conflicts with the file type you have selected.") return if suffix not in self.name_to_suffix.values(): oops("Unknown file suffix "+suffix) return # We now have a consistent file name with an allowed suffix. # Find out which images we want to save. if self.radio_thisconf.get_active(): indices = [self.gui.frame] elif self.radio_allconf.get_active(): indices = range(self.gui.images.nimages) elif self.radio_someconf.get_active(): txt = self.whichconf.get_text() if not txt: oops("Please specify which images to save.") return try: slice = string2index(txt) except ValueError: oops("ERROR: Failed to parse image specification '%s'" % (txt,)) return indices = range(self.gui.images.nimages)[slice] if isinstance(indices, int): indices = [indices] else: raise RuntimeError("No radio button selected - should not be possible!") # Now we are ready to write the file! extra = {} remove_hidden = False if self.is_graphics[suffix]: bbox = np.empty(4) size = np.array([self.gui.width, self.gui.height]) / self.gui.scale bbox[0:2] = np.dot(self.gui.center, self.gui.axes[:, :2]) - size / 2 bbox[2:] = bbox[:2] + size extra['rotation'] = self.gui.axes extra['show_unit_cell'] = self.gui.ui.get_widget('/MenuBar/ViewMenu/ShowUnitCell').get_active() extra['bbox'] = bbox extra['colors'] = self.gui.get_colors(rgb=True)[self.gui.images.visible] remove_hidden = True if len(indices) == 1: # Saving a single configuration is always possible. write(filename, self.gui.images.get_atoms(indices[0], remove_hidden=remove_hidden), **extra) elif self.support_multi[suffix]: images = [self.gui.images.get_atoms(i, remove_hidden=remove_hidden) for i in indices] write(filename, images, **extra) else: # We want to write multiple images, but the file format does not support it. # The solution is to write multiple files, inserting a number in the file name # before the suffix. filename = filename.replace('%', '%%') # Preserve % in filenames. suffixpos = filename.rfind('.') filename = filename[:suffixpos] + '%05d' + filename[suffixpos:] for i, idx in enumerate(indices): write(filename % (i,), self.gui.images.get_atoms(idx, remove_hidden=remove_hidden), **extra) oops("Wrote %d files" % (len(indices),), (filename % (0,)) + ' .. ' + (filename % (len(indices)-1,))) self.destroy() def add_filters(self, chooser): # Add file type filters self.name_to_suffix = {} self.is_graphics = {} self.support_multi = {} for name, suffix, graphics, multi in self.filetypes: 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) self.name_to_suffix[name] = suffix if suffix is not None: self.is_graphics[suffix] = graphics self.support_multi[suffix] = multi chooser.add_filter(filt) python-ase-3.9.1.4567/ase/gui/quickinfo.py0000664000175000017500000000374412553425551020402 0ustar jensjjensj00000000000000# 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 %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) periodic = [[_('no'), _('yes')][periodic] for periodic in images.pbc] # TRANSLATORS: This has the form Periodic: no, no, yes pbcstring = _('Periodic: %s, %s, %s' % tuple(periodic)) txt = format % ((imgtxt, natoms) + tuple(uc.flat) + (pbcstring,) + (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.9.1.4567/ase/gui/crystal.py0000664000175000017500000005446212553425527020101 0ustar jensjjensj00000000000000# 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.data.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.9.1.4567/ase/gui/render.py0000664000175000017500000003656512553425527017703 0ustar jensjjensj00000000000000from __future__ import print_function 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) colors_tmp = [] for n in range(self.natoms): colors_tmp.append(list(colors[n]) + [0,self.default_transparency.value]) colors = colors_tmp 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.9.1.4567/ase/gui/graphs.py0000664000175000017500000001121612553425527017672 0ustar jensjjensj00000000000000from math import sqrt import gtk from gettext import gettext as _ from ase.gui.widgets import pack, help graph_help_text = _("""\ Help for plot ... Symbols: e:\t\t\t\ttotal energy epot:\t\t\tpotential energy ekin:\t\t\tkinetic energy fmax:\t\t\tmaximum force fave:\t\t\taverage force R[n,0-2]:\t\t\tposition of atom number n d(n1,n2):\t\t\tdistance between two atoms n1 and n2 i:\t\t\t\tcurrent image number E[i]:\t\t\t\tenergy of image number i F[n,0-2]:\t\t\tforce on atom number n V[n,0-2]:\t\t\tvelocity of atom number n M[n]:\t\t\tmagnetic moment of atom number n A[0-2,0-2]:\t\tunit-cell basis vectors s:\t\t\t\tpath length a(n1,n2,n3):\t\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\t\ttemperature (K)\ """) 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(graph_help_text)])[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('GTKAgg') #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.9.1.4567/ase/gui/view.py0000664000175000017500000010530512553425527017363 0ustar jensjjensj00000000000000# Emacs: treat this as -*- python -*- import os import gtk import pango import tempfile from math import cos, sin, sqrt, atan, atan2 from os.path import basename import numpy as np from ase.data import chemical_symbols 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.gui.defaults import read_defaults from ase.utils import rotate from ase.quaternions import Quaternion class View: def __init__(self, vbox, rotations): self.colormode = 'jmol' # The default colors self.nselected = 0 self.labels = None 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.config = None 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 Disp = self.images.D 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) self.coordination = np.zeros((self.images.natoms), dtype=int) if nb == 0: return n1 = 0 for a in range(self.images.natoms): indices, offsets = nl.get_neighbors(a) self.coordination[a] += len(indices) for a2 in indices: self.coordination[a2] += 1 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 show_labels(self, action, active): an = active.get_name() if an == "AtomIndex": self.labels = [list(range(self.images.natoms))] * self.images.nimages elif an == "NoLabel": self.labels = None elif an == "MagMom": self.labels = self.images.M elif an == "Element": self.labels = [[chemical_symbols[x] for x in self.images.Z]] * self.images.nimages self.draw() def toggle_show_axes(self, action): self.draw() def toggle_show_bonds(self, action): self.set_coordinates() def toggle_show_velocities(self, action): self.show_vectors(10 * self.images.V) # XXX hard coded scale is ugly self.draw() def toggle_show_forces(self, action): self.show_vectors(self.images.F) self.draw() def hide_selected(self, button): self.images.visible[self.images.selected] = False self.draw() def show_selected(self, button): self.images.visible[self.images.selected] = True self.draw() 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 set_view(self, menuitem): plane_rotation = menuitem.get_name() if plane_rotation == 'xyPlane': self.axes = rotate('0.0x,0.0y,0.0z') elif plane_rotation == 'yzPlane': self.axes = rotate('-90.0x,-90.0y,0.0z') elif plane_rotation == 'zxPlane': self.axes = rotate('90.0x,0.0y,90.0z') elif plane_rotation == 'yxPlane': self.axes = rotate('180.0x,0.0y,90.0z') elif plane_rotation == 'zyPlane': self.axes = rotate('0.0x,90.0y,0.0z') elif plane_rotation == 'xzPlane': self.axes = rotate('-90.0x,0.0y,0.0z') else: if plane_rotation == 'a1a2Plane': i, j = 0, 1 elif plane_rotation == 'a2a3Plane': i, j = 1, 2 elif plane_rotation == 'a3a1Plane': i, j = 2, 0 elif plane_rotation == 'a2a1Plane': i, j = 1, 0 elif plane_rotation == 'a3a2Plane': i, j = 2, 1 elif plane_rotation == 'a1a3Plane': i, j = 0, 2 x1 = self.images.A[self.frame, i] x2 = self.images.A[self.frame, j] norm = np.linalg.norm x1 = x1 / norm(x1) x2 = x2 - x1 * np.dot(x1, x2) x2 /= norm(x2) x3 = np.cross(x1, x2) self.axes = np.array([x1, x2, x3]).T self.set_coordinates() 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. # The rgb data may be three numbers, or a named color. As # the type of data is unknown, we cannot create an array # beforehand with sensible default values, but need to # create unused elements on the fly. The type of unused # elements is important to prevent trouble when converting # to numpy arrays. colarray = [] for z, c in self.colordata: if z >= len(colarray): # Allocate unused elements as well. colarray.extend([c,] * (1 + z - len(colarray))) 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_data[0]) * self.colormode_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_data[0]) * self.colormode_data[1] nV = np.clip(nV.astype(int), 0, len(self.colors)-1) colors = np.array(colarray)[nV] elif self.colormode == 'charge': Q = self.images.q[self.frame] nq = ((Q - self.colormode_data[0]) * self.colormode_data[1] ) nq = np.clip(nq.astype(int), 0, len(self.colors)-1) colors = np.array(colarray)[nq] elif self.colormode == 'magnetic moment': M = self.images.M[self.frame] nm = ((M - self.colormode_data[0]) * self.colormode_data[1] ) nm = np.clip(nm.astype(int), 0, len(self.colors)-1) colors = np.array(colarray)[nm] elif self.colormode == 'coordination': if not hasattr(self, 'coordination'): self.bind(self.frame) colors = np.array(colarray)[self.coordination] 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, d): 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 if not circle: Q = Quaternion(self.images.Q[self.frame][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 rotated 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 rotated 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.arange(16) * 2 * np.pi / 16 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) else: return self.pixmap.draw_arc(gc, fill, A[j, 0], A[j, 1], d[j], d[j], 0, 23040) else: return self.pixmap.draw_arc(gc, fill, A[j, 0], A[j, 1], d[j], d[j], 0, 23040) def arrow(self, begin, end): vec = end - begin length = np.sqrt((vec[:2]**2).sum()) length = min(length, 0.3 * self.scale) line = self.pixmap.draw_line beg = begin.round().astype(int) en = end.round().astype(int) line(self.foreground_gc, beg[0], beg[1], en[0], en[1]) angle = atan2(en[1] - beg[1], en[0] - beg[0]) + np.pi x1 = (end[0] + length * cos(angle - 0.3)).round().astype(int) y1 = (end[1] + length * sin(angle - 0.3)).round().astype(int) x2 = (end[0] + length * cos(angle + 0.3)).round().astype(int) y2 = (end[1] + length * sin(angle + 0.3)).round().astype(int) line(self.foreground_gc, x1, y1, en[0], en[1]) line(self.foreground_gc, x2, y2, en[0], en[1]) def draw(self, status=True): self.pixmap.draw_rectangle(self.background_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) disp = (np.dot(self.images.D[self.frame],axes)).round().astype(int) d = (2 * r).round().astype(int) vectors = (self.ui.get_widget('/MenuBar/ViewMenu/ShowVelocities' ).get_active() or self.ui.get_widget('/MenuBar/ViewMenu/ShowForces' ).get_active()) if vectors: V = np.dot(self.vectors[self.frame], axes) selected_gc = self.selected_gc colors = self.get_colors() arc = self.pixmap.draw_arc line = self.pixmap.draw_line foreground_gc = self.foreground_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]: # Draw the atoms self.my_arc(colors[a], True, a, X, r, n, A, d) # Draw labels on the atoms if self.labels is not None: # start labeling with atomic indexes # to do: scale position and size with radius in some # meaningful manner - pick a reference magnification # where it "looks good" and then go from there ... nlabel = str(self.labels[self.frame][a]) colorl = self.foreground_gc layout = self.drawing_area.create_pango_layout(nlabel) xlabel = int(A[a,0]+ra/2 - layout.get_size()[0]/2. / pango.SCALE) ylabel = int(A[a,1]+ra/2 - layout.get_size()[1]/2. / pango.SCALE) self.pixmap.draw_layout(colorl, xlabel, ylabel, layout) # Draw cross on constrained atoms if not dynamic[a]: R1 = int(0.14644 * ra) R2 = int(0.85355 * ra) line(foreground_gc, A[a, 0] + R1, A[a, 1] + R1, A[a, 0] + R2, A[a, 1] + R2) line(foreground_gc, A[a, 0] + R2, A[a, 1] + R1, A[a, 0] + R1, A[a, 1] + R2) # Draw velocities og forces if vectors: self.arrow(X[a], X[a] + V[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) # Draw marking circles around the atoms if selected[a]: self.my_arc(selected_gc, False, a, X, r, n, A, d) elif visible[a]: self.my_arc(foreground_gc, False, a, X, r, n, A, d) else: # Draw unit cell a -= n line(foreground_gc, X1[a, 0] + disp[0], X1[a, 1] + disp[1], X2[a, 0] + disp[0], X2[a, 1] + disp[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.background_gc, self.pixmap, 0, 0, 0, 0, self.width, self.height) if status: self.status() def draw_axes(self): axes_labels = [ "X", "Y", "Z"] axes_length = 15 for i in self.axes[:,2].argsort(): a = 20 b = self.height - 20 c = int(self.axes[i][0] * axes_length + a) d = int(-self.axes[i][1] * axes_length + b) self.pixmap.draw_line(self.foreground_gc, a, b, c, d) # The axes label layout = self.drawing_area.create_pango_layout(axes_labels[i]) layout.set_markup(axes_labels[i]) lox = int(self.axes[i][0] * 20 + 20\ - layout.get_size()[0] / 2. / pango.SCALE) loy = int(self.height - 20 - self.axes[i][1] * 20\ - layout.get_size()[1] / 2. / pango.SCALE) self.pixmap.draw_layout(self.foreground_gc, lox, loy, layout) def draw_frame_number(self): n = str(self.frame) color = self.foreground_gc line = self.pixmap.draw_line layout = self.drawing_area.create_pango_layout("Frame: " + n) x = self.width - 3 - layout.get_size()[0] / pango.SCALE y = self.height - 5 - layout.get_size()[1] / pango.SCALE self.pixmap.draw_layout(self.foreground_gc, x, y, layout) 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.background_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.config = read_defaults() self.colormap = self.drawing_area.get_colormap() self.foreground_gc = self.drawing_area.window.new_gc( self.colormap.alloc_color(self.config['gui_foreground_color'])) self.background_gc = self.drawing_area.window.new_gc( self.colormap.alloc_color(self.config['gui_background_color'])) 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.background_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) def show_vectors(self, vectors): self.vectors = vectors python-ase-3.9.1.4567/ase/gui/neb.py0000664000175000017500000000024512553425527017152 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- from ase.neb import NEBtools def NudgedElasticBand(images): nebtools = NEBtools(images) fig = nebtools.plot_band() fig.show() python-ase-3.9.1.4567/ase/atom.py0000664000175000017500000001426112553425527016565 0ustar jensjjensj00000000000000"""This module defines the Atom object.""" import numpy as np from ase.data import atomic_numbers, chemical_symbols, atomic_masses # Singular, plural, default value: names = {'position': ('positions', np.zeros(3)), 'number': ('numbers', 0), 'tag': ('tags', 0), 'momentum': ('momenta', np.zeros(3)), 'mass': ('masses', None), 'magmom': ('magmoms', 0.0), 'charge': ('charges', 0.0)} def atomproperty(name, doc): """Helper function to easily create Atom attribute property.""" def getter(self): return self.get(name) def setter(self, value): self.set(name, value) def deleter(self): self.delete(name) return property(getter, setter, deleter, doc) def abcproperty(index): """Helper function to easily create Atom ABC-property.""" def getter(self): spos = self.atoms.get_scaled_positions() return spos[self.index][index] def setter(self, value): spos = self.atoms.get_scaled_positions() spos[self.index][index] = value self.atoms.set_scaled_positions(spos) return property(getter, setter, doc='ABC'[index] + '-coordinate') def xyzproperty(index): """Helper function to easily create Atom XYZ-property.""" def getter(self): return self.position[index] def setter(self, value): self.position[index] = value return property(getter, setter, doc='XYZ'[index] + '-coordinate') class Atom(object): """Class for representing a single atom. Parameters: symbol: str or int Can be a chemical symbol (str) or an atomic number (int). position: sequence of 3 floats Atomi position. tag: int Special purpose tag. momentum: sequence of 3 floats Momentum for atom. mass: float Atomic mass in atomic units. magmom: float or 3 floats Magnetic moment. charge: float Atomic charge. """ __slots__ = ['data', 'atoms', 'index'] def __init__(self, symbol='X', position=(0, 0, 0), tag=None, momentum=None, mass=None, magmom=None, charge=None, atoms=None, index=None): self.data = d = {} if atoms is None: # This atom is not part of any Atoms object: if isinstance(symbol, str): d['number'] = atomic_numbers[symbol] else: d['number'] = symbol d['position'] = np.array(position, float) d['tag'] = tag if momentum is not None: momentum = np.array(momentum, float) d['momentum'] = momentum d['mass'] = mass if magmom is not None: magmom = np.array(magmom, float) d['magmom'] = magmom d['charge'] = charge self.index = index self.atoms = atoms def __repr__(self): s = "Atom('%s', %s" % (self.symbol, list(self.position)) for name in ['tag', 'momentum', 'mass', 'magmom', 'charge']: value = self.get_raw(name) if value is not None: if isinstance(value, np.ndarray): value = value.tolist() s += ', %s=%s' % (name, value) if self.atoms is None: s += ')' else: s += ', index=%d)' % self.index return s def cut_reference_to_atoms(self): """Cut reference to atoms object.""" for name in names: self.data[name] = self.get_raw(name) self.index = None self.atoms = None def get_raw(self, name): """Get name attribute, return None if not explicitely set.""" if name == 'symbol': return chemical_symbols[self.get_raw('number')] if self.atoms is None: return self.data[name] plural = names[name][0] if plural in self.atoms.arrays: return self.atoms.arrays[plural][self.index] else: return None def get(self, name): """Get name attribute, return default if not explicitely set.""" value = self.get_raw(name) if value is None: if name == 'mass': value = atomic_masses[self.number] else: value = names[name][1] return value def set(self, name, value): """Set name attribute to value.""" if name == 'symbol': name = 'number' value = atomic_numbers[value] if self.atoms is None: assert name in names self.data[name] = value else: plural, default = names[name] if plural in self.atoms.arrays: array = self.atoms.arrays[plural] if name == 'magmom' and array.ndim == 2: assert len(value) == 3 array[self.index] = value else: if name == 'magmom' and np.asarray(value).ndim == 1: array = np.zeros((len(self.atoms), 3)) elif name == 'mass': array = self.atoms.get_masses() else: default = np.asarray(default) array = np.zeros((len(self.atoms),) + default.shape, default.dtype) array[self.index] = value self.atoms.new_array(plural, array) def delete(self, name): """Delete name attribute.""" assert self.atoms is None assert name not in ['number', 'symbol', 'position'] self.data[name] = None symbol = atomproperty('symbol', 'Chemical symbol') number = atomproperty('number', 'Atomic number') position = atomproperty('position', 'XYZ-coordinates') tag = atomproperty('tag', 'Integer tag') momentum = atomproperty('momentum', 'XYZ-momentum') mass = atomproperty('mass', 'Atomic mass') magmom = atomproperty('magmom', 'Initial magnetic moment') charge = atomproperty('charge', 'Atomic charge') x = xyzproperty(0) y = xyzproperty(1) z = xyzproperty(2) scaled_position = atomproperty('scaled_position', 'ABC-coordinates') a = abcproperty(0) b = abcproperty(1) c = abcproperty(2) python-ase-3.9.1.4567/ase/quaternions.py0000664000175000017500000000755012553425527020200 0ustar jensjjensj00000000000000import 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([[3, 2, 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').copy() 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.9.1.4567/ase/phonons.py0000664000175000017500000006512612553425527017317 0ustar jensjjensj00000000000000from __future__ import print_function """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 Trajectory from ase.utils import opencew 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' fd = opencew(filename) if fd is not None: # Call derived class implementation of __call__ output = self.__call__(atoms_N) # Write output to file if rank == 0: 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() fd = opencew(filename) if fd is None: # Skip if already done continue # 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: 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.lattice 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 the 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] traj = Trajectory('%s.mode.%d.traj' % (self.name, l), 'w') for x in np.linspace(0, 2*pi, nimages, endpoint=False): atoms.set_positions((pos_Nav + np.exp(1.j * x) * mode_Nav).real) traj.write(atoms) traj.close() python-ase-3.9.1.4567/ase/version.py0000664000175000017500000000041212553425527017303 0ustar jensjjensj00000000000000# Copyright (C) 2003 CAMP # Please see the accompanying LICENSE file for further information. version_base = '3.9.1' try: from ase.svnversion import svnversion except ImportError: version = version_base else: version = version_base + '.' + svnversion python-ase-3.9.1.4567/ase/transport/0000775000175000017500000000000012553427753017306 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/transport/stm_test.py0000664000175000017500000000326312553425527021523 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/transport/__init__.py0000664000175000017500000000005512553425527021414 0ustar jensjjensj00000000000000from .calculators import TransportCalculator python-ase-3.9.1.4567/ase/transport/test_transport_calulator.py0000664000175000017500000000423512553425527025022 0ustar jensjjensj00000000000000from __future__ import print_function 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(x, y, file=fd) 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.9.1.4567/ase/transport/calculators.py0000664000175000017500000003605712553425527022204 0ustar jensjjensj00000000000000from __future__ import print_function 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, 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('%r 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('# Initializing calculator...', file=self.log) 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('# Aligning scat. H to left lead H. diff=', diff, file=self.log) 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(energy, self.T_e[e], file=self.log) 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 not None: 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.9.1.4567/ase/transport/selfenergy.py0000664000175000017500000000545512553425527022031 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/transport/greenfunction.py0000664000175000017500000000411012553425527022517 0ustar jensjjensj00000000000000import 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.retarded(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.9.1.4567/ase/transport/stm.py0000664000175000017500000001653612553425527020473 0ustar jensjjensj00000000000000import 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 = list(range(nbf1_small))# XXX -||- coupling_list2 = list(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 = sorted(-np.array([bias * self.w, bias * (self.w - 1)])) 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.9.1.4567/ase/transport/tools.py0000664000175000017500000003420112553425527021015 0ustar jensjjensj00000000000000from __future__ import print_function 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 range(nb_sub): for j in range(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, np.real(Za), np.imag(Za), np.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.9.1.4567/ase/phasediagram.py0000664000175000017500000005060412553425526020252 0ustar jensjjensj00000000000000from __future__ import division, print_function import fractions import functools import re import numpy as np from scipy.spatial import ConvexHull, Delaunay import ase.units as units from ase.atoms import string2symbols from ase.utils import hill _solvated = [] def parse_formula(formula): aq = formula.endswith('(aq)') if aq: formula = formula[:-4] charge = formula.count('+') - formula.count('-') if charge: formula = formula.rstrip('+-') count = {} for symbol in string2symbols(formula): count[symbol] = count.get(symbol, 0) + 1 return count, charge, aq def float2str(x): f = fractions.Fraction(x).limit_denominator(100) n = f.numerator d = f.denominator if abs(n / d - f) > 1e-6: return '{0:.3f}'.format(f) if d == 0: return '0' if f.denominator == 1: return str(n) return '{0}/{1}'.format(f.numerator, f.denominator) def solvated(symbols): """Extract solvation energies from database. symbols: str Extract only those molecules that contain the chemical elements given by the symbols string (plus water and H+). Data from: Johnson JW, Oelkers EH, Helgeson HC (1992) Comput Geosci 18(7):899. doi:10.1016/0098-3004(92)90029-Q and: Pourbaix M (1966) Atlas of electrochemical equilibria in aqueous solutions. No. v. 1 in Atlas of Electrochemical Equilibria in Aqueous Solutions. Pergamon Press, New York. Returns list of (name, energy) tuples. """ if isinstance(symbols, str): symbols = set(string2symbols(symbols)) if len(_solvated) == 0: for line in _aqueous.splitlines(): energy, formula = line.split(',') name = formula + '(aq)' count, charge, aq = parse_formula(name) energy = float(energy) * 0.001 * units.kcal / units.mol _solvated.append((name, count, charge, aq, energy)) references = [] for name, count, charge, aq, energy in _solvated: for symbol in count: if symbol not in 'HO' and symbol not in symbols: break else: references.append((name, energy)) return references def bisect(A, X, Y, f): a = [] for i in [0, -1]: for j in [0, -1]: if A[i, j] == -1: A[i, j] = f(X[i], Y[j]) a.append(A[i, j]) if np.ptp(a) == 0: A[:] = a[0] return if a[0] == a[1]: A[0] = a[0] if a[1] == a[3]: A[:, -1] = a[1] if a[3] == a[2]: A[-1] = a[3] if a[2] == a[0]: A[:, 0] = a[2] if not (A == -1).any(): return i = len(X) // 2 j = len(Y) // 2 bisect(A[:i + 1, :j + 1], X[:i + 1], Y[:j + 1], f) bisect(A[:i + 1, j:], X[:i + 1], Y[j:], f) bisect(A[i:, :j + 1], X[i:], Y[:j + 1], f) bisect(A[i:, j:], X[i:], Y[j:], f) def print_results(results): total_energy = 0.0 print('reference coefficient energy') print('------------------------------------') for name, coef, energy in results: total_energy += coef * energy if abs(coef) < 1e-7: continue print('{0:14}{1:>10}{2:12.3f}'.format(name, float2str(coef), energy)) print('------------------------------------') print('Total energy: {0:22.3f}'.format(total_energy)) print('------------------------------------') class Pourbaix: def __init__(self, references, formula=None, T=300.0, **kwargs): """Pourbaix object. references: list of (name, energy) tuples Examples of names: ZnO2, H+(aq), H2O(aq), Zn++(aq), ... formula: str Stoichiometry. Example: ``'ZnO'``. Can also be given as keyword arguments: ``Pourbaix(refs, Zn=1, O=1)``. T: float Temperature in Kelvin. """ if formula: assert not kwargs kwargs = parse_formula(formula)[0] self.kT = units.kB * T self.references = [] for name, energy in references: if name == 'O': continue count, charge, aq = parse_formula(name) for symbol in count: if aq: if not (symbol in 'HO' or symbol in kwargs): break else: if symbol not in kwargs: break else: self.references.append((count, charge, aq, energy, name)) self.references.append(({}, -1, False, 0.0, 'e-')) # an electron self.count = kwargs if 'O' not in self.count: self.count['O'] = 0 self.N = {'e-': 0, 'H': 1} for symbol in kwargs: if symbol not in self.N: self.N[symbol] = len(self.N) def decompose(self, U, pH, verbose=True, concentration=1e-6): """Decompose material. U: float Potential in eV. pH: float pH value. verbose: bool Default is True. concentration: float Concentration of solvated references. Returns optimal coefficients and energy. """ alpha = np.log(10) * self.kT entropy = -np.log(concentration) * self.kT # We want to minimize np.dot(energies, x) under the constraints: # # np.dot(x, eq2) == eq1 # # with bounds[i,0] <= x[i] <= bounds[i, 1]. # # First two equations are charge and number of hydrogens, and # the rest are the remaining species. eq1 = [0, 0] + list(self.count.values()) eq2 = [] energies = [] bounds = [] names = [] for count, charge, aq, energy, name in self.references: eq = np.zeros(len(self.N)) eq[0] = charge for symbol, n in count.items(): eq[self.N[symbol]] = n eq2.append(eq) if name in ['H2O(aq)', 'H+(aq)', 'e-']: bounds.append((-np.inf, np.inf)) if name == 'e-': energy = -U elif name == 'H+(aq)': energy = -pH * alpha else: bounds.append((0, 1)) if aq: energy -= entropy if verbose: print('{0:<5}{1:10}{2:10.3f}'.format(len(energies), name, energy)) energies.append(energy) names.append(name) try: from scipy.optimize import linprog except ImportError: from ase.utils._linprog import linprog result = linprog(energies, None, None, np.transpose(eq2), eq1, bounds) if verbose: print_results(zip(names, result.x, energies)) return result.x, result.fun def diagram(self, U, pH, plot=True, show=True): """Calculate Pourbaix diagram. U: list of float Potentials in eV. pH: list of float pH values. plot: bool Create plot. show: bool Show plot. """ a = np.empty((len(U), len(pH)), int) a[:] = -1 colors = {} f = functools.partial(self.colorfunction, colors=colors) bisect(a, U, pH, f) compositions = [None] * len(colors) names = [ref[-1] for ref in self.references] for indices, color in colors.items(): compositions[color] = ' + '.join(names[i] for i in indices if names[i] not in ['H2O(aq)', 'H+(aq)', 'e-']) text = [] for i, name in enumerate(compositions): b = (a == i) x = np.dot(b.sum(1), U) / b.sum() y = np.dot(b.sum(0), pH) / b.sum() name = re.sub('(\S)([+-]+)', r'\1$^{\2}$', name) name = re.sub('(\d+)', r'$_{\1}$', name) text.append((x, y, name)) if plot: import matplotlib.pyplot as plt import matplotlib.cm as cm plt.pcolormesh(pH, U, a, cmap=cm.Accent) for x, y, name in text: plt.text(y, x, name, horizontalalignment='center') plt.xlabel('pH') plt.ylabel('potential [eV]') plt.xlim(min(pH), max(pH)) plt.ylim(min(U), max(U)) if show: plt.show() return a, compositions, text def colorfunction(self, U, pH, colors): coefs, energy = self.decompose(U, pH, verbose=False) indices = tuple(sorted(np.where(abs(coefs) > 1e-7)[0])) color = colors.get(indices) if color is None: color = len(colors) colors[indices] = color return color class PhaseDiagram: def __init__(self, references, filter='', verbose=True): """Phase-diagram. references: list of (name, energy) tuples List of references. The names can also be dicts like ``{'Zn': 1, 'O': 2}`` which would be equivalent to ``'ZnO2'``. filter: str or list of str Use only those references that match the given filter. Example: ``filter='ZnO'`` will select those that contain zinc or oxygen. verbose: bool Write information. """ filter = parse_formula(filter)[0] self.verbose = verbose self.species = {} self.references = [] for name, energy in references: if isinstance(name, str): count = parse_formula(name)[0] else: count = name name = hill(count) if filter and any(symbol not in filter for symbol in count): continue natoms = 0 for symbol, n in count.items(): natoms += n if symbol not in self.species: self.species[symbol] = len(self.species) self.references.append((count, energy, name, natoms)) if verbose: print('Species:', ', '.join(self.species)) print('References:', len(self.references)) for i, (count, energy, name, natoms) in enumerate(self.references): print('{0:<5}{1:10}{2:10.3f}'.format(i, name, energy)) self.points = np.zeros((len(self.references), len(self.species) + 1)) for s, (count, energy, name, natoms) in enumerate(self.references): for symbol, n in count.items(): self.points[s, self.species[symbol]] = n / natoms self.points[s, -1] = energy / natoms hull = ConvexHull(self.points[:, 1:]) # Find relevant vertices: ok = hull.equations[:, -2] < 0 vertices = set() for simplex in hull.simplices[ok]: vertices.update(simplex) self.vertices = np.array(list(vertices)) if verbose: print('Simplices:', ok.sum()) # Create triangulation: if len(self.species) == 2: D = Delaunay1D # scipy's Delaunay doesn't like 1-d! else: D = Delaunay self.tri = D(self.points[self.vertices, 1:-1]) def decompose(self, formula=None, **kwargs): """Find the combination of the references with the lowest energy. formula: str Stoichiometry. Example: ``'ZnO'``. Can also be given as keyword arguments: ``decompose(Zn=1, O=1)``. Example:: pd = PhaseDiagram(...) pd.decompose(Zn=1, O=3) Returns energy, indices of references and coefficients.""" if formula: assert not kwargs kwargs = parse_formula(formula)[0] point = np.zeros(len(self.species)) natoms = 0 for symbol, n in kwargs.items(): point[self.species[symbol]] = n natoms += n i = self.tri.find_simplex(point[1:] / natoms) indices = self.vertices[self.tri.simplices[i]] points = self.points[indices] scaledcoefs = np.linalg.solve(points[:, :-1].T, point) energy = np.dot(scaledcoefs, points[:, -1]) coefs = [] results = [] for coef, s in zip(scaledcoefs, indices): count, e, name, natoms = self.references[s] coef /= natoms coefs.append(coef) results.append((name, coef, e)) if self.verbose: print_results(results) return energy, indices, np.array(coefs) def plot(self): """Plot datapoints and convex hull. Works only for 2 and 3 components systems. """ if len(self.species) == 2: self.plot2d() elif len(self.species) == 3: self.plot3d() else: raise ValueError('...') def plot2d(self): import matplotlib.pyplot as plt x, y = self.points[:, 1:].T xsymbol = [symbol for symbol, id in self.species.items() if id == 1][0] plt.plot(x, y, 'or') for i, j in self.tri.simplices: plt.plot([x[i], x[j]], [y[i], y[j]], '-g') for count, energy, name, natoms in self.references: name = re.sub('(\d+)', r'$_{\1}$', name) plt.text(count.get(xsymbol, 0) / natoms, energy / natoms, name, horizontalalignment='center', verticalalignment='bottom') plt.xlabel(xsymbol) plt.ylabel('energy') plt.show() class Delaunay1D: """Simple 1-d implementation.""" def __init__(self, points): self.points = points[:, 0] a = self.points.argsort() self.simplices = np.array([a[:-1], a[1:]]).T def find_simplex(self, point): p = point[0] for i, s in enumerate(self.simplices[:, 1]): if p < self.points[s]: return i return i + 1 _aqueous = """\ -525700,SiF6-- -514100,Rh(SO4)3---- -504800,Ru(SO4)3---- -499900,Pd(SO4)3---- -495200,Ru(SO4)3--- -485700,H4P2O7 -483700,Rh(SO4)3--- -483600,H3P2O7- -480400,H2P2O7-- -480380,Pt(SO4)3---- -471400,HP2O7--- -458700,P2O7---- -447500,LaF4- -437600,LaH2PO4++ -377900,LaF3 -376299,Ca(HSiO3)+ -370691,BeF4-- -355400,BF4- -353025,Mg(HSiO3)+ -346900,LaSO4+ -334100,Rh(SO4)2-- -325400,Ru(SO4)2-- -319640,Pd(SO4)2-- -317900,Ru(SO4)2- -312970,Cr2O7-- -312930,CaSO4 -307890,NaHSiO3 -307800,LaF2+ -307000,LaHCO3++ -306100,Rh(SO4)2- -302532,BeF3- -300670,Pt(SO4)2-- -299900,LaCO3+ -289477,MgSO4 -288400,LaCl4- -281500,HZrO3- -279200,HHfO3- -276720,Sr(HCO3)+ -275700,Ba(HCO3)+ -273830,Ca(HCO3)+ -273100,H3PO4 -270140,H2PO4- -266500,S2O8-- -264860,Sr(CO3) -264860,SrCO3 -263830,Ba(CO3) -263830,BaCO3 -262850,Ca(CO3) -262850,CaCO3 -260310,HPO4-- -257600,LaCl3 -250200,Mg(HCO3)+ -249200,H3VO4 -248700,S4O6-- -246640,KSO4- -243990,H2VO4- -243500,PO4--- -243400,KHSO4 -242801,HSiO3- -241700,HYO2 -241476,NaSO4- -239700,HZrO2+ -239300,LaO2H -238760,Mg(CO3) -238760,MgCO3 -237800,HHfO2+ -236890,Ag(CO3)2--- -236800,HNbO3 -236600,LaF++ -235640,MnSO4 -233400,ZrO2 -233000,HVO4-- -231600,HScO2 -231540,B(OH)3 -231400,HfO2 -231386,BeF2 -231000,S2O6-- -229000,S3O6-- -229000,S5O6-- -228460,HTiO3- -227400,YO2- -227100,NbO3- -226700,LaCl2+ -223400,HWO4- -221700,LaO2- -218500,WO4-- -218100,ScO2- -214900,VO4--- -210000,YOH++ -208900,LaOH++ -207700,HAlO2 -206400,HMoO4- -204800,H3PO3 -202350,H2PO3- -202290,SrF+ -201807,BaF+ -201120,BaF+ -200400,MoO4-- -200390,CaF+ -199190,SiO2 -198693,AlO2- -198100,YO+ -195900,LaO+ -195800,LaCl++ -194000,CaCl2 -194000,HPO3-- -191300,LaNO3++ -190400,ZrOH+++ -189000,HfOH+++ -189000,S2O5-- -187600,ZrO++ -186000,HfO++ -183700,HCrO4- -183600,ScO+ -183100,H3AsO4 -180630,HSO4- -180010,H2AsO4- -177930,SO4-- -177690,MgF+ -174800,CrO4-- -173300,SrOH+ -172300,BaOH+ -172200,HBeO2- -171300,CaOH+ -170790,HAsO4-- -166000,ReO4- -165800,SrCl+ -165475,Al(OH)++ -165475,AlOH++ -164730,BaCl+ -164000,La+++ -163800,Y+++ -163100,CaCl+ -162240,BO2- -158493,BeF+ -158188,AlO+ -155700,VOOH+ -155164,CdF2 -154970,AsO4--- -153500,Rh(SO4) -152900,BeO2-- -152370,HSO5- -151540,RuCl6--- -149255,MgOH+ -147400,H2S2O4 -146900,HS2O4- -146081,CdCl4-- -145521,BeCl2 -145200,Ru(SO4) -145056,PbF2 -143500,S2O4-- -140330,H2AsO3- -140300,VO2+ -140282,HCO3- -140200,Sc+++ -139900,BeOH+ -139700,MgCl+ -139200,Ru(SO4)+ -139000,Pd(SO4) -138160,HF2- -138100,HCrO2 -138000,TiO++ -137300,HGaO2 -136450,RbF -134760,Sr++ -134030,Ba++ -133270,Zr++++ -133177,PbCl4-- -132600,Hf++++ -132120,Ca++ -129310,ZnCl3- -128700,GaO2- -128600,BeO -128570,NaF -128000,H2S2O3 -127500,Rh(SO4)+ -127200,HS2O3- -126191,CO3-- -126130,HSO3- -125300,CrO2- -125100,H3PO2 -124900,S2O3-- -123641,MnF+ -122400,H2PO2- -121000,HMnO2- -120700,RuCl5-- -120400,MnO4-- -120300,Pt(SO4) -119800,HInO2 -116300,SO3-- -115971,CdCl3- -115609,Al+++ -115316,BeCl+ -112280,AgCl4--- -111670,TiO2++ -111500,VOH++ -111430,Ag(CO3)- -110720,HZnO2- -108505,Mg++ -108100,HSeO4- -108000,LiOH -107600,MnO4- -106988,HgCl4-- -106700,InO2- -106700,VO++ -106100,VO+ -105500,SeO4-- -105100,RbOH -105000,CsOH -104500,KOH -104109,ZnF+ -103900,PdCl4-- -103579,CuCl4-- -102600,MnO2-- -102150,PbCl3- -101850,H2SeO3 -101100,HFeO2 -100900,CsCl -100500,CrOH++ -99900,NaOH -99800,VOH+ -99250,LiCl -98340,HSeO3- -98300,ZnCl2 -97870,RbCl -97400,HSbO2 -97300,HSnO2- -97300,MnOH+ -97016,InF++ -96240,HAsO2 -95430,KCl -95400,HFeO2- -94610,CsBr -93290,ZnO2-- -93250,RhCl4-- -92910,NaCl -92800,CrO+ -92250,CO2 -91210,PtCl4-- -91157,FeF+ -91100,GaOH++ -91010,RbBr -90550,Be++ -90010,KBr -89963,CuCl3-- -89730,RuCl4- -88400,SeO3-- -88000,FeO2- -87373,CdF+ -86600,GaO+ -86500,HCdO2- -86290,MnCl+ -85610,NaBr -84851,CdCl2 -83900,RuCl4-- -83650,AsO2- -83600,Ti+++ -83460,CsI -83400,HCoO2- -82710,AgCl3-- -82400,SbO2- -81980,HNiO2- -81732,CoF+ -81500,MnO -81190,ZnOH+ -81000,HPbO2- -79768,NiF+ -79645,FeF++ -79300,HBiO2 -78900,RbI -77740,KI -77700,La++ -77500,RhCl4- -75860,PbF+ -75338,CuCl3- -75216,TlF -75100,Ti++ -74600,InOH++ -74504,HgCl3- -73480,FeCl2 -72900,NaI -71980,SO2 -71662,HF -71600,RuO4-- -71200,PbCl2 -69933,Li+ -69810,PdCl3- -69710,Cs+ -69400,InO+ -67811,AuCl3-- -67800,Rb+ -67510,K+ -67420,ZnO -67340,F- -67300,CdO2-- -66850,ZnCl+ -65850,FeOH+ -65550,TlOH -64200,NiO2-- -63530,RhCl3- -63200,CoO2-- -62591,Na+ -61700,BiO2- -61500,CdOH+ -60100,HCuO2- -59226,InCl++ -58600,SnOH+ -58560,RuCl3 -58038,CuCl2- -57900,V+++ -57800,FeOH++ -57760,PtCl3- -57600,HTlO2 -56690,H2O -56025,CoOH+ -55100,Mn++ -54380,RuCl3- -53950,PbOH+ -53739,CuF+ -53600,SnO -53100,FeO+ -53030,FeCl+ -52850,NiOH+ -52627,CdCl+ -52000,V++ -51560,AgCl2- -50720,FeO -49459,AgF -49300,Cr+++ -47500,CdO -46190,RhCl3 -46142,CuCl2 -45200,HHgO2- -45157,CoCl+ -44000,CoO -42838,HgCl2 -41600,TlO2- -41200,CuO2-- -40920,NiCl+ -39815,TlCl -39400,Cr++ -39350,PbO -39340,NiO -39050,PbCl+ -38000,Ga+++ -37518,FeCl++ -36781,AuCl2- -35332,AuCl4- -35200,Zn++ -35160,PdCl2 -33970,RhCl2 -32300,BiOH++ -31700,HIO3 -31379,Cl- -30600,IO3- -30410,HCl -30204,HgF+ -30200,CuOH+ -29300,BiO+ -28682,CO -26507,NO3- -26440,RuCl2+ -25590,Br3- -25060,RuCl2 -24870,Br- -24730,HNO3 -23700,HIO -23400,In+++ -23280,OCN- -23000,CoOH++ -22608,CuCl -22290,PtCl2 -21900,AgOH -21870,Fe++ -20800,CuO -20300,Mn+++ -20058,Pb(HS)2 -19700,HBrO -19100,HClO -19100,ScOH++ -18990,NH4+ -18971,Pb(HS)3- -18560,Cd++ -18290,Rh(OH)+ -17450,AgCl -16250,CuCl+ -14780,RhCl2+ -14000,IO4- -13130,Pd(OH)+ -13000,Co++ -12700,HgOH+ -12410,I- -12300,I3- -12190,Ru(OH)++ -12100,HNO2 -11500,PdO -10900,Ni++ -10470,Ru(OH)+ -10450,RuO+ -9200,IO- -8900,HgO -8800,ClO- -8000,BrO- -7740,Tl+ -7738,AgNO3 -7700,NO2- -7220,RhO -6673,H2S -6570,Sn++ -6383,NH3 -5710,Pb++ -5500,AgO- -4500,TlOH++ -4120,Fe+++ -3380,RhCl+ -3200,TlO+ -3184,AuCl -2155,HgCl+ -2040,ClO4- -1900,ClO3- -1130,PtO -820,Rh(OH)++ 0,Ag(HS)2- 0,H+ 230,RuO 1400,HClO2 1560,Pt(OH)+ 2429,Au(HS)2- 2500,PdCl+ 2860,HS- 3140,RhO+ 3215,Xe 3554,Kr 3890,Ar 4100,ClO2- 4347,N2 4450,BrO3- 4565,Ne 4658,He 5210,RuCl+ 7100,RuCl++ 8600,H2N2O2 9375,TlCl++ 10500,HSe- 11950,Cu+ 15675,Cu++ 15700,S5-- 16500,S4-- 17600,S3-- 18200,HN2O2- 18330,RhCl++ 18380,PtCl+ 18427,Ag+ 19000,S2-- 19500,SeCN- 19700,N2H5+ 21100,N2H6++ 22160,SCN- 22880,Bi+++ 27700,Rh++ 28200,BrO4- 28600,HCN 32000,Co+++ 33200,N2O2-- 35900,Ru++ 36710,Hg2++ 39360,Hg++ 41200,CN- 41440,Ru+++ 42200,Pd++ 51300,Tl+++ 52450,Rh+++ 61600,Pt++ 64300,Ag++ 103600,Au+++""" python-ase-3.9.1.4567/ase/dft/0000775000175000017500000000000012553427753016027 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/dft/__init__.py0000664000175000017500000000142012553425527020132 0ustar jensjjensj00000000000000import numpy as np from ase.dft.stm import STM from ase.dft.dos import DOS from ase.dft.wannier import Wannier from ase.dft.kpoints import monkhorst_pack def get_distribution_moment(x, y, order=0): """Return the moment of nth order of distribution. 1st and 2nd order moments of a band correspond to the band's center and width respectively. For integration, the trapezoid rule is used. """ x = np.asarray(x) y = np.asarray(y) if order == 0: return np.trapz(y, x) elif isinstance(order, int): return np.trapz(x**order * y, x) / np.trapz(y, x) elif hasattr(order, '__iter__'): return [get_distribution_moment(x, y, n) for n in order] else: raise ValueError('Illegal order: %s' % order) python-ase-3.9.1.4567/ase/dft/dos.py0000664000175000017500000000425312553425527017167 0ustar jensjjensj00000000000000from math import pi, sqrt import numpy as np class DOS: def __init__(self, calc, width=0.1, window=None, npts=201): """Electronic Density Of States object. calc: calculator object Any ASE compliant calculator object. width: float Width of guassian smearing. window: tuple of two float Use ``window=(emin, emax)``. If not specified, a window big enough to hold all the eigenvalues will be used. npts: int Number of points. """ self.npts = npts self.width = width self.w_k = calc.get_k_point_weights() self.nspins = calc.get_number_of_spins() self.e_skn = np.array([[calc.get_eigenvalues(kpt=k, spin=s) for k in range(len(self.w_k))] for s in range(self.nspins)]) self.e_skn -= calc.get_fermi_level() if window is None: emin = self.e_skn.min() - 5 * self.width emax = self.e_skn.max() + 5 * self.width else: emin, emax = window self.energies = np.linspace(emin, emax, npts) def get_energies(self): """Return the array of energies used to sample the DOS. The energies are reported relative to the Fermi level.""" return self.energies def delta(self, energy): """Return a delta-function centered at 'energy'.""" x = -((self.energies - energy) / self.width)**2 return np.exp(x) / (sqrt(pi) * self.width) def get_dos(self, spin=None): """Get array of DOS values. The *spin* argument can be 0 or 1 (spin up or down) - if not specified, the total DOS is returned. """ if spin is None: if self.nspins == 2: # Spin-polarized calculation, but no spin specified - # return the total DOS: return self.get_dos(spin=0) + self.get_dos(spin=1) else: spin = 0 dos = np.zeros(self.npts) for w, e_n in zip(self.w_k, self.e_skn[spin]): for e in e_n: dos += w * self.delta(e) return dos python-ase-3.9.1.4567/ase/dft/pars_beefvdw.py0000664000175000017500000005616212553425527021057 0ustar jensjjensj00000000000000import numpy as np """ BEEF-vdW ensemble matrix """ uiOmega = np.array([ [ 9.238289896663336e-02 , 1.573812432079919e-01 , 1.029935738540308e-01 , 1.366003143143216e-02 , -2.170819634832974e-02 , -1.971473025898487e-03 , 6.694499988752175e-03 , -1.436837103528228e-03 , -1.894288263659829e-03 , 1.620730202731354e-03 , 3.342742083591797e-05 , -8.935288190655010e-04 , 5.660396510944252e-04 , 1.092640880494036e-04 , -3.909536572033999e-04 , 2.271387694573118e-04 , 4.720081507064245e-05 , -1.728805247746040e-04 , 1.161095890105822e-04 , 1.632569772443308e-05 , -9.505329207480296e-05 , 5.966357079138161e-05 , 3.909940118293563e-05 , -9.094078397503243e-05 , 3.979403197298154e-05 , 5.883724662690913e-05 , -8.868728142026543e-05 , 1.649195968392651e-05 , 3.986378541237102e-05 , -2.080734204109696e-05 , -5.210020320050114e-02 ], [ 1.573812432080020e-01 , 3.194503568212250e-01 , 2.330350019456029e-01 , 3.539526885754365e-02 , -4.398162505429017e-02 , -7.870052015456349e-03 , 1.288386845762548e-02 , -1.452985165647521e-03 , -3.414852982913958e-03 , 2.242106483095301e-03 , 2.411666744826487e-04 , -1.065238741066354e-03 , 4.135880276069384e-04 , 2.536775346693924e-04 , -2.530397572915468e-04 , -5.690638693892032e-05 , 1.673844673999724e-04 , -9.944997873568069e-06 , -1.718953440120930e-04 , 1.760399953825598e-04 , -4.156338135631344e-06 , -1.832004402941794e-04 , 2.147464735651294e-04 , -6.193272093284920e-05 , -1.319710553323893e-04 , 1.948452573660156e-04 , -5.101630490846988e-05 , -9.176394513865211e-05 , 4.717722996545362e-05 , 7.111249931485782e-06 , -1.890906559696380e-02 ], [ 1.029935738540465e-01 , 2.330350019456185e-01 , 1.906771663140688e-01 , 4.596131842244390e-02 , -2.792908137436464e-02 , -1.240232492150593e-02 , 5.672917933168648e-03 , 1.434385697982085e-03 , -9.455904542077782e-04 , 3.036359098459168e-05 , 1.161828188486106e-04 , 7.937359374341367e-05 , -1.452498186750268e-04 , 1.384058476815110e-05 , 1.530299855805981e-04 , -1.908370243275392e-04 , 5.614920168522352e-05 , 1.448595900033545e-04 , -2.366731351667913e-04 , 1.303628937641542e-04 , 8.403491035544659e-05 , -2.162539474930004e-04 , 1.579894933576654e-04 , 1.853443013110853e-05 , -1.453365923716440e-04 , 1.270119640983266e-04 , 1.393651877686879e-05 , -8.735349638010247e-05 , 1.562163815156337e-05 , 1.819382613180743e-05 , 1.382668594717776e-02 ], [ 1.366003143144247e-02 , 3.539526885755911e-02 , 4.596131842245237e-02 , 3.412600355844948e-02 , 5.788002236623282e-03 , -9.314441356035262e-03 , -5.276305980529734e-03 , 2.351769282262449e-03 , 1.746899840570664e-03 , -1.053810170761046e-03 , -2.902616086744972e-04 , 5.752547360555607e-04 , -8.857003353891879e-05 , -2.395794347875841e-04 , 1.413569388536142e-04 , 5.605747482892052e-05 , -9.488998643296934e-05 , 2.026963310534137e-05 , 3.772638762355388e-05 , -4.067190865485931e-05 , 1.321492117521963e-05 , 1.940880629107831e-05 , -3.480998018498056e-05 , 1.778991053651829e-05 , 1.586887875776044e-05 , -3.017037178432038e-05 , 6.647594986708508e-06 , 1.545376441325688e-05 , -5.578313586587479e-06 , -2.498675358121092e-06 , -7.076421937394695e-03 ], [ -2.170819634832771e-02 , -4.398162505428508e-02 , -2.792908137435959e-02 , 5.788002236625639e-03 , 1.599472206930952e-02 , 1.608917143245890e-03 , -5.597384471167169e-03 , -1.499164748509191e-03 , 1.031475806000458e-03 , 5.332996506181574e-04 , -2.489713532023827e-04 , -1.029965243518429e-04 , 1.699409468310518e-04 , -5.189717276078564e-05 , -6.126197146900113e-05 , 8.454620554637730e-05 , -2.898403340456230e-05 , -4.695866195676658e-05 , 7.705234549813160e-05 , -3.658438803802928e-05 , -3.319317982415972e-05 , 6.573717163798472e-05 , -3.698152620572900e-05 , -1.629294629181860e-05 , 4.241341573520274e-05 , -2.624727597577873e-05 , -1.229090821564833e-05 , 2.348090332681114e-05 , -2.215657597169080e-07 , -6.444872622959645e-06 , 7.322667111791249e-04 ], [ -1.971473025900972e-03 , -7.870052015460869e-03 , -1.240232492150907e-02 , -9.314441356035836e-03 , 1.608917143246348e-03 , 7.634754660592785e-03 , 2.015667017611551e-03 , -3.623574339977459e-03 , -1.474755821692741e-03 , 1.127995802260326e-03 , 4.639737083120432e-04 , -4.567637545650261e-04 , -2.016876766012911e-05 , 2.508509815496272e-04 , -1.147671414054848e-04 , -7.415040892571524e-05 , 9.932046149486572e-05 , -1.325820303664777e-05 , -5.028147494244732e-05 , 4.435536803388949e-05 , -2.227553213442618e-06 , -3.139708798837062e-05 , 3.307650446358692e-05 , -6.558671845195734e-06 , -2.123041867524418e-05 , 2.397646436678162e-05 , 9.138618011606733e-07 , -1.527849014454442e-05 , 2.261408120954423e-06 , 3.617283769859004e-06 , 2.325697711871941e-03 ], [ 6.694499988750638e-03 , 1.288386845762195e-02 , 5.672917933165492e-03 , -5.276305980530938e-03 , -5.597384471167074e-03 , 2.015667017611739e-03 , 4.377508336814056e-03 , 4.100359917331289e-04 , -1.876150671093797e-03 , -7.271917289430953e-04 , 4.632933527994722e-04 , 2.963398987389869e-04 , -1.506945170950558e-04 , -5.149346314745077e-05 , 9.215110292974351e-05 , -3.132804577761338e-05 , -2.100641270393858e-05 , 3.506730172274297e-05 , -2.465494126635098e-05 , 1.240900749825681e-06 , 2.076535734347166e-05 , -2.285062874633954e-05 , 4.208354769194986e-06 , 1.425348474305690e-05 , -1.526811061895161e-05 , 3.047660598079506e-06 , 9.299255727538788e-06 , -8.183025849838069e-06 , -2.016271133614633e-06 , 3.118202698102115e-06 , -1.983005807705875e-03 ], [ -1.436837103527614e-03 , -1.452985165646303e-03 , 1.434385697983009e-03 , 2.351769282262657e-03 , -1.499164748509336e-03 , -3.623574339977513e-03 , 4.100359917331572e-04 , 3.388139698932502e-03 , 4.194131188659545e-04 , -1.640686728848097e-03 , -4.535159587025243e-04 , 5.155942974268080e-04 , 1.219637950738874e-04 , -1.881362361335498e-04 , 5.406677887798438e-05 , 6.730117550948196e-05 , -6.826604522477651e-05 , -7.600076704978491e-08 , 4.545041141091276e-05 , -3.434406804211548e-05 , -5.396753498031206e-06 , 3.160900890445868e-05 , -2.489184945477622e-05 , -2.480536094745677e-06 , 2.230938441981598e-05 , -1.767486060639981e-05 , -6.845063675872953e-06 , 1.581526117380142e-05 , 2.198506926484949e-07 , -4.837425950871762e-06 , -2.819410239268639e-05 ], [ -1.894288263659430e-03 , -3.414852982912986e-03 , -9.455904542068480e-04 , 1.746899840571073e-03 , 1.031475806000471e-03 , -1.474755821692797e-03 , -1.876150671093806e-03 , 4.194131188659666e-04 , 2.016821929004358e-03 , 2.913183096117767e-04 , -1.031831612901280e-03 , -3.523961692265613e-04 , 3.020345263188065e-04 , 1.358462914820522e-04 , -1.115872186939481e-04 , 4.093795217439325e-06 , 4.590005891560275e-05 , -2.788695451888706e-05 , -4.445454868386084e-06 , 1.774618276396958e-05 , -1.122137909788981e-05 , -3.231227423595720e-06 , 1.210473810098234e-05 , -7.926468935313864e-06 , -3.432017428898823e-06 , 8.827938351713780e-06 , -2.192391060027345e-06 , -4.171466247118773e-06 , 1.331053824099077e-06 , 8.121122753847691e-07 , 1.468573793837378e-03 ], [ 1.620730202730968e-03 , 2.242106483094428e-03 , 3.036359098381830e-05 , -1.053810170761330e-03 , 5.332996506181955e-04 , 1.127995802260379e-03 , -7.271917289430953e-04 , -1.640686728848104e-03 , 2.913183096117794e-04 , 1.618640260028683e-03 , 1.578833514403573e-04 , -8.684832913376226e-04 , -1.835212360942493e-04 , 2.681276727854413e-04 , 3.285354767345348e-05 , -7.506050741939204e-05 , 4.030911032027864e-05 , 1.270499721233960e-05 , -3.550009040339185e-05 , 2.093845130027192e-05 , 6.936412133339431e-06 , -2.092061019101916e-05 , 1.263627438389547e-05 , 5.132905197400893e-06 , -1.410173385828192e-05 , 8.068421998377687e-06 , 6.590533164499491e-06 , -9.628875957888051e-06 , -1.186884523575427e-06 , 3.379003341108947e-06 , -1.318935000558665e-03 ], [ 3.342742083582248e-05 , 2.411666744824321e-04 , 1.161828188484188e-04 , -2.902616086745682e-04 , -2.489713532023758e-04 , 4.639737083120528e-04 , 4.632933527994702e-04 , -4.535159587025258e-04 , -1.031831612901280e-03 , 1.578833514403571e-04 , 1.126887798536041e-03 , 1.596306400901984e-04 , -6.262219982793480e-04 , -1.832949555936158e-04 , 2.062011811517906e-04 , 5.639579837834072e-05 , -7.429445085205222e-05 , 1.947674856272851e-05 , 2.925850101283131e-05 , -3.392404367734551e-05 , 7.606268115327377e-06 , 1.774935646371143e-05 , -2.076809415497982e-05 , 3.678275105655822e-06 , 1.351664987117452e-05 , -1.391917758734145e-05 , -3.264922954751679e-06 , 1.128720431864021e-05 , -1.552278484090616e-07 , -3.464691582178041e-06 , 2.259380952893320e-04 ], [ -8.935288190652161e-04 , -1.065238741065750e-03 , 7.937359374391768e-05 , 5.752547360557256e-04 , -1.029965243518811e-04 , -4.567637545650542e-04 , 2.963398987389943e-04 , 5.155942974268113e-04 , -3.523961692265653e-04 , -8.684832913376213e-04 , 1.596306400901987e-04 , 9.274502975544414e-04 , 4.771446682359326e-05 , -5.007069662988802e-04 , -7.942270207742560e-05 , 1.322450571128168e-04 , 2.441262913064850e-05 , -2.756468125262591e-05 , 6.943645566973078e-06 , 1.041750480940249e-05 , -1.187862037244014e-05 , 1.702364109770825e-06 , 7.400825614557900e-06 , -6.767501859886680e-06 , -7.456805310854244e-07 , 5.695968329623519e-06 , -2.204234030240727e-06 , -2.458146094280224e-06 , 1.077364537604088e-06 , 4.312391512705764e-07 , 5.884326361165565e-04 ], [ 5.660396510942980e-04 , 4.135880276066762e-04 , -1.452498186752349e-04 , -8.857003353897563e-05 , 1.699409468310743e-04 , -2.016876766011903e-05 , -1.506945170950608e-04 , 1.219637950738874e-04 , 3.020345263188087e-04 , -1.835212360942504e-04 , -6.262219982793482e-04 , 4.771446682359360e-05 , 7.353511125371758e-04 , 8.054171359132859e-05 , -4.354044149858314e-04 , -6.575758219487838e-05 , 1.322779340443631e-04 , 4.893233447412187e-06 , -2.860359932846397e-05 , 1.985815168274937e-05 , 1.407122212777636e-06 , -1.355631776270834e-05 , 9.804336837952511e-06 , 1.705077595669618e-06 , -8.448838581047592e-06 , 5.271239541237292e-06 , 3.753161433794400e-06 , -5.679341230392703e-06 , -7.297839478992945e-07 , 1.996414791054073e-06 , -5.689656491774725e-04 ], [ 1.092640880493588e-04 , 2.536775346692864e-04 , 1.384058476804722e-05 , -2.395794347876363e-04 , -5.189717276079290e-05 , 2.508509815496312e-04 , -5.149346314745000e-05 , -1.881362361335514e-04 , 1.358462914820523e-04 , 2.681276727854418e-04 , -1.832949555936157e-04 , -5.007069662988805e-04 , 8.054171359132875e-05 , 5.670985721529502e-04 , 4.105350281394086e-05 , -3.243779076268346e-04 , -5.693079967475888e-05 , 9.476238507687856e-05 , 1.671992883730651e-05 , -2.625490072653236e-05 , 1.094711235171939e-05 , 8.092095182176009e-06 , -1.368592923368957e-05 , 4.725521343618847e-06 , 6.462723202671019e-06 , -8.176454311340966e-06 , -1.037965911726869e-06 , 5.963104944027835e-06 , -2.287646204875769e-07 , -1.804397982061943e-06 , 6.675499678278738e-05 ], [ -3.909536572033257e-04 , -2.530397572913827e-04 , 1.530299855807417e-04 , 1.413569388536693e-04 , -6.126197146900289e-05 , -1.147671414054899e-04 , 9.215110292974495e-05 , 5.406677887798494e-05 , -1.115872186939490e-04 , 3.285354767345385e-05 , 2.062011811517907e-04 , -7.942270207742549e-05 , -4.354044149858315e-04 , 4.105350281394089e-05 , 5.023053531078210e-04 , 1.395753202566780e-05 , -2.794248341066854e-04 , -2.462616877967573e-05 , 7.014950575686348e-05 , 7.678983396148418e-06 , -1.200073137869544e-05 , 4.735853628377502e-06 , 3.823008200476699e-06 , -5.632608045337210e-06 , 1.401726052082347e-06 , 2.631914429094741e-06 , -1.879900165857796e-06 , -6.802392260490853e-07 , 6.412891565621652e-07 , 5.793723170821993e-08 , 2.979440856739876e-04 ], [ 2.271387694572524e-04 , -5.690638693903491e-05 , -1.908370243276230e-04 , 5.605747482890452e-05 , 8.454620554639201e-05 , -7.415040892571150e-05 , -3.132804577761707e-05 , 6.730117550948228e-05 , 4.093795217440853e-06 , -7.506050741939299e-05 , 5.639579837834042e-05 , 1.322450571128173e-04 , -6.575758219487839e-05 , -3.243779076268348e-04 , 1.395753202566789e-05 , 4.086277915281374e-04 , 2.438181614175771e-05 , -2.406201469878970e-04 , -2.063418073175250e-05 , 6.468348516289834e-05 , 1.651842998945461e-06 , -1.016330205472771e-05 , 7.380837404491689e-06 , 7.876901704903023e-07 , -5.693055610174383e-06 , 3.898194171094561e-06 , 1.890193310260514e-06 , -3.494268997347222e-06 , -2.097250054628417e-07 , 1.107934512468949e-06 , -2.578053969849174e-04 ], [ 4.720081507065945e-05 , 1.673844673999971e-04 , 5.614920168523253e-05 , -9.488998643297809e-05 , -2.898403340457248e-05 , 9.932046149486507e-05 , -2.100641270393638e-05 , -6.826604522477717e-05 , 4.590005891560220e-05 , 4.030911032027912e-05 , -7.429445085205212e-05 , 2.441262913064812e-05 , 1.322779340443633e-04 , -5.693079967475883e-05 , -2.794248341066855e-04 , 2.438181614175779e-05 , 3.367003211899217e-04 , 1.421493027932063e-05 , -1.961053122230117e-04 , -1.831760815509797e-05 , 5.249705849097755e-05 , 4.009767661794436e-06 , -9.222615132968448e-06 , 4.447935971545765e-06 , 2.844605015203588e-06 , -4.927439995523699e-06 , 2.779858179450743e-07 , 2.890920446156232e-06 , -3.536840533005166e-07 , -7.989052895188473e-07 , -2.873774500946350e-05 ], [ -1.728805247745767e-04 , -9.944997873510153e-06 , 1.448595900034050e-04 , 2.026963310536173e-05 , -4.695866195676680e-05 , -1.325820303664937e-05 , 3.506730172274367e-05 , -7.600076704937241e-08 , -2.788695451888763e-05 , 1.270499721233979e-05 , 1.947674856272868e-05 , -2.756468125262590e-05 , 4.893233447412072e-06 , 9.476238507687867e-05 , -2.462616877967574e-05 , -2.406201469878971e-04 , 1.421493027932067e-05 , 2.919803798609199e-04 , 7.292181033176667e-06 , -1.680274842794751e-04 , -1.103641130738799e-05 , 4.275283346882578e-05 , 1.839573029824585e-06 , -5.092906646915116e-06 , 2.996296133918005e-06 , 5.026786485483826e-07 , -1.803524706078249e-06 , 7.612853881615933e-07 , 3.175194859018497e-07 , -2.524196216716103e-07 , 2.671139718648832e-04 ], [ 1.161095890105204e-04 , -1.718953440122134e-04 , -2.366731351668826e-04 , 3.772638762353110e-05 , 7.705234549814230e-05 , -5.028147494244480e-05 , -2.465494126635465e-05 , 4.545041141091324e-05 , -4.445454868384867e-06 , -3.550009040339265e-05 , 2.925850101283112e-05 , 6.943645566973460e-06 , -2.860359932846412e-05 , 1.671992883730641e-05 , 7.014950575686358e-05 , -2.063418073175254e-05 , -1.961053122230117e-04 , 7.292181033176704e-06 , 2.476672606367232e-04 , 8.122604369362667e-06 , -1.452133704846186e-04 , -9.497391478575562e-06 , 3.809665940899583e-05 , 1.059672833862896e-06 , -5.566702444135148e-06 , 4.241342392780321e-06 , 1.125163314158913e-06 , -3.300826353062116e-06 , 2.381295916739009e-07 , 8.492464195141368e-07 , -2.789569803656198e-04 ], [ 1.632569772446249e-05 , 1.760399953826087e-04 , 1.303628937641828e-04 , -4.067190865486029e-05 , -3.658438803803874e-05 , 4.435536803388934e-05 , 1.240900749828609e-06 , -3.434406804211623e-05 , 1.774618276396873e-05 , 2.093845130027264e-05 , -3.392404367734537e-05 , 1.041750480940207e-05 , 1.985815168274956e-05 , -2.625490072653231e-05 , 7.678983396148288e-06 , 6.468348516289841e-05 , -1.831760815509795e-05 , -1.680274842794751e-04 , 8.122604369362710e-06 , 2.112966630126243e-04 , 5.363176092207731e-06 , -1.235778898069599e-04 , -7.709953870959738e-06 , 3.098655427549614e-05 , 2.634638058314591e-06 , -4.584365006125596e-06 , 7.784307399132289e-07 , 2.345452381285535e-06 , -6.188482408032955e-07 , -4.998403651495349e-07 , 8.079312086264899e-05 ], [ -9.505329207477657e-05 , -4.156338135574478e-06 , 8.403491035549607e-05 , 1.321492117523870e-05 , -3.319317982416059e-05 , -2.227553213444590e-06 , 2.076535734347213e-05 , -5.396753498031014e-06 , -1.122137909789006e-05 , 6.936412133339521e-06 , 7.606268115327406e-06 , -1.187862037244012e-05 , 1.407122212777626e-06 , 1.094711235171940e-05 , -1.200073137869545e-05 , 1.651842998945439e-06 , 5.249705849097757e-05 , -1.103641130738799e-05 , -1.452133704846186e-04 , 5.363176092207760e-06 , 1.841513653060571e-04 , 4.008684964031859e-06 , -1.088327175419565e-04 , -4.436272922923257e-06 , 2.663616882515994e-05 , 4.441129647729434e-07 , -1.823900470977472e-06 , 9.131027910925659e-07 , 3.423181895869568e-07 , -3.248030257457939e-07 , 1.565114731653676e-04 ], [ 5.966357079134110e-05 , -1.832004402942522e-04 , -2.162539474930512e-04 , 1.940880629106866e-05 , 6.573717163799288e-05 , -3.139708798836991e-05 , -2.285062874634257e-05 , 3.160900890445919e-05 , -3.231227423594649e-06 , -2.092061019101990e-05 , 1.774935646371122e-05 , 1.702364109771204e-06 , -1.355631776270847e-05 , 8.092095182175919e-06 , 4.735853628377626e-06 , -1.016330205472776e-05 , 4.009767661794407e-06 , 4.275283346882582e-05 , -9.497391478575592e-06 , -1.235778898069599e-04 , 4.008684964031889e-06 , 1.585945240480566e-04 , 4.814276592252276e-06 , -9.505942249560426e-05 , -5.269885642910686e-06 , 2.508762233822088e-05 , 1.002347324957512e-06 , -3.233685256439425e-06 , 3.615248228908033e-07 , 7.731232588721100e-07 , -2.364008973553363e-04 ], [ 3.909940118295615e-05 , 2.147464735651595e-04 , 1.579894933576790e-04 , -3.480998018498535e-05 , -3.698152620573602e-05 , 3.307650446358831e-05 , 4.208354769197900e-06 , -2.489184945477703e-05 , 1.210473810098150e-05 , 1.263627438389614e-05 , -2.076809415497966e-05 , 7.400825614557483e-06 , 9.804336837952683e-06 , -1.368592923368950e-05 , 3.823008200476585e-06 , 7.380837404491765e-06 , -9.222615132968445e-06 , 1.839573029824542e-06 , 3.809665940899589e-05 , -7.709953870959746e-06 , -1.088327175419565e-04 , 4.814276592252303e-06 , 1.387884209137800e-04 , 2.113244593212237e-06 , -8.153912579909763e-05 , -4.652337820383065e-06 , 1.937304772679640e-05 , 2.478096542996087e-06 , -8.169606503678209e-07 , -4.287488876009555e-07 , 1.035998031439656e-04 ], [ -9.094078397502061e-05 , -6.193272093282151e-05 , 1.853443013113500e-05 , 1.778991053653038e-05 , -1.629294629181825e-05 , -6.558671845197636e-06 , 1.425348474305646e-05 , -2.480536094745301e-06 , -7.926468935313898e-06 , 5.132905197400817e-06 , 3.678275105655839e-06 , -6.767501859886567e-06 , 1.705077595669545e-06 , 4.725521343618848e-06 , -5.632608045337194e-06 , 7.876901704902667e-07 , 4.447935971545785e-06 , -5.092906646915108e-06 , 1.059672833862867e-06 , 3.098655427549616e-05 , -4.436272922923254e-06 , -9.505942249560430e-05 , 2.113244593212259e-06 , 1.241068277448159e-04 , 1.324825159079387e-06 , -7.356715084057034e-05 , -1.785631352650215e-06 , 1.695100826863567e-05 , 5.774682432637083e-07 , -3.303613432465353e-07 , 9.651449332646128e-05 ], [ 3.979403197295345e-05 , -1.319710553324410e-04 , -1.453365923716808e-04 , 1.586887875775279e-05 , 4.241341573520792e-05 , -2.123041867524383e-05 , -1.526811061895372e-05 , 2.230938441981634e-05 , -3.432017428898139e-06 , -1.410173385828241e-05 , 1.351664987117440e-05 , -7.456805310851761e-07 , -8.448838581047687e-06 , 6.462723202670970e-06 , 1.401726052082422e-06 , -5.693055610174417e-06 , 2.844605015203572e-06 , 2.996296133918029e-06 , -5.566702444135167e-06 , 2.634638058314581e-06 , 2.663616882515997e-05 , -5.269885642910686e-06 , -8.153912579909767e-05 , 1.324825159079404e-06 , 1.082133675166925e-04 , 2.990415878922840e-06 , -6.513246311773947e-05 , -2.759724213714544e-06 , 1.484095638923724e-05 , 7.424809301046746e-07 , -1.617594954504215e-04 ], [ 5.883724662691994e-05 , 1.948452573660281e-04 , 1.270119640983281e-04 , -3.017037178432670e-05 , -2.624727597578309e-05 , 2.397646436678337e-05 , 3.047660598081647e-06 , -1.767486060640050e-05 , 8.827938351713212e-06 , 8.068421998378197e-06 , -1.391917758734134e-05 , 5.695968329623178e-06 , 5.271239541237441e-06 , -8.176454311340913e-06 , 2.631914429094653e-06 , 3.898194171094623e-06 , -4.927439995523706e-06 , 5.026786485483527e-07 , 4.241342392780371e-06 , -4.584365006125614e-06 , 4.441129647729196e-07 , 2.508762233822091e-05 , -4.652337820383076e-06 , -7.356715084057034e-05 , 2.990415878922861e-06 , 9.541694080046339e-05 , 5.311088722428387e-07 , -5.655395254747548e-05 , -7.544356044794082e-07 , 1.269980847624510e-05 , 4.696018935268347e-05 ], [ -8.868728142024831e-05 , -5.101630490843126e-05 , 1.393651877690296e-05 , 6.647594986721235e-06 , -1.229090821564965e-05 , 9.138618011586676e-07 , 9.299255727538887e-06 , -6.845063675872692e-06 , -2.192391060027468e-06 , 6.590533164499501e-06 , -3.264922954751675e-06 , -2.204234030240666e-06 , 3.753161433794360e-06 , -1.037965911726866e-06 , -1.879900165857787e-06 , 1.890193310260486e-06 , 2.779858179450956e-07 , -1.803524706078243e-06 , 1.125163314158881e-06 , 7.784307399132557e-07 , -1.823900470977467e-06 , 1.002347324957483e-06 , 1.937304772679643e-05 , -1.785631352650217e-06 , -6.513246311773947e-05 , 5.311088722428587e-07 , 7.440208775369848e-05 , 7.311641032314037e-07 , -2.774078047441206e-05 , -4.408828958294675e-07 , 1.075017250578020e-04 ], [ 1.649195968391140e-05 , -9.176394513867907e-05 , -8.735349638012086e-05 , 1.545376441325374e-05 , 2.348090332681419e-05 , -1.527849014454438e-05 , -8.183025849839297e-06 , 1.581526117380169e-05 , -4.171466247118380e-06 , -9.628875957888362e-06 , 1.128720431864013e-05 , -2.458146094280058e-06 , -5.679341230392763e-06 , 5.963104944027804e-06 , -6.802392260490372e-07 , -3.494268997347246e-06 , 2.890920446156225e-06 , 7.612853881616096e-07 , -3.300826353062134e-06 , 2.345452381285531e-06 , 9.131027910925789e-07 , -3.233685256439427e-06 , 2.478096542996079e-06 , 1.695100826863569e-05 , -2.759724213714545e-06 , -5.655395254747549e-05 , 7.311641032314153e-07 , 6.559666484932615e-05 , 1.240877065411180e-07 , -2.470688255280269e-05 , -9.189338863514660e-05 ], [ 3.986378541236639e-05 , 4.717722996544147e-05 , 1.562163815155139e-05 , -5.578313586592747e-06 , -2.215657597169136e-07 , 2.261408120955417e-06 , -2.016271133614381e-06 , 2.198506926483088e-07 , 1.331053824099042e-06 , -1.186884523575363e-06 , -1.552278484090472e-07 , 1.077364537604021e-06 , -7.297839478992591e-07 , -2.287646204875707e-07 , 6.412891565621495e-07 , -2.097250054628229e-07 , -3.536840533005254e-07 , 3.175194859018434e-07 , 2.381295916739206e-07 , -6.188482408033085e-07 , 3.423181895869513e-07 , 3.615248228908187e-07 , -8.169606503678325e-07 , 5.774682432637071e-07 , 1.484095638923725e-05 , -7.544356044794156e-07 , -2.774078047441205e-05 , 1.240877065411238e-07 , 1.330905767924987e-05 , 8.884104622005010e-08 , -3.158609279173533e-05 ], [ -2.080734204109082e-05 , 7.111249931498269e-06 , 1.819382613181743e-05 , -2.498675358118083e-06 , -6.444872622960494e-06 , 3.617283769858598e-06 , 3.118202698102355e-06 , -4.837425950871769e-06 , 8.121122753846729e-07 , 3.379003341109011e-06 , -3.464691582178025e-06 , 4.312391512705559e-07 , 1.996414791054076e-06 , -1.804397982061937e-06 , 5.793723170821257e-08 , 1.107934512468949e-06 , -7.989052895188420e-07 , -2.524196216716127e-07 , 8.492464195141338e-07 , -4.998403651495291e-07 , -3.248030257457955e-07 , 7.731232588721048e-07 , -4.287488876009484e-07 , -3.303613432465375e-07 , 7.424809301046709e-07 , 1.269980847624510e-05 , -4.408828958294696e-07 , -2.470688255280269e-05 , 8.884104622005171e-08 , 1.197542910948322e-05 , 3.878501241188344e-05 ], [ -5.210020320049051e-02 , -1.890906559693971e-02 , 1.382668594719924e-02 , -7.076421937386331e-03 , 7.322667111787697e-04 , 2.325697711870943e-03 , -1.983005807705755e-03 , -2.819410239254837e-05 , 1.468573793837301e-03 , -1.318935000558654e-03 , 2.259380952893342e-04 , 5.884326361165944e-04 , -5.689656491774901e-04 , 6.675499678278620e-05 , 2.979440856739906e-04 , -2.578053969849344e-04 , -2.873774500945195e-05 , 2.671139718648887e-04 , -2.789569803656384e-04 , 8.079312086266559e-05 , 1.565114731653709e-04 , -2.364008973553556e-04 , 1.035998031439817e-04 , 9.651449332646111e-05 , -1.617594954504337e-04 , 4.696018935269557e-05 , 1.075017250578020e-04 , -9.189338863515410e-05 , -3.158609279173351e-05 , 3.878501241188487e-05 , 2.121632678397157e-01 ]]) python-ase-3.9.1.4567/ase/dft/pars_mbeefvdw.py0000664000175000017500000003445312553425527021233 0ustar jensjjensj00000000000000import numpy as np """ mBEEF-vdW ensemble matrix """ uiOmega = np.array([ [ +9.79238372e-03 , +9.50432310e-03 , +1.50664280e-03 , +6.61931580e-04 , +2.72510261e-05 , +9.90017737e-04 , +1.23236176e-04 , +2.62528888e-04 , +2.34614133e-04 , +6.84454480e-07 , -5.14228020e-04 , -1.04662360e-03 , -1.00585951e-04 , +3.57949943e-08 , -2.56240699e-08 , -1.67475516e-05 , -7.41926572e-05 , -5.02094424e-07 , +1.19039715e-08 , -1.29725342e-09 , +2.72539382e-06 , -1.23014194e-09 , +9.61006747e-09 , -4.23645875e-09 , +4.83157082e-09 , -2.37696438e-03 , +6.30187579e-03 , +8.45414159e-03 ], [ +9.50432310e-03 , +1.48454683e-02 , +8.19524284e-03 , +2.99452202e-03 , +4.19982301e-04 , +8.65266882e-04 , -7.84232852e-04 , -3.02933428e-03 , -1.09999053e-03 , +5.04829749e-07 , -3.17422914e-03 , -4.73475658e-03 , -1.54957880e-03 , +6.94163523e-08 , -5.87481438e-08 , +1.91484554e-04 , +3.47848793e-04 , -3.69344627e-07 , +4.00562770e-09 , +2.38952342e-09 , +4.20025223e-05 , -7.41374790e-09 , +2.51886090e-08 , -8.06116478e-09 , +7.58498138e-09 , -2.53805670e-03 , +4.44858633e-03 , +1.13607915e-02 ], [ +1.50664280e-03 , +8.19524284e-03 , +9.68246500e-03 , +4.60794826e-03 , +9.57794927e-04 , +7.91698846e-04 , +3.02182549e-04 , -2.92734046e-03 , -1.14832064e-03 , -1.19250814e-06 , -4.39066124e-03 , -7.28579873e-03 , -3.53350385e-03 , -4.63971114e-08 , +1.48775235e-07 , +1.85392800e-04 , +3.63129723e-04 , +8.78208888e-07 , -9.00768180e-09 , -2.32642126e-08 , +9.57618157e-05 , +3.79151614e-09 , -4.37832686e-08 , +4.39367089e-09 , -1.15880046e-08 , +4.12406124e-04 , -2.34003226e-03 , +2.76246807e-03 ], [ +6.61931580e-04 , +2.99452202e-03 , +4.60794826e-03 , +3.68858946e-03 , +1.03215651e-03 , +1.01882200e-03 , +1.84982081e-03 , +2.12057592e-04 , +1.71824389e-04 , -1.16829718e-06 , -2.88910105e-03 , -5.83219403e-03 , -3.80766808e-03 , -1.14588088e-07 , +2.61037141e-07 , -1.31651700e-05 , -5.43361509e-05 , +8.57297369e-07 , -2.75193317e-09 , -2.69213762e-08 , +1.03184182e-04 , +1.42047337e-08 , -8.57390506e-08 , +1.16543616e-08 , -2.13553999e-08 , +1.31242915e-03 , +4.12599185e-04 , -4.03633739e-04 ], [ +2.72510261e-05 , +4.19982301e-04 , +9.57794927e-04 , +1.03215651e-03 , +3.30125740e-04 , +2.74639742e-04 , +6.70624314e-04 , +3.04292673e-04 , +1.69223504e-04 , -2.88551411e-07 , -7.60839808e-04 , -1.63202154e-03 , -1.21774465e-03 , -7.40128104e-08 , +1.55291965e-07 , -1.91844916e-05 , -5.35127143e-05 , +2.11089750e-07 , -3.60080833e-10 , -6.36045136e-09 , +3.29928974e-05 , +1.09646220e-08 , -5.24829640e-08 , +7.09061625e-09 , -1.25751693e-08 , +2.66170220e-04 , +4.19886833e-04 , -1.53276698e-04 ], [ +9.90017737e-04 , +8.65266882e-04 , +7.91698846e-04 , +1.01882200e-03 , +2.74639742e-04 , +5.71805336e-03 , +1.07594484e-02 , +7.30821331e-03 , +1.86467250e-03 , +6.04989862e-07 , -6.31345738e-04 , -1.61093490e-03 , -1.01312558e-03 , -2.01746526e-08 , +9.74609274e-08 , -4.62340444e-04 , -5.89660173e-04 , -4.45396553e-07 , +4.53087729e-09 , +1.03506087e-08 , +2.74507815e-05 , +5.67601230e-09 , -3.22487615e-08 , +1.96941674e-09 , -7.16476249e-09 , -4.64673810e-04 , -5.85522233e-04 , +1.86494917e-03 ], [ +1.23236176e-04 , -7.84232852e-04 , +3.02182549e-04 , +1.84982081e-03 , +6.70624314e-04 , +1.07594484e-02 , +2.17490074e-02 , +1.56346470e-02 , +4.38169379e-03 , +2.02053669e-06 , -1.02592042e-03 , -2.92485426e-03 , -2.47391959e-03 , -7.22382735e-08 , +2.10729273e-07 , -9.89249619e-04 , -1.38560910e-03 , -1.48793375e-06 , +7.37606189e-09 , +4.44431993e-08 , +6.70374964e-05 , +1.00626123e-08 , -6.84118030e-08 , +7.78331509e-09 , -1.85012551e-08 , -8.42061784e-04 , -8.45327436e-04 , +4.29840991e-03 ], [ +2.62528888e-04 , -3.02933428e-03 , -2.92734046e-03 , +2.12057592e-04 , +3.04292673e-04 , +7.30821331e-03 , +1.56346470e-02 , +1.37522091e-02 , +4.54545202e-03 , +4.46846524e-06 , +5.03562911e-04 , -3.35334388e-04 , -1.12247640e-03 , -7.97967222e-08 , +1.11924011e-07 , -8.70709322e-04 , -1.43739110e-03 , -3.28832967e-06 , +1.68045306e-08 , +9.49033008e-08 , +3.04155636e-05 , +1.12942113e-08 , -3.89523797e-08 , +7.72331538e-09 , -1.03944401e-08 , +3.34852709e-04 , -2.98782797e-03 , +3.13475363e-03 ], [ +2.34614133e-04 , -1.09999053e-03 , -1.14832064e-03 , +1.71824389e-04 , +1.69223504e-04 , +1.86467250e-03 , +4.38169379e-03 , +4.54545202e-03 , +1.90035377e-03 , +5.90455164e-06 , +1.28295178e-04 , -2.71674080e-04 , -6.24452180e-04 , +3.86856722e-08 , -1.38167749e-07 , -2.88727565e-04 , -6.00934035e-04 , -4.34005248e-06 , +1.36416517e-08 , +1.33945566e-07 , +1.69386526e-05 , -5.43803093e-09 , +4.40875972e-08 , -4.44117566e-09 , +1.06101747e-08 , +5.60504546e-04 , -1.66863173e-03 , +1.34126356e-03 ], [ +6.84454480e-07 , +5.04829749e-07 , -1.19250814e-06 , -1.16829718e-06 , -2.88551411e-07 , +6.04989862e-07 , +2.02053669e-06 , +4.46846524e-06 , +5.90455164e-06 , +2.72320605e-06 , +7.77447682e-07 , +1.84724608e-06 , +1.06456034e-06 , +6.69493478e-12 , +6.30646706e-12 , -8.56710027e-07 , -1.86719086e-06 , -1.99409195e-06 , -2.07679229e-11 , +6.44562331e-08 , -2.88558852e-08 , -1.11030343e-13 , -3.28984512e-12 , +1.93883885e-12 , -2.60058997e-12 , +9.72721650e-08 , +1.03866025e-06 , +1.76745507e-06 ], [ -5.14228020e-04 , -3.17422914e-03 , -4.39066124e-03 , -2.88910105e-03 , -7.60839808e-04 , -6.31345738e-04 , -1.02592042e-03 , +5.03562911e-04 , +1.28295178e-04 , +7.77447682e-07 , +2.44400487e-03 , +4.56812141e-03 , +2.80678109e-03 , +1.17366862e-07 , -1.74755350e-07 , -3.20118275e-05 , -4.05707677e-05 , -5.70585303e-07 , +3.34803030e-09 , +1.61815389e-08 , -7.60641405e-05 , -1.64128287e-08 , +5.79789803e-08 , -1.12279343e-08 , +1.44018734e-08 , -4.99745472e-04 , +1.57431803e-04 , -6.60989591e-04 ], [ -1.04662360e-03 , -4.73475658e-03 , -7.28579873e-03 , -5.83219403e-03 , -1.63202154e-03 , -1.61093490e-03 , -2.92485426e-03 , -3.35334388e-04 , -2.71674080e-04 , +1.84724608e-06 , +4.56812141e-03 , +9.22166011e-03 , +6.02059499e-03 , +2.64249604e-07 , -4.12725590e-07 , +2.08186100e-05 , +8.59116912e-05 , -1.35551058e-06 , +4.35129473e-09 , +4.25664567e-08 , -1.63152398e-04 , -4.06173537e-08 , +1.35561846e-07 , -2.55304553e-08 , +3.37650355e-08 , -2.07507947e-03 , -6.52350596e-04 , +6.38273811e-04 ], [ -1.00585951e-04 , -1.54957880e-03 , -3.53350385e-03 , -3.80766808e-03 , -1.21774465e-03 , -1.01312558e-03 , -2.47391959e-03 , -1.12247640e-03 , -6.24452180e-04 , +1.06456034e-06 , +2.80678109e-03 , +6.02059499e-03 , +4.49230737e-03 , +2.73078483e-07 , -3.40246051e-07 , +7.07678211e-05 , +1.97467435e-04 , -7.78779091e-07 , +1.32834740e-09 , +2.34660148e-08 , -1.21733100e-04 , -4.04555296e-08 , +1.08842940e-07 , -2.61619244e-08 , +2.86711066e-08 , -9.82131412e-04 , -1.54903596e-03 , +5.65290647e-04 ], [ +3.57949943e-08 , +6.94163523e-08 , -4.63971114e-08 , -1.14588088e-07 , -7.40128104e-08 , -2.01746526e-08 , -7.22382735e-08 , -7.97967222e-08 , +3.86856722e-08 , +6.69493478e-12 , +1.17366862e-07 , +2.64249604e-07 , +2.73078483e-07 , +1.83885237e-07 , +1.84772071e-11 , +5.04542783e-09 , -1.22335796e-08 , -4.90688923e-12 , +1.72899348e-13 , -5.42214908e-14 , -7.40357839e-09 , -2.49210461e-08 , -6.16160227e-12 , -1.57240072e-08 , -1.49312340e-12 , +7.83338129e-08 , -7.54039419e-09 , +6.99371400e-08 ], [ -2.56240699e-08 , -5.87481438e-08 , +1.48775235e-07 , +2.61037141e-07 , +1.55291965e-07 , +9.74609274e-08 , +2.10729273e-07 , +1.11924011e-07 , -1.38167749e-07 , +6.30646706e-12 , -1.74755350e-07 , -4.12725590e-07 , -3.40246051e-07 , +1.84772071e-11 , +2.21554697e-07 , -7.08008517e-09 , +4.36926162e-08 , -4.69670738e-12 , -4.13877958e-14 , +3.31303941e-13 , -1.07950559e-08 , -2.98766537e-12 , -6.98031417e-08 , -2.05269794e-12 , -1.69620289e-08 , -9.58766371e-08 , +6.91609109e-08 , -1.64810443e-07 ], [ -1.67475516e-05 , +1.91484554e-04 , +1.85392800e-04 , -1.31651700e-05 , -1.91844916e-05 , -4.62340444e-04 , -9.89249619e-04 , -8.70709322e-04 , -2.88727565e-04 , -8.56710027e-07 , -3.20118275e-05 , +2.08186100e-05 , +7.07678211e-05 , +5.04542783e-09 , -7.08008517e-09 , +5.52514333e-05 , +9.13032298e-05 , +6.28361676e-07 , -1.05842476e-09 , -1.95907146e-08 , -1.91758229e-06 , -7.14298923e-10 , +2.46428666e-09 , -4.88879860e-10 , +6.57952661e-10 , -2.12013649e-05 , +1.88744789e-04 , -1.98634974e-04 ], [ -7.41926572e-05 , +3.47848793e-04 , +3.63129723e-04 , -5.43361509e-05 , -5.35127143e-05 , -5.89660173e-04 , -1.38560910e-03 , -1.43739110e-03 , -6.00934035e-04 , -1.86719086e-06 , -4.05707677e-05 , +8.59116912e-05 , +1.97467435e-04 , -1.22335796e-08 , +4.36926162e-08 , +9.13032298e-05 , +1.90035439e-04 , +1.37245078e-06 , -4.31390391e-09 , -4.23574780e-08 , -5.35642668e-06 , +1.71968282e-09 , -1.39417854e-08 , +1.40443715e-09 , -3.35524075e-09 , -1.77241856e-04 , +5.27672890e-04 , -4.24140805e-04 ], [ -5.02094424e-07 , -3.69344627e-07 , +8.78208888e-07 , +8.57297369e-07 , +2.11089750e-07 , -4.45396553e-07 , -1.48793375e-06 , -3.28832967e-06 , -4.34005248e-06 , -1.99409195e-06 , -5.70585303e-07 , -1.35551058e-06 , -7.78779091e-07 , -4.90688923e-12 , -4.69670738e-12 , +6.28361676e-07 , +1.37245078e-06 , +1.47137559e-06 , +1.53009722e-11 , -4.75601282e-08 , +2.11095324e-08 , +7.37036156e-14 , +2.44763282e-12 , -1.43430074e-12 , +1.92137501e-12 , -7.28460072e-08 , -7.62645903e-07 , -1.29440956e-06 ], [ +1.19039715e-08 , +4.00562770e-09 , -9.00768180e-09 , -2.75193317e-09 , -3.60080833e-10 , +4.53087729e-09 , +7.37606189e-09 , +1.68045306e-08 , +1.36416517e-08 , -2.07679229e-11 , +3.34803030e-09 , +4.35129473e-09 , +1.32834740e-09 , +1.72899348e-13 , -4.13877958e-14 , -1.05842476e-09 , -4.31390391e-09 , +1.53009722e-11 , +1.43429102e-08 , -3.54619237e-13 , -3.60003242e-11 , -2.31122149e-14 , +6.21751119e-15 , +1.31255209e-14 , -3.05018991e-14 , -2.71858486e-09 , -3.16500839e-09 , +8.01110140e-09 ], [ -1.29725342e-09 , +2.38952342e-09 , -2.32642126e-08 , -2.69213762e-08 , -6.36045136e-09 , +1.03506087e-08 , +4.44431993e-08 , +9.49033008e-08 , +1.33945566e-07 , +6.44562331e-08 , +1.61815389e-08 , +4.25664567e-08 , +2.34660148e-08 , -5.42214908e-14 , +3.31303941e-13 , -1.95907146e-08 , -4.23574780e-08 , -4.75601282e-08 , -3.54619237e-13 , +1.42837187e-08 , -6.36088407e-10 , +2.84240518e-14 , -1.31773354e-13 , +4.28363928e-14 , -4.56626091e-14 , +3.56938041e-09 , +2.85769294e-08 , +2.98911743e-08 ], [ +2.72539382e-06 , +4.20025223e-05 , +9.57618157e-05 , +1.03184182e-04 , +3.29928974e-05 , +2.74507815e-05 , +6.70374964e-05 , +3.04155636e-05 , +1.69386526e-05 , -2.88558852e-08 , -7.60641405e-05 , -1.63152398e-04 , -1.21733100e-04 , -7.40357839e-09 , -1.07950559e-08 , -1.91758229e-06 , -5.35642668e-06 , +2.11095324e-08 , -3.60003242e-11 , -6.36088407e-10 , +3.30123691e-06 , +1.09683945e-09 , +3.35650816e-09 , +7.09315875e-10 , +7.55386204e-10 , +2.66304703e-05 , +4.19829380e-05 , -1.53056583e-05 ], [ -1.23014194e-09 , -7.41374790e-09 , +3.79151614e-09 , +1.42047337e-08 , +1.09646220e-08 , +5.67601230e-09 , +1.00626123e-08 , +1.12942113e-08 , -5.43803093e-09 , -1.11030343e-13 , -1.64128287e-08 , -4.06173537e-08 , -4.04555296e-08 , -2.49210461e-08 , -2.98766537e-12 , -7.14298923e-10 , +1.71968282e-09 , +7.37036156e-14 , -2.31122149e-14 , +2.84240518e-14 , +1.09683945e-09 , +5.44732885e-09 , +1.00514455e-12 , +2.13099114e-09 , +2.39387495e-13 , -1.43942267e-08 , -2.98613193e-09 , -1.47071201e-08 ], [ +9.61006747e-09 , +2.51886090e-08 , -4.37832686e-08 , -8.57390506e-08 , -5.24829640e-08 , -3.22487615e-08 , -6.84118030e-08 , -3.89523797e-08 , +4.40875972e-08 , -3.28984512e-12 , +5.79789803e-08 , +1.35561846e-07 , +1.08842940e-07 , -6.16160227e-12 , -6.98031417e-08 , +2.46428666e-09 , -1.39417854e-08 , +2.44763282e-12 , +6.21751119e-15 , -1.31773354e-13 , +3.35650816e-09 , +1.00514455e-12 , +2.54352135e-08 , +6.87052397e-13 , +5.31684220e-09 , +3.53044149e-08 , -2.12170404e-08 , +5.60695185e-08 ], [ -4.23645875e-09 , -8.06116478e-09 , +4.39367089e-09 , +1.16543616e-08 , +7.09061625e-09 , +1.96941674e-09 , +7.78331509e-09 , +7.72331538e-09 , -4.44117566e-09 , +1.93883885e-12 , -1.12279343e-08 , -2.55304553e-08 , -2.61619244e-08 , -1.57240072e-08 , -2.05269794e-12 , -4.88879860e-10 , +1.40443715e-09 , -1.43430074e-12 , +1.31255209e-14 , +4.28363928e-14 , +7.09315875e-10 , +2.13099114e-09 , +6.87052397e-13 , +4.71738370e-09 , +1.78694840e-13 , -5.77469515e-09 , +4.75788636e-09 , -6.92043746e-09 ], [ +4.83157082e-09 , +7.58498138e-09 , -1.15880046e-08 , -2.13553999e-08 , -1.25751693e-08 , -7.16476249e-09 , -1.85012551e-08 , -1.03944401e-08 , +1.06101747e-08 , -2.60058997e-12 , +1.44018734e-08 , +3.37650355e-08 , +2.86711066e-08 , -1.49312340e-12 , -1.69620289e-08 , +6.57952661e-10 , -3.35524075e-09 , +1.92137501e-12 , -3.05018991e-14 , -4.56626091e-14 , +7.55386204e-10 , +2.39387495e-13 , +5.31684220e-09 , +1.78694840e-13 , +5.30772991e-09 , +4.72338916e-09 , -1.17284428e-08 , +1.33104649e-08 ], [ -2.37696438e-03 , -2.53805670e-03 , +4.12406124e-04 , +1.31242915e-03 , +2.66170220e-04 , -4.64673810e-04 , -8.42061784e-04 , +3.34852709e-04 , +5.60504546e-04 , +9.72721650e-08 , -4.99745472e-04 , -2.07507947e-03 , -9.82131412e-04 , +7.83338129e-08 , -9.58766371e-08 , -2.12013649e-05 , -1.77241856e-04 , -7.28460072e-08 , -2.71858486e-09 , +3.56938041e-09 , +2.66304703e-05 , -1.43942267e-08 , +3.53044149e-08 , -5.77469515e-09 , +4.72338916e-09 , +3.92773651e-02 , -1.98144281e-02 , -2.86271098e-03 ], [ +6.30187579e-03 , +4.44858633e-03 , -2.34003226e-03 , +4.12599185e-04 , +4.19886833e-04 , -5.85522233e-04 , -8.45327436e-04 , -2.98782797e-03 , -1.66863173e-03 , +1.03866025e-06 , +1.57431803e-04 , -6.52350596e-04 , -1.54903596e-03 , -7.54039419e-09 , +6.91609109e-08 , +1.88744789e-04 , +5.27672890e-04 , -7.62645903e-07 , -3.16500839e-09 , +2.85769294e-08 , +4.19829380e-05 , -2.98613193e-09 , -2.12170404e-08 , +4.75788636e-09 , -1.17284428e-08 , -1.98144281e-02 , +4.31445418e-02 , -2.27839928e-03 ], [ +8.45414159e-03 , +1.13607915e-02 , +2.76246807e-03 , -4.03633739e-04 , -1.53276698e-04 , +1.86494917e-03 , +4.29840991e-03 , +3.13475363e-03 , +1.34126356e-03 , +1.76745507e-06 , -6.60989591e-04 , +6.38273811e-04 , +5.65290647e-04 , +6.99371400e-08 , -1.64810443e-07 , -1.98634974e-04 , -4.24140805e-04 , -1.29440956e-06 , +8.01110140e-09 , +2.98911743e-08 , -1.53056583e-05 , -1.47071201e-08 , +5.60695185e-08 , -6.92043746e-09 , +1.33104649e-08 , -2.86271098e-03 , -2.27839928e-03 , +2.82051899e-02 ]]) python-ase-3.9.1.4567/ase/dft/wannier.py0000664000175000017500000007323212553425527020050 0ustar jensjjensj00000000000000from __future__ import print_function """ Maximally localized Wannier Functions Find the set of maximally localized Wannier functions using the spread functional of Marzari and Vanderbilt (PRB 56, 1997 page 12847). """ from time import time from math import sqrt, pi from pickle import dump, load import numpy as np from ase.parallel import paropen from ase.dft.kpoints import get_monkhorst_pack_size_and_offset from ase.transport.tools import dagger, normalize dag = dagger def gram_schmidt(U): """Orthonormalize columns of U according to the Gram-Schmidt procedure.""" for i, col in enumerate(U.T): for col2 in U.T[:i]: col -= col2 * np.dot(col2.conj(), col) col /= np.linalg.norm(col) def gram_schmidt_single(U, n): """Orthogonalize columns of U to column n""" N = len(U.T) v_n = U.T[n] indices = list(range(N)) del indices[indices.index(n)] for i in indices: v_i = U.T[i] v_i -= v_n * np.dot(v_n.conj(), v_i) def lowdin(U, S=None): """Orthonormalize columns of U according to the Lowdin procedure. If the overlap matrix is know, it can be specified in S. """ if S is None: S = np.dot(dag(U), U) eig, rot = np.linalg.eigh(S) rot = np.dot(rot / np.sqrt(eig), dag(rot)) U[:] = np.dot(U, rot) def neighbor_k_search(k_c, G_c, kpt_kc, tol=1e-4): # search for k1 (in kpt_kc) and k0 (in alldir), such that # k1 - k - G + k0 = 0 alldir_dc = np.array([[0,0,0],[1,0,0],[0,1,0],[0,0,1], [1,1,0],[1,0,1],[0,1,1]], int) for k0_c in alldir_dc: for k1, k1_c in enumerate(kpt_kc): if np.linalg.norm(k1_c - k_c - G_c + k0_c) < tol: return k1, k0_c print('Wannier: Did not find matching kpoint for kpt=', k_c) print('Probably non-uniform k-point grid') raise NotImplementedError def calculate_weights(cell_cc): """ Weights are used for non-cubic cells, see PRB **61**, 10040""" alldirs_dc = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [1, 0, 1], [0, 1, 1]], dtype=int) g = np.dot(cell_cc, cell_cc.T) # NOTE: Only first 3 of following 6 weights are presently used: w = np.zeros(6) w[0] = g[0, 0] - g[0, 1] - g[0, 2] w[1] = g[1, 1] - g[0, 1] - g[1, 2] w[2] = g[2, 2] - g[0, 2] - g[1, 2] w[3] = g[0, 1] w[4] = g[0, 2] w[5] = g[1, 2] # Make sure that first 3 Gdir vectors are included - # these are used to calculate Wanniercenters. Gdir_dc = alldirs_dc[:3] weight_d = w[:3] for d in range(3, 6): if abs(w[d]) > 1e-5: Gdir_dc = np.concatenate((Gdir_dc, alldirs_dc[d:d + 1])) weight_d = np.concatenate((weight_d, w[d:d + 1])) weight_d /= max(abs(weight_d)) return weight_d, Gdir_dc def random_orthogonal_matrix(dim, seed=None, real=False): """Generate a random orthogonal matrix""" if seed is not None: np.random.seed(seed) H = np.random.rand(dim, dim) np.add(dag(H), H, H) np.multiply(.5, H, H) if real: gram_schmidt(H) return H else: val, vec = np.linalg.eig(H) return np.dot(vec * np.exp(1.j * val), dag(vec)) def steepest_descent(func, step=.005, tolerance=1e-6, **kwargs): fvalueold = 0. fvalue = fvalueold + 10 count=0 while abs((fvalue - fvalueold) / fvalue) > tolerance: fvalueold = fvalue dF = func.get_gradients() func.step(dF * step, **kwargs) fvalue = func.get_functional_value() count += 1 print('SteepestDescent: iter=%s, value=%s' % (count, fvalue)) def md_min(func, step=.25, tolerance=1e-6, verbose=False, **kwargs): if verbose: print('Localize with step =', step, 'and tolerance =', tolerance) t = -time() fvalueold = 0. fvalue = fvalueold + 10 count = 0 V = np.zeros(func.get_gradients().shape, dtype=complex) while abs((fvalue - fvalueold) / fvalue) > tolerance: fvalueold = fvalue dF = func.get_gradients() V *= (dF * V.conj()).real > 0 V += step * dF func.step(V, **kwargs) fvalue = func.get_functional_value() if fvalue < fvalueold: step *= 0.5 count += 1 if verbose: print('MDmin: iter=%s, step=%s, value=%s' % (count, step, fvalue)) if verbose: t += time() print('%d iterations in %0.2f seconds (%0.2f ms/iter), endstep = %s' %( count, t, t * 1000. / count, step)) def rotation_from_projection2(proj_nw, fixed): V_ni = proj_nw Nb, Nw = proj_nw.shape M = fixed L = Nw - M print('M=%i, L=%i, Nb=%i, Nw=%i' % (M, L, Nb, Nw)) U_ww = np.zeros((Nw, Nw), dtype=proj_nw.dtype) c_ul = np.zeros((Nb-M, L), dtype=proj_nw.dtype) for V_n in V_ni.T: V_n /= np.linalg.norm(V_n) # Find EDF P_ui = V_ni[M:].copy() la = np.linalg for l in range(L): norm_list = np.array([la.norm(v) for v in P_ui.T]) perm_list = np.argsort(-norm_list) P_ui = P_ui[:, perm_list].copy() # largest norm to the left P_ui[:, 0] /= la.norm(P_ui[:, 0]) # normalize c_ul[:, l] = P_ui[:, 0] # save normalized EDF gram_schmidt_single(P_ui, 0) # ortho remain. to this EDF P_ui = P_ui[:, 1:].copy() # remove this EDF U_ww[:M] = V_ni[:M, :] U_ww[M:] = np.dot(c_ul.T.conj(), V_ni[M:]) gram_schmidt(U_ww) return U_ww, c_ul def rotation_from_projection(proj_nw, fixed, ortho=True): """Determine rotation and coefficient matrices from projections proj_nw = psi_n: eigenstates p_w: localized function Nb (n) = Number of bands Nw (w) = Number of wannier functions M (f) = Number of fixed states L (l) = Number of extra degrees of freedom U (u) = Number of non-fixed states """ Nb, Nw = proj_nw.shape M = fixed L = Nw - M U_ww = np.empty((Nw, Nw), dtype=proj_nw.dtype) U_ww[:M] = proj_nw[:M] if L > 0: proj_uw = proj_nw[M:] eig_w, C_ww = np.linalg.eigh(np.dot(dag(proj_uw), proj_uw)) C_ul = np.dot(proj_uw, C_ww[:, np.argsort(-eig_w.real)[:L]]) #eig_u, C_uu = np.linalg.eigh(np.dot(proj_uw, dag(proj_uw))) #C_ul = C_uu[:, np.argsort(-eig_u.real)[:L]] U_ww[M:] = np.dot(dag(C_ul), proj_uw) else: C_ul = np.empty((Nb - M, 0)) normalize(C_ul) if ortho: lowdin(U_ww) else: normalize(U_ww) return U_ww, C_ul class Wannier: """Maximally localized Wannier Functions Find the set of maximally localized Wannier functions using the spread functional of Marzari and Vanderbilt (PRB 56, 1997 page 12847). """ def __init__(self, nwannier, calc, file=None, nbands=None, fixedenergy=None, fixedstates=None, spin=0, initialwannier='random', seed=None, verbose=False): """ Required arguments: ``nwannier``: The number of Wannier functions you wish to construct. This must be at least half the number of electrons in the system and at most equal to the number of bands in the calculation. ``calc``: A converged DFT calculator class. If ``file`` arg. is not provided, the calculator *must* provide the method ``get_wannier_localization_matrix``, and contain the wavefunctions (save files with only the density is not enough). If the localization matrix is read from file, this is not needed, unless ``get_function`` or ``write_cube`` is called. Optional arguments: ``nbands``: Bands to include in localization. The number of bands considered by Wannier can be smaller than the number of bands in the calculator. This is useful if the highest bands of the DFT calculation are not well converged. ``spin``: The spin channel to be considered. The Wannier code treats each spin channel independently. ``fixedenergy`` / ``fixedstates``: Fixed part of Heilbert space. Determine the fixed part of Hilbert space by either a maximal energy *or* a number of bands (possibly a list for multiple k-points). Default is None meaning that the number of fixed states is equated to ``nwannier``. ``file``: Read localization and rotation matrices from this file. ``initialwannier``: Initial guess for Wannier rotation matrix. Can be 'bloch' to start from the Bloch states, 'random' to be randomized, or a list passed to calc.get_initial_wannier. ``seed``: Seed for random ``initialwannier``. ``verbose``: True / False level of verbosity. """ # Bloch phase sign convention sign = -1 classname = calc.__class__.__name__ if classname in ['Dacapo', 'Jacapo']: print('Using ' + classname) sign = +1 self.nwannier = nwannier self.calc = calc self.spin = spin self.verbose = verbose self.kpt_kc = calc.get_bz_k_points() assert len(calc.get_ibz_k_points()) == len(self.kpt_kc) self.kptgrid = get_monkhorst_pack_size_and_offset(self.kpt_kc)[0] self.kpt_kc *= sign self.Nk = len(self.kpt_kc) self.unitcell_cc = calc.get_atoms().get_cell() self.largeunitcell_cc = (self.unitcell_cc.T * self.kptgrid).T self.weight_d, self.Gdir_dc = calculate_weights(self.largeunitcell_cc) self.Ndir = len(self.weight_d) # Number of directions if nbands is not None: self.nbands = nbands else: self.nbands = calc.get_number_of_bands() if fixedenergy is None: if fixedstates is None: self.fixedstates_k = np.array([nwannier] * self.Nk, int) else: if isinstance(fixedstates, int): fixedstates = [fixedstates] * self.Nk self.fixedstates_k = np.array(fixedstates, int) else: # Setting number of fixed states and EDF from specified energy. # All states below this energy (relative to Fermi level) are fixed. fixedenergy += calc.get_fermi_level() print(fixedenergy) self.fixedstates_k = np.array( [calc.get_eigenvalues(k, spin).searchsorted(fixedenergy) for k in range(self.Nk)], int) self.edf_k = self.nwannier - self.fixedstates_k if verbose: print('Wannier: Fixed states : %s' % self.fixedstates_k) print('Wannier: Extra degrees of freedom: %s' % self.edf_k) # Set the list of neighboring k-points k1, and the "wrapping" k0, # such that k1 - k - G + k0 = 0 # # Example: kpoints = (-0.375,-0.125,0.125,0.375), dir=0 # G = [0.25,0,0] # k=0.375, k1= -0.375 : -0.375-0.375-0.25 => k0=[1,0,0] # # For a gamma point calculation k1 = k = 0, k0 = [1,0,0] for dir=0 if self.Nk == 1: self.kklst_dk = np.zeros((self.Ndir, 1), int) k0_dkc = self.Gdir_dc.reshape(-1, 1, 3) else: self.kklst_dk = np.empty((self.Ndir, self.Nk), int) k0_dkc = np.empty((self.Ndir, self.Nk, 3), int) # Distance between kpoints kdist_c = np.empty(3) for c in range(3): # make a sorted list of the kpoint values in this direction slist = np.argsort(self.kpt_kc[:, c], kind='mergesort') skpoints_kc = np.take(self.kpt_kc, slist, axis=0) kdist_c[c] = max([skpoints_kc[n + 1, c] - skpoints_kc[n, c] for n in range(self.Nk - 1)]) for d, Gdir_c in enumerate(self.Gdir_dc): for k, k_c in enumerate(self.kpt_kc): # setup dist vector to next kpoint G_c = np.where(Gdir_c > 0, kdist_c, 0) if max(G_c) < 1e-4: self.kklst_dk[d, k] = k k0_dkc[d, k] = Gdir_c else: self.kklst_dk[d, k], k0_dkc[d, k] = \ neighbor_k_search(k_c, G_c, self.kpt_kc) # Set the inverse list of neighboring k-points self.invkklst_dk = np.empty((self.Ndir, self.Nk), int) for d in range(self.Ndir): for k1 in range(self.Nk): self.invkklst_dk[d, k1] = self.kklst_dk[d].tolist().index(k1) Nw = self.nwannier Nb = self.nbands self.Z_dkww = np.empty((self.Ndir, self.Nk, Nw, Nw), complex) self.V_knw = np.zeros((self.Nk, Nb, Nw), complex) if file is None: self.Z_dknn = np.empty((self.Ndir, self.Nk, Nb, Nb), complex) for d, dirG in enumerate(self.Gdir_dc): for k in range(self.Nk): k1 = self.kklst_dk[d, k] k0_c = k0_dkc[d, k] self.Z_dknn[d, k] = calc.get_wannier_localization_matrix( nbands=Nb, dirG=dirG, kpoint=k, nextkpoint=k1, G_I=k0_c, spin=self.spin) self.initialize(file=file, initialwannier=initialwannier, seed=seed) def initialize(self, file=None, initialwannier='random', seed=None): """Re-initialize current rotation matrix. Keywords are identical to those of the constructor. """ Nw = self.nwannier Nb = self.nbands if file is not None: self.Z_dknn, self.U_kww, self.C_kul = load(paropen(file)) elif initialwannier == 'bloch': # Set U and C to pick the lowest Bloch states self.U_kww = np.zeros((self.Nk, Nw, Nw), complex) self.C_kul = [] for U, M, L in zip(self.U_kww, self.fixedstates_k, self.edf_k): U[:] = np.identity(Nw, complex) if L > 0: self.C_kul.append( np.identity(Nb - M, complex)[:, :L]) else: self.C_kul.append([]) elif initialwannier == 'random': # Set U and C to random (orthogonal) matrices self.U_kww = np.zeros((self.Nk, Nw, Nw), complex) self.C_kul = [] for U, M, L in zip(self.U_kww, self.fixedstates_k, self.edf_k): U[:] = random_orthogonal_matrix(Nw, seed, real=False) if L > 0: self.C_kul.append(random_orthogonal_matrix( Nb - M, seed=seed, real=False)[:, :L]) else: self.C_kul.append(np.array([])) else: # Use initial guess to determine U and C self.C_kul, self.U_kww = self.calc.initial_wannier( initialwannier, self.kptgrid, self.fixedstates_k, self.edf_k, self.spin, self.nbands) self.update() def save(self, file): """Save information on localization and rotation matrices to file.""" dump((self.Z_dknn, self.U_kww, self.C_kul), paropen(file, 'w')) def update(self): # Update large rotation matrix V (from rotation U and coeff C) for k, M in enumerate(self.fixedstates_k): self.V_knw[k, :M] = self.U_kww[k, :M] if M < self.nwannier: self.V_knw[k, M:] = np.dot(self.C_kul[k], self.U_kww[k, M:]) # else: self.V_knw[k, M:] = 0.0 # Calculate the Zk matrix from the large rotation matrix: # Zk = V^d[k] Zbloch V[k1] for d in range(self.Ndir): for k in range(self.Nk): k1 = self.kklst_dk[d, k] self.Z_dkww[d, k] = np.dot(dag(self.V_knw[k]), np.dot( self.Z_dknn[d, k], self.V_knw[k1])) # Update the new Z matrix self.Z_dww = self.Z_dkww.sum(axis=1) / self.Nk def get_centers(self, scaled=False): """Calculate the Wannier centers :: pos = L / 2pi * phase(diag(Z)) """ coord_wc = np.angle(self.Z_dww[:3].diagonal(0, 1, 2)).T / (2 * pi) % 1 if not scaled: coord_wc = np.dot(coord_wc, self.largeunitcell_cc) return coord_wc def get_radii(self): """Calculate the spread of the Wannier functions. :: -- / L \ 2 2 radius**2 = - > | --- | ln |Z| --d \ 2pi / """ r2 = -np.dot(self.largeunitcell_cc.diagonal()**2 / (2 * pi)**2, np.log(abs(self.Z_dww[:3].diagonal(0, 1, 2))**2)) return np.sqrt(r2) def get_spectral_weight(self, w): return abs(self.V_knw[:, :, w])**2 / self.Nk def get_pdos(self, w, energies, width): """Projected density of states (PDOS). Returns the (PDOS) for Wannier function ``w``. The calculation is performed over the energy grid specified in energies. The PDOS is produced as a sum of Gaussians centered at the points of the energy grid and with the specified width. """ spec_kn = self.get_spectral_weight(w) dos = np.zeros(len(energies)) for k, spec_n in enumerate(spec_kn): eig_n = self.calc.get_eigenvalues(k=kpt, s=self.spin) for weight, eig in zip(spec_n, eig): # Add gaussian centered at the eigenvalue x = ((energies - center) / width)**2 dos += weight * np.exp(-x.clip(0., 40.)) / (sqrt(pi) * width) return dos def max_spread(self, directions=[0, 1, 2]): """Returns the index of the most delocalized Wannier function together with the value of the spread functional""" d = np.zeros(self.nwannier) for dir in directions: d[dir] = np.abs(self.Z_dww[dir].diagonal())**2 *self.weight_d[dir] index = np.argsort(d)[0] print('Index:', index) print('Spread:', d[index]) def translate(self, w, R): """Translate the w'th Wannier function The distance vector R = [n1, n2, n3], is in units of the basis vectors of the small cell. """ for kpt_c, U_ww in zip(self.kpt_kc, self.U_kww): U_ww[:, w] *= np.exp(2.j * pi * np.dot(np.array(R), kpt_c)) self.update() def translate_to_cell(self, w, cell): """Translate the w'th Wannier function to specified cell""" scaled_c = np.angle(self.Z_dww[:3, w, w]) * self.kptgrid / (2 * pi) trans = np.array(cell) - np.floor(scaled_c) self.translate(w, trans) def translate_all_to_cell(self, cell=[0, 0, 0]): """Translate all Wannier functions to specified cell. Move all Wannier orbitals to a specific unit cell. There exists an arbitrariness in the positions of the Wannier orbitals relative to the unit cell. This method can move all orbitals to the unit cell specified by ``cell``. For a `\Gamma`-point calculation, this has no effect. For a **k**-point calculation the periodicity of the orbitals are given by the large unit cell defined by repeating the original unitcell by the number of **k**-points in each direction. In this case it is usefull to move the orbitals away from the boundaries of the large cell before plotting them. For a bulk calculation with, say 10x10x10 **k** points, one could move the orbitals to the cell [2,2,2]. In this way the pbc boundary conditions will not be noticed. """ scaled_wc = np.angle(self.Z_dww[:3].diagonal(0, 1, 2)).T * \ self.kptgrid / (2 * pi) trans_wc = np.array(cell)[None] - np.floor(scaled_wc) for kpt_c, U_ww in zip(self.kpt_kc, self.U_kww): U_ww *= np.exp(2.j * pi * np.dot(trans_wc, kpt_c)) self.update() def distances(self, R): Nw = self.nwannier cen = self.get_centers() r1 = cen.repeat(Nw, axis=0).reshape(Nw, Nw, 3) r2 = cen.copy() for i in range(3): r2 += self.unitcell_cc[i] * R[i] r2 = np.swapaxes(r2.repeat(Nw, axis=0).reshape(Nw, Nw, 3), 0, 1) return np.sqrt(np.sum((r1 - r2)**2, axis=-1)) def get_hopping(self, R): """Returns the matrix H(R)_nm=<0,n|H|R,m>. :: 1 _ -ik.R H(R) = <0,n|H|R,m> = --- >_ e H(k) Nk k where R is the cell-distance (in units of the basis vectors of the small cell) and n,m are indices of the Wannier functions. """ H_ww = np.zeros([self.nwannier, self.nwannier], complex) for k, kpt_c in enumerate(self.kpt_kc): phase = np.exp(-2.j * pi * np.dot(np.array(R), kpt_c)) H_ww += self.get_hamiltonian(k) * phase return H_ww / self.Nk def get_hamiltonian(self, k=0): """Get Hamiltonian at existing k-vector of index k :: dag H(k) = V diag(eps ) V k k k """ eps_n = self.calc.get_eigenvalues(kpt=k, spin=self.spin)[:self.nbands] return np.dot(dag(self.V_knw[k]) * eps_n, self.V_knw[k]) def get_hamiltonian_kpoint(self, kpt_c): """Get Hamiltonian at some new arbitrary k-vector :: _ ik.R H(k) = >_ e H(R) R Warning: This method moves all Wannier functions to cell (0, 0, 0) """ if self.verbose: print('Translating all Wannier functions to cell (0, 0, 0)') self.translate_all_to_cell() max = (self.kptgrid - 1) / 2 N1, N2, N3 = max Hk = np.zeros([self.nwannier, self.nwannier], complex) for n1 in range(-N1, N1 + 1): for n2 in range(-N2, N2 + 1): for n3 in range(-N3, N3 + 1): R = np.array([n1, n2, n3], float) hop_ww = self.get_hopping(R) phase = np.exp(+2.j * pi * np.dot(R, kpt_c)) Hk += hop_ww * phase return Hk def get_function(self, index, repeat=None): """Get Wannier function on grid. Returns an array with the funcion values of the indicated Wannier function on a grid with the size of the *repeated* unit cell. For a calculation using **k**-points the relevant unit cell for eg. visualization of the Wannier orbitals is not the original unit cell, but rather a larger unit cell defined by repeating the original unit cell by the number of **k**-points in each direction. Note that for a `\Gamma`-point calculation the large unit cell coinsides with the original unit cell. The large unitcell also defines the periodicity of the Wannier orbitals. ``index`` can be either a single WF or a coordinate vector in terms of the WFs. """ # Default size of plotting cell is the one corresponding to k-points. if repeat is None: repeat = self.kptgrid N1, N2, N3 = repeat dim = self.calc.get_number_of_grid_points() largedim = dim * [N1, N2, N3] wanniergrid = np.zeros(largedim, dtype=complex) for k, kpt_c in enumerate(self.kpt_kc): # The coordinate vector of wannier functions if isinstance(index, int): vec_n = self.V_knw[k, :, index] else: vec_n = np.dot(self.V_knw[k], index) wan_G = np.zeros(dim, complex) for n, coeff in enumerate(vec_n): wan_G += coeff * self.calc.get_pseudo_wave_function( n, k, self.spin, pad=True) # Distribute the small wavefunction over large cell: for n1 in range(N1): for n2 in range(N2): for n3 in range(N3): # sign? e = np.exp(-2.j * pi * np.dot([n1, n2, n3], kpt_c)) wanniergrid[n1 * dim[0]:(n1 + 1) * dim[0], n2 * dim[1]:(n2 + 1) * dim[1], n3 * dim[2]:(n3 + 1) * dim[2]] += e * wan_G # Normalization wanniergrid /= np.sqrt(self.Nk) return wanniergrid def write_cube(self, index, fname, repeat=None, real=True): """Dump specified Wannier function to a cube file""" from ase.io.cube import write_cube # Default size of plotting cell is the one corresponding to k-points. if repeat is None: repeat = self.kptgrid atoms = self.calc.get_atoms() * repeat func = self.get_function(index, repeat) # Handle separation of complex wave into real parts if real: if self.Nk == 1: func *= np.exp(-1.j * np.angle(func.max())) if 0: assert max(abs(func.imag).flat) < 1e-4 func = func.real else: func = abs(func) else: phase_fname = fname.split('.') phase_fname.insert(1, 'phase') phase_fname = '.'.join(phase_fname) write_cube(phase_fname, atoms, data=np.angle(func)) func = abs(func) write_cube(fname, atoms, data=func) def localize(self, step=0.25, tolerance=1e-08, updaterot=True, updatecoeff=True): """Optimize rotation to give maximal localization""" md_min(self, step, tolerance, verbose=self.verbose, updaterot=updaterot, updatecoeff=updatecoeff) def get_functional_value(self): """Calculate the value of the spread functional. :: Tr[|ZI|^2]=sum(I)sum(n) w_i|Z_(i)_nn|^2, where w_i are weights.""" a_d = np.sum(np.abs(self.Z_dww.diagonal(0, 1, 2))**2, axis=1) return np.dot(a_d, self.weight_d).real def get_gradients(self): # Determine gradient of the spread functional. # # The gradient for a rotation A_kij is:: # # dU = dRho/dA_{k,i,j} = sum(I) sum(k') # + Z_jj Z_kk',ij^* - Z_ii Z_k'k,ij^* # - Z_ii^* Z_kk',ji + Z_jj^* Z_k'k,ji # # The gradient for a change of coefficients is:: # # dRho/da^*_{k,i,j} = sum(I) [[(Z_0)_{k} V_{k'} diag(Z^*) + # (Z_0_{k''})^d V_{k''} diag(Z)] * # U_k^d]_{N+i,N+j} # # where diag(Z) is a square,diagonal matrix with Z_nn in the diagonal, # k' = k + dk and k = k'' + dk. # # The extra degrees of freedom chould be kept orthonormal to the fixed # space, thus we introduce lagrange multipliers, and minimize instead:: # # Rho_L=Rho- sum_{k,n,m} lambda_{k,nm} # # for this reason the coefficient gradients should be multiplied # by (1 - c c^d). Nb = self.nbands Nw = self.nwannier dU = [] dC = [] for k in range(self.Nk): M = self.fixedstates_k[k] L = self.edf_k[k] U_ww = self.U_kww[k] C_ul = self.C_kul[k] Utemp_ww = np.zeros((Nw, Nw), complex) Ctemp_nw = np.zeros((Nb, Nw), complex) for d, weight in enumerate(self.weight_d): if abs(weight) < 1.0e-6: continue Z_knn = self.Z_dknn[d] diagZ_w = self.Z_dww[d].diagonal() Zii_ww = np.repeat(diagZ_w, Nw).reshape(Nw, Nw) k1 = self.kklst_dk[d, k] k2 = self.invkklst_dk[d, k] V_knw = self.V_knw Z_kww = self.Z_dkww[d] if L > 0: Ctemp_nw += weight * np.dot( np.dot(Z_knn[k], V_knw[k1]) * diagZ_w.conj() + np.dot(dag(Z_knn[k2]), V_knw[k2]) * diagZ_w, dag(U_ww)) temp = Zii_ww.T * Z_kww[k].conj() - Zii_ww * Z_kww[k2].conj() Utemp_ww += weight * (temp - dag(temp)) dU.append(Utemp_ww.ravel()) if L > 0: # Ctemp now has same dimension as V, the gradient is in the # lower-right (Nb-M) x L block Ctemp_ul = Ctemp_nw[M:, M:] G_ul = Ctemp_ul - np.dot(np.dot(C_ul, dag(C_ul)), Ctemp_ul) dC.append(G_ul.ravel()) return np.concatenate(dU + dC) def step(self, dX, updaterot=True, updatecoeff=True): # dX is (A, dC) where U->Uexp(-A) and C->C+dC Nw = self.nwannier Nk = self.Nk M_k = self.fixedstates_k L_k = self.edf_k if updaterot: A_kww = dX[:Nk * Nw**2].reshape(Nk, Nw, Nw) for U, A in zip(self.U_kww, A_kww): H = -1.j * A.conj() epsilon, Z = np.linalg.eigh(H) # Z contains the eigenvectors as COLUMNS. # Since H = iA, dU = exp(-A) = exp(iH) = ZDZ^d dU = np.dot(Z * np.exp(1.j * epsilon), dag(Z)) if U.dtype == float: U[:] = np.dot(U, dU).real else: U[:] = np.dot(U, dU) if updatecoeff: start = 0 for C, unocc, L in zip(self.C_kul, self.nbands - M_k, L_k): if L == 0 or unocc == 0: continue Ncoeff = L * unocc deltaC = dX[Nk * Nw**2 + start: Nk * Nw**2 + start + Ncoeff] C += deltaC.reshape(unocc, L) gram_schmidt(C) start += Ncoeff self.update() python-ase-3.9.1.4567/ase/dft/bandgap.py0000664000175000017500000000625712553425527020004 0ustar jensjjensj00000000000000from __future__ import print_function import sys import functools import numpy as np def get_band_gap(calc, direct=False, spin=None, output=sys.stdout): """Calculates the band-gap. Parameters: calc: Calculator object Electronic structure calculator object. direct: bool Calculate direct band-gap. spin: int or None For spin-polarized systems, you can use spin=0 or spin=1 to look only at a single spin-channel. output: file descriptor Use output=None for no text output. Rerurns a (gap, k1, k2) tuple where k1 and k2 are the indices of the valence and conduction k-points. For the spin-polarized case, a (gap, (s1, k1), (s2, k2)) tuple is returned. Example: >>> gap, k1, k2 = get_band_gap(silicon.calc) Gap: 1.2 eV Transition (v -> c): [0.000, 0.000, 0.000] -> [0.500, 0.500, 0.000] >>> print(gap, k1, k2) 1.2 0 5 >>> gap, k1, k2 = get_band_gap(atoms.calc, direct=True) Direct gap: 3.4 eV Transition at: [0.000, 0.000, 0.000] >>> print(gap, k1, k2) 3.4 0 0 """ kpts_kc = calc.get_ibz_k_points() nk = len(kpts_kc) ns = calc.get_number_of_spins() e_skn = np.array([[calc.get_eigenvalues(kpt=k, spin=s) for k in range(nk)] for s in range(ns)]) e_skn -= calc.get_fermi_level() N_sk = (e_skn < 0.0).sum(2) # number of occupied bands e_skn = np.array([[e_skn[s, k, N_sk[s, k] - 1:N_sk[s, k] + 1] for k in range(nk)] for s in range(ns)]) ev_sk = e_skn[:, :, 0] # valence band ec_sk = e_skn[:, :, 1] # conduction band if ns == 1: gap, k1, k2 = find_gap(N_sk[0], ev_sk[0], ec_sk[0], direct) elif spin is None: gap, k1, k2 = find_gap(N_sk.ravel(), ev_sk.ravel(), ec_sk.ravel(), direct) if gap > 0.0: k1 = divmod(k1, nk) k2 = divmod(k2, nk) else: k1 = (None, None) k2 = (None, None) else: gap, k1, k2 = find_gap(N_sk[spin], ev_sk[spin], ec_sk[spin], direct) if output is not None: def sk(k): """Convert k or (s, k) to string.""" if isinstance(k, tuple): s, k = k return '(spin={0}, {1})'.format(s, sk(k)) return '[{0:.3f}, {1:.3f}, {2:.3f}]'.format(*kpts_kc[k]) p = functools.partial(print, file=output) if spin is not None: p('spin={0}: '.format(spin), end='') if gap == 0.0: p('No gap!') elif direct: p('Direct gap: {0:.3f} eV'.format(gap)) p('Transition at:', sk(k1)) else: p('Gap: {0:.3f} eV'.format(gap)) p('Transition (v -> c):') p(' ', sk(k1), '->', sk(k2)) return gap, k1, k2 def find_gap(N_k, ev_k, ec_k, direct): """Helper function.""" if N_k.ptp() > 0: return 0.0, None, None if direct: gap_k = ec_k - ev_k k = gap_k.argmin() return gap_k[k], k, k kv = ev_k.argmax() kc = ec_k.argmin() return ec_k[kc] - ev_k[kv], kv, kc python-ase-3.9.1.4567/ase/dft/pars_mbeef.py0000664000175000017500000022620712553425527020512 0ustar jensjjensj00000000000000import numpy as np """ mBEEF ensemble matrix """ uiOmega = np.array([ [ +3.97526822e+00 , +9.89942369e+00 , +1.07326424e+01 , +6.75380818e+00 , +1.77302640e+00 , -6.84112187e-01 , -6.54206764e-01 , -1.39507729e-01 , -4.36967834e+00 , -1.16814935e+01 , -1.39547031e+01 , -9.53518416e+00 , -2.62228452e+00 , +1.14105816e+00 , +1.16365187e+00 , +2.82352691e-01 , -9.81697534e-01 , -1.41339774e+00 , +6.15364041e-01 , +2.54529066e+00 , +2.16101378e+00 , +6.60664611e-01 , +1.36501058e-03 , -2.32275169e-03 , +2.53968706e-01 , +3.74626666e-01 , -2.05813962e-01 , -8.44468626e-01 , -7.68127322e-01 , -2.69065920e-01 , -5.47673080e-05 , -1.61579894e-05 , -6.88223680e-02 , -1.92158621e-01 , -2.16638369e-01 , -1.17358804e-01 , -6.77575337e-04 , +1.32077264e-03 , -2.51835861e-04 , +3.96250933e-04 , +1.33956923e-02 , +3.87302168e-02 , +4.27005394e-02 , +2.68638059e-02 , +8.89902141e-05 , -7.44173561e-05 , +3.99260995e-05 , -4.28746505e-06 , +6.75748630e-04 , +1.66816940e-03 , +8.45332951e-05 , -1.96576973e-04 , +7.61037965e-05 , -9.43608480e-05 , +3.16431618e-05 , -4.45517629e-05 , -9.17705334e-05 , -2.75099179e-04 , -1.51884837e-05 , +2.25081009e-05 , -2.68193558e-05 , +2.04396573e-05 , -6.98162678e-06 , -4.44246376e-06 ], [ +9.89942369e+00 , +2.48462398e+01 , +2.72961422e+01 , +1.75339421e+01 , +4.84077678e+00 , -1.66256296e+00 , -1.69903464e+00 , -3.69347990e-01 , -1.06680161e+01 , -2.85412091e+01 , -3.42584233e+01 , -2.36338271e+01 , -6.59254846e+00 , +2.92322623e+00 , +3.04630046e+00 , +7.54658909e-01 , -2.57832311e+00 , -3.82240745e+00 , +1.32299675e+00 , +6.42484068e+00 , +5.61261493e+00 , +1.74814856e+00 , +3.73980970e-03 , -6.84283125e-03 , +6.00384512e-01 , +8.55253481e-01 , -6.02361336e-01 , -2.20369524e+00 , -2.01091687e+00 , -7.18947807e-01 , -2.65351664e-04 , +1.96742578e-04 , -1.76403390e-01 , -4.94927722e-01 , -5.62730485e-01 , -3.10118352e-01 , -1.84143143e-03 , +3.84450130e-03 , -7.23669468e-04 , +1.19393383e-03 , +3.53809131e-02 , +1.02174628e-01 , +1.11818628e-01 , +7.16897926e-02 , +2.62494628e-04 , -2.86897997e-04 , +1.51714933e-04 , -1.00094347e-04 , +1.75643964e-03 , +4.38501160e-03 , +2.24783064e-04 , -5.58567196e-04 , +2.03670441e-04 , -2.74524725e-04 , +1.00265250e-04 , -1.47525319e-04 , -2.41998964e-04 , -7.24967136e-04 , -4.49685991e-05 , +7.30327855e-05 , -7.40137176e-05 , +6.59539212e-05 , -2.88277013e-05 , +7.01714628e-06 ], [ +1.07326424e+01 , +2.72961422e+01 , +3.08517093e+01 , +2.09243877e+01 , +6.78971087e+00 , -1.20198675e+00 , -1.78013092e+00 , -4.12741140e-01 , -1.13343829e+01 , -3.03721286e+01 , -3.70059336e+01 , -2.67007286e+01 , -8.78688082e+00 , +2.16732861e+00 , +3.07444525e+00 , +8.18326743e-01 , -3.55620410e+00 , -6.05477908e+00 , -6.17105792e-01 , +5.79834358e+00 , +5.88129151e+00 , +1.95117019e+00 , +4.75788247e-03 , -9.34685366e-03 , +8.03385351e-01 , +1.34370771e+00 , -1.10156830e-01 , -1.96826295e+00 , -2.02953739e+00 , -7.79325366e-01 , -4.48896157e-04 , +5.99194963e-04 , -1.67760279e-01 , -4.92967114e-01 , -5.89983939e-01 , -3.45130767e-01 , -2.24934808e-03 , +5.12873094e-03 , -9.43933585e-04 , +1.62428178e-03 , +3.33558699e-02 , +1.00645901e-01 , +1.12908315e-01 , +7.75632007e-02 , +3.21010483e-04 , -4.47617442e-04 , +2.26457038e-04 , -2.41331304e-04 , +1.85038643e-03 , +4.81901216e-03 , +2.68751414e-04 , -7.17942224e-04 , +2.38973419e-04 , -3.56454344e-04 , +1.40452020e-04 , -2.13945344e-04 , -2.48072180e-04 , -7.67791109e-04 , -5.90737875e-05 , +1.03390024e-04 , -8.70430417e-05 , +8.92952512e-05 , -4.41152932e-05 , +3.28087412e-05 ], [ +6.75380817e+00 , +1.75339421e+01 , +2.09243877e+01 , +1.59716063e+01 , +7.13399329e+00 , +8.71480564e-01 , -6.47324653e-01 , -2.06400474e-01 , -7.38161742e+00 , -1.97748537e+01 , -2.48822797e+01 , -2.00185546e+01 , -9.29228728e+00 , -1.08019525e+00 , +1.11973389e+00 , +4.08083195e-01 , -3.97334744e+00 , -8.28852069e+00 , -5.66492619e+00 , -1.96714051e-01 , +2.14059303e+00 , +9.72812934e-01 , +3.73968914e-03 , -6.46977724e-03 , +9.45721973e-01 , +2.00614963e+00 , +1.38147405e+00 , -7.39925977e-02 , -7.38953239e-01 , -3.88652594e-01 , -2.44397697e-04 , +5.40516249e-04 , -1.46118789e-02 , -1.12839852e-01 , -2.15407056e-01 , -1.71061496e-01 , -1.58842691e-03 , +3.47750188e-03 , -6.57672843e-04 , +1.00975956e-03 , +5.38674913e-03 , +2.85395155e-02 , +4.11033431e-02 , +3.86636488e-02 , +9.57096141e-05 , -2.43325480e-04 , +1.11219526e-04 , -1.73906206e-04 , +6.94735976e-04 , +2.32756351e-03 , +1.72534544e-04 , -4.54457176e-04 , +1.48573809e-04 , -2.21570151e-04 , +8.92714594e-05 , -1.22428827e-04 , -9.15028132e-05 , -3.79520424e-04 , -2.47685280e-05 , +5.14415522e-05 , -3.38221017e-05 , +4.08127877e-05 , -1.79855445e-05 , +2.01134776e-05 ], [ +1.77302640e+00 , +4.84077677e+00 , +6.78971085e+00 , +7.13399329e+00 , +5.45078785e+00 , +2.68292167e+00 , +7.21375013e-01 , +7.75881757e-02 , -2.71472615e+00 , -7.17973487e+00 , -9.68701212e+00 , -9.85659382e+00 , -7.34902805e+00 , -3.56997318e+00 , -9.50848950e-01 , -9.85029370e-02 , -3.49420597e+00 , -8.57456944e+00 , -9.31626879e+00 , -6.25175245e+00 , -2.37985521e+00 , -3.69419384e-01 , +1.29040028e-03 , +7.28907342e-04 , +8.76527543e-01 , +2.16444406e+00 , +2.38328416e+00 , +1.62603650e+00 , +6.28271374e-01 , +9.32978712e-02 , +2.68823152e-04 , -1.68692490e-04 , +1.49610663e-01 , +3.14498460e-01 , +2.37733053e-01 , +6.58688849e-02 , -3.62660945e-04 , -3.46243404e-04 , -2.69261299e-05 , -3.61194367e-04 , -2.15182352e-02 , -4.50862489e-02 , -3.50723337e-02 , -9.06358508e-03 , -2.59958962e-04 , +2.47794970e-04 , -1.39142538e-04 , +1.30483974e-04 , -7.18171794e-04 , -9.46516814e-04 , +5.74404093e-06 , +8.23988495e-05 , +5.20180553e-06 , +5.16178171e-05 , -2.85216961e-05 , +8.67492299e-05 , +8.12470741e-05 , +6.80502614e-05 , +3.76643891e-05 , -5.72730087e-05 , +4.81831226e-05 , -5.26892601e-05 , +3.76242631e-05 , -3.73320890e-05 ], [ -6.84112191e-01 , -1.66256297e+00 , -1.20198676e+00 , +8.71480558e-01 , +2.68292167e+00 , +2.50274085e+00 , +1.10737906e+00 , +1.90318472e-01 , -1.74878087e-01 , -3.30139335e-01 , -8.44759084e-01 , -2.37547360e+00 , -3.61774441e+00 , -3.03871428e+00 , -1.39919684e+00 , -2.76948349e-01 , -2.11828143e+00 , -5.77888818e+00 , -7.67200655e+00 , -6.76301160e+00 , -3.65574211e+00 , -8.99584691e-01 , -6.76569040e-04 , +5.37599144e-03 , +5.19547282e-01 , +1.39609471e+00 , +1.82776666e+00 , +1.63324906e+00 , +9.24295294e-01 , +2.62905879e-01 , +5.63053977e-04 , -7.58338682e-04 , +1.73158663e-01 , +4.02083923e-01 , +3.66068969e-01 , +1.58454175e-01 , +4.38421027e-04 , -2.73248171e-03 , +3.69728163e-04 , -1.11920657e-03 , -2.36814914e-02 , -5.68516879e-02 , -5.16074562e-02 , -2.57667257e-02 , -3.82509996e-04 , +5.17098493e-04 , -2.68592722e-04 , +3.36979790e-04 , -1.13047468e-03 , -2.16750571e-03 , -8.54703015e-05 , +3.83708324e-04 , -6.91558748e-05 , +2.00204398e-04 , -9.33756340e-05 , +1.91551440e-04 , +1.21629453e-04 , +2.15064263e-04 , +6.24680716e-05 , -1.09361373e-04 , +7.84590747e-05 , -9.62804317e-05 , +6.39648556e-05 , -7.22203671e-05 ], [ -6.54206766e-01 , -1.69903464e+00 , -1.78013092e+00 , -6.47324656e-01 , +7.21375012e-01 , +1.10737906e+00 , +5.89181578e-01 , +1.13115025e-01 , +2.76106053e-01 , +8.20026094e-01 , +9.49474837e-01 , +2.14299002e-01 , -8.29935587e-01 , -1.12722881e+00 , -6.44440192e-01 , -1.45734250e-01 , -7.54345816e-01 , -2.20385299e+00 , -3.25886973e+00 , -3.21887372e+00 , -1.94562005e+00 , -5.32998890e-01 , -1.02024946e-03 , +4.25939321e-03 , +1.54178875e-01 , +4.42807013e-01 , +6.46723370e-01 , +6.61178350e-01 , +4.25761129e-01 , +1.38224307e-01 , +3.76128909e-04 , -5.69574089e-04 , +8.51518736e-02 , +2.04093210e-01 , +1.95048293e-01 , +9.32815939e-02 , +4.66944603e-04 , -2.14579453e-03 , +3.03633025e-04 , -7.85859258e-04 , -9.98695833e-03 , -2.51514750e-02 , -2.38031652e-02 , -1.34898398e-02 , -2.17819013e-04 , +3.33790789e-04 , -1.70099932e-04 , +2.28610888e-04 , -6.08005395e-04 , -1.24177211e-03 , -6.65943614e-05 , +2.81559820e-04 , -5.31061368e-05 , +1.42569467e-04 , -6.47466824e-05 , +1.24280760e-04 , +5.77842166e-05 , +1.07006895e-04 , +3.60446395e-05 , -6.69690940e-05 , +4.50608719e-05 , -5.87147591e-05 , +3.87120822e-05 , -4.57872945e-05 ], [ -1.39507729e-01 , -3.69347991e-01 , -4.12741140e-01 , -2.06400475e-01 , +7.75881755e-02 , +1.90318472e-01 , +1.13115025e-01 , +2.32646180e-02 , +7.66538334e-02 , +2.21516751e-01 , +2.80737665e-01 , +1.64301731e-01 , -4.91638023e-02 , -1.54584678e-01 , -1.04009469e-01 , -2.53248631e-02 , -1.15463245e-01 , -3.52383632e-01 , -5.54827710e-01 , -5.82599706e-01 , -3.73723060e-01 , -1.09099882e-01 , -3.75380612e-04 , +1.20382089e-03 , +1.64195612e-02 , +5.15047376e-02 , +8.46029279e-02 , +9.75224142e-02 , +6.87293530e-02 , +2.39908996e-02 , +8.34493592e-05 , -1.30629457e-04 , +1.57617385e-02 , +3.83959866e-02 , +3.75256494e-02 , +1.89047321e-02 , +1.52795123e-04 , -6.00125848e-04 , +8.38734411e-05 , -1.99694876e-04 , -1.51926328e-03 , -3.94815364e-03 , -3.84851852e-03 , -2.32871614e-03 , -4.37745728e-05 , +7.15227057e-05 , -3.61306006e-05 , +4.97187484e-05 , -1.18293305e-04 , -2.41147735e-04 , -1.78582518e-05 , +7.43243106e-05 , -1.39029362e-05 , +3.61955020e-05 , -1.56800116e-05 , +2.90415623e-05 , +9.64489117e-06 , +1.72632625e-05 , +7.16729874e-06 , -1.38098126e-05 , +8.98217711e-06 , -1.21227397e-05 , +7.96991794e-06 , -9.59765553e-06 ], [ -4.36967834e+00 , -1.06680161e+01 , -1.13343829e+01 , -7.38161743e+00 , -2.71472616e+00 , -1.74878095e-01 , +2.76106050e-01 , +7.66538327e-02 , +1.14317912e+01 , +3.12030287e+01 , +4.11085373e+01 , +3.71761363e+01 , +2.38185130e+01 , +1.04813369e+01 , +2.88928109e+00 , +3.71912897e-01 , +1.81591960e+00 , +3.54807042e+00 , +2.03380600e+00 , -2.41663959e-01 , -9.12497307e-01 , -3.63245856e-01 , -5.24309938e-04 , +1.08572079e-03 , -3.00087103e+00 , -7.24520358e+00 , -7.58791039e+00 , -4.88303220e+00 , -1.90682820e+00 , -3.54367279e-01 , -1.27406828e-04 , +3.80646344e-04 , +9.40583293e-03 , +5.60428696e-02 , +9.15661470e-02 , +6.45647468e-02 , +3.04697354e-04 , -6.13531385e-04 , +1.05151516e-04 , -2.11409275e-04 , +6.69606087e-02 , +1.40696276e-01 , +1.05964317e-01 , +3.53205177e-02 , -3.52701292e-06 , -1.19507597e-04 , +6.41980513e-05 , -1.43862303e-04 , -2.90647139e-04 , -9.11748744e-04 , -5.40864384e-05 , +1.05168711e-04 , -3.49416988e-05 , +4.64931595e-05 , -1.78809290e-05 , +2.95185424e-05 , -2.23824279e-04 , -3.58437845e-04 , -1.36616121e-06 , +1.48464038e-05 , +1.39162680e-07 , +1.75021102e-05 , -1.64920060e-05 , +3.08317964e-05 ], [ -1.16814935e+01 , -2.85412091e+01 , -3.03721286e+01 , -1.97748537e+01 , -7.17973490e+00 , -3.30139359e-01 , +8.20026085e-01 , +2.21516749e-01 , +3.12030287e+01 , +8.53351169e+01 , +1.12944008e+02 , +1.02972988e+02 , +6.67477894e+01 , +2.98232942e+01 , +8.35696946e+00 , +1.08910158e+00 , +4.74034465e+00 , +9.17792161e+00 , +5.01067658e+00 , -1.06577019e+00 , -2.70933541e+00 , -1.04960309e+00 , -1.21686401e-03 , +3.54745607e-03 , -8.41086157e+00 , -2.03596031e+01 , -2.14467427e+01 , -1.39341511e+01 , -5.51527141e+00 , -1.03788052e+00 , -2.82604604e-04 , +9.23143951e-04 , +3.67389252e-02 , +1.77488855e-01 , +2.71784497e-01 , +1.86331667e-01 , +7.38936232e-04 , -1.92155846e-03 , +2.93355296e-04 , -7.19998335e-04 , +1.91279273e-01 , +4.03391305e-01 , +3.06444642e-01 , +1.03541509e-01 , -4.53699942e-05 , -2.69889065e-04 , +1.48738764e-04 , -3.49671968e-04 , -8.61971728e-04 , -2.61228008e-03 , -1.50283045e-04 , +3.24108037e-04 , -9.09262792e-05 , +1.44464624e-04 , -5.86154509e-05 , +1.11307863e-04 , -6.44720523e-04 , -1.06199882e-03 , +5.46427262e-06 , +2.66530662e-05 , +7.93197907e-06 , +3.81841075e-05 , -3.82509369e-05 , +7.47396899e-05 ], [ -1.39547031e+01 , -3.42584233e+01 , -3.70059336e+01 , -2.48822798e+01 , -9.68701216e+00 , -8.44759114e-01 , +9.49474824e-01 , +2.80737663e-01 , +4.11085373e+01 , +1.12944008e+02 , +1.51803696e+02 , +1.42849857e+02 , +9.71134767e+01 , +4.61096176e+01 , +1.38010921e+01 , +1.90965491e+00 , +6.17602531e+00 , +1.22698388e+01 , +7.40432170e+00 , -4.52431042e-01 , -3.13631869e+00 , -1.32900027e+00 , -1.12028539e-03 , +5.98459982e-03 , -1.22804119e+01 , -3.00244533e+01 , -3.23575173e+01 , -2.18358194e+01 , -9.10838689e+00 , -1.82010155e+00 , -2.93535339e-04 , +9.83278190e-04 , +2.88385993e-02 , +1.85626391e-01 , +3.14674599e-01 , +2.35073678e-01 , +6.96656797e-04 , -3.04659259e-03 , +3.90216439e-04 , -1.25546623e-03 , +3.01290750e-01 , +6.45674346e-01 , +5.06049294e-01 , +1.81749205e-01 , -3.16346981e-05 , -3.15328136e-04 , +1.73354960e-04 , -3.84477793e-04 , -1.00664774e-03 , -3.22833335e-03 , -1.85085726e-04 , +4.85316781e-04 , -9.24057092e-05 , +2.20975553e-04 , -1.00341379e-04 , +2.18862704e-04 , -1.06226522e-03 , -1.88370223e-03 , +9.27544182e-06 , +3.02061923e-05 , +2.11084765e-06 , +4.83814974e-05 , -4.29649497e-05 , +7.97249392e-05 ], [ -9.53518416e+00 , -2.36338271e+01 , -2.67007286e+01 , -2.00185546e+01 , -9.85659385e+00 , -2.37547363e+00 , +2.14298990e-01 , +1.64301729e-01 , +3.71761363e+01 , +1.02972988e+02 , +1.42849857e+02 , +1.43732679e+02 , +1.07658030e+02 , +5.73396043e+01 , +1.92930394e+01 , +2.96461771e+00 , +6.04037681e+00 , +1.31115645e+01 , +1.06180810e+01 , +3.68943111e+00 , -7.07110240e-01 , -7.76503979e-01 , +1.42909822e-04 , +5.50818085e-03 , -1.38191645e+01 , -3.44213470e+01 , -3.86772354e+01 , -2.79165129e+01 , -1.27337323e+01 , -2.82532609e+00 , -4.62487982e-04 , +1.03979948e-03 , -7.00237233e-02 , -6.20066692e-02 , +7.13071770e-02 , +1.36189584e-01 , -6.97718975e-05 , -2.50011121e-03 , +1.74239030e-04 , -1.18157252e-03 , +3.89970453e-01 , +8.60008166e-01 , +7.07567767e-01 , +2.82067885e-01 , +2.31769608e-04 , -5.33793624e-04 , +2.69570215e-04 , -4.40507545e-04 , -2.59229168e-04 , -1.76341574e-03 , -1.06360905e-04 , +3.75452571e-04 , -2.90606669e-07 , +1.60742001e-04 , -8.44068098e-05 , +2.37405475e-04 , -1.49022835e-03 , -2.91783739e-03 , -2.52032598e-05 , +8.61237390e-05 , -5.54383584e-05 , +9.53166240e-05 , -6.07664654e-05 , +8.47178528e-05 ], [ -2.62228452e+00 , -6.59254846e+00 , -8.78688083e+00 , -9.29228730e+00 , -7.34902807e+00 , -3.61774442e+00 , -8.29935594e-01 , -4.91638035e-02 , +2.38185130e+01 , +6.67477894e+01 , +9.71134767e+01 , +1.07658030e+02 , +9.15037261e+01 , +5.55978813e+01 , +2.10783981e+01 , +3.57095294e+00 , +4.51284991e+00 , +1.10836104e+01 , +1.19768822e+01 , +7.99111674e+00 , +2.74211987e+00 , +2.33328782e-01 , +1.71236945e-03 , +9.07076298e-04 , -1.20965161e+01 , -3.07653629e+01 , -3.61629417e+01 , -2.79678907e+01 , -1.39131023e+01 , -3.40212609e+00 , -1.01258271e-03 , +1.79971426e-03 , -1.83045533e-01 , -3.72925706e-01 , -2.74416636e-01 , -4.24452290e-02 , -9.68148998e-04 , +2.35277546e-05 , -2.80476940e-04 , -2.69656211e-04 , +3.97093770e-01 , +9.00935745e-01 , +7.73352363e-01 , +3.39186852e-01 , +6.69024134e-04 , -1.06832997e-03 , +5.09598895e-04 , -7.37809353e-04 , +8.17788389e-04 , +7.26501209e-04 , +2.68606778e-05 , +5.61497204e-07 , +1.14307376e-04 , -3.33589805e-05 , +1.82422576e-06 , +1.03373337e-04 , -1.64168366e-03 , -3.46165373e-03 , -9.40183924e-05 , +2.04384183e-04 , -1.43188313e-04 , +1.87544958e-04 , -1.09339981e-04 , +1.35368384e-04 ], [ +1.14105816e+00 , +2.92322623e+00 , +2.16732861e+00 , -1.08019526e+00 , -3.56997319e+00 , -3.03871429e+00 , -1.12722881e+00 , -1.54584678e-01 , +1.04813369e+01 , +2.98232942e+01 , +4.61096176e+01 , +5.73396043e+01 , +5.55978813e+01 , +3.81241085e+01 , +1.59663376e+01 , +2.91728724e+00 , +2.36919403e+00 , +6.59289808e+00 , +8.78865430e+00 , +7.60698048e+00 , +3.72367867e+00 , +7.30042451e-01 , +2.42463779e-03 , -3.53129165e-03 , -7.65691083e+00 , -1.98246537e+01 , -2.41930022e+01 , -1.97825973e+01 , -1.05394613e+01 , -2.77833093e+00 , -1.35203771e-03 , +2.41686301e-03 , -1.84685838e-01 , -4.17784410e-01 , -3.73078533e-01 , -1.29104629e-01 , -1.23615787e-03 , +2.14567679e-03 , -5.37324965e-04 , +5.55056952e-04 , +2.85606165e-01 , +6.62710415e-01 , +5.86050234e-01 , +2.76512615e-01 , +8.07577106e-04 , -1.32187708e-03 , +6.14527580e-04 , -9.18102798e-04 , +1.14059317e-03 , +1.84389411e-03 , +9.72361742e-05 , -2.79821982e-04 , +1.43484908e-04 , -1.66500585e-04 , +6.80195000e-05 , -3.87250767e-05 , -1.25488176e-03 , -2.77577780e-03 , -1.20393458e-04 , +2.51975822e-04 , -1.63937327e-04 , +2.18045341e-04 , -1.28374788e-04 , +1.64992498e-04 ], [ +1.16365187e+00 , +3.04630046e+00 , +3.07444525e+00 , +1.11973389e+00 , -9.50848952e-01 , -1.39919685e+00 , -6.44440193e-01 , -1.04009469e-01 , +2.88928109e+00 , +8.35696946e+00 , +1.38010921e+01 , +1.92930394e+01 , +2.10783981e+01 , +1.59663376e+01 , +7.23414643e+00 , +1.40269743e+00 , +7.71439142e-01 , +2.41412066e+00 , +3.75298326e+00 , +3.76199858e+00 , +2.12858824e+00 , +4.90853807e-01 , +1.49512374e-03 , -2.98025002e-03 , -3.04054349e+00 , -7.97570913e+00 , -1.00022444e+01 , -8.51808184e+00 , -4.77559253e+00 , -1.33528020e+00 , -9.80559904e-04 , +1.80431522e-03 , -9.47227842e-02 , -2.22636089e-01 , -2.13349891e-01 , -8.65102744e-02 , -6.78738774e-04 , +1.60887340e-03 , -3.13509246e-04 , +4.45545001e-04 , +1.24869469e-01 , +2.94783588e-01 , +2.65670205e-01 , +1.32613143e-01 , +5.08491361e-04 , -8.93882920e-04 , +4.04714749e-04 , -6.34999593e-04 , +6.56476325e-04 , +1.21083239e-03 , +5.96368584e-05 , -1.97973667e-04 , +7.01242203e-05 , -1.04499532e-04 , +4.32259650e-05 , -4.46472027e-05 , -5.74559892e-04 , -1.30536890e-03 , -7.80257296e-05 , +1.64720522e-04 , -9.77939519e-05 , +1.37205629e-04 , -8.14635493e-05 , +1.10821099e-04 ], [ +2.82352691e-01 , +7.54658910e-01 , +8.18326743e-01 , +4.08083194e-01 , -9.85029374e-02 , -2.76948349e-01 , -1.45734250e-01 , -2.53248631e-02 , +3.71912897e-01 , +1.08910158e+00 , +1.90965491e+00 , +2.96461771e+00 , +3.57095294e+00 , +2.91728724e+00 , +1.40269743e+00 , +2.85127304e-01 , +1.19439277e-01 , +4.11800989e-01 , +7.12732913e-01 , +7.82377936e-01 , +4.81262018e-01 , +1.19680443e-01 , +3.08297799e-04 , -6.63926587e-04 , -5.38240281e-01 , -1.42428027e+00 , -1.81908652e+00 , -1.59339293e+00 , -9.26080584e-01 , -2.71222197e-01 , -3.11630207e-04 , +5.78111554e-04 , -2.02534543e-02 , -4.85196776e-02 , -4.82261437e-02 , -2.11488684e-02 , -1.23668355e-04 , +3.36213414e-04 , -5.52757782e-05 , +8.72816072e-05 , +2.36500679e-02 , +5.65674106e-02 , +5.15568750e-02 , +2.68472703e-02 , +1.40798929e-04 , -2.63852214e-04 , +1.15985617e-04 , -1.89201177e-04 , +1.48041102e-04 , +2.99858329e-04 , +9.98230616e-06 , -3.79678968e-05 , +1.02222637e-05 , -1.79057052e-05 , +6.97543732e-06 , -8.24734878e-06 , -1.13128644e-04 , -2.56436193e-04 , -2.15720741e-05 , +4.64143704e-05 , -2.50973326e-05 , +3.73472480e-05 , -2.20548302e-05 , +3.16066186e-05 ], [ -9.81697530e-01 , -2.57832310e+00 , -3.55620409e+00 , -3.97334744e+00 , -3.49420597e+00 , -2.11828143e+00 , -7.54345817e-01 , -1.15463245e-01 , +1.81591959e+00 , +4.74034463e+00 , +6.17602528e+00 , +6.04037679e+00 , +4.51284989e+00 , +2.36919403e+00 , +7.71439140e-01 , +1.19439276e-01 , +2.49151001e+00 , +6.24660325e+00 , +7.17060106e+00 , +5.36066563e+00 , +2.49005314e+00 , +5.44842201e-01 , +3.35290771e-04 , -4.15702502e-03 , -5.76362318e-01 , -1.42956699e+00 , -1.59546840e+00 , -1.14846076e+00 , -5.09858147e-01 , -1.12920345e-01 , -4.79882627e-04 , +6.47214307e-04 , -1.34611496e-01 , -2.97387715e-01 , -2.49319125e-01 , -9.54390148e-02 , -2.14497672e-04 , +2.04442703e-03 , -2.54681477e-04 , +8.60109746e-04 , +1.58700003e-02 , +3.49651640e-02 , +2.85412381e-02 , +1.08545709e-02 , +3.10016371e-04 , -4.24269089e-04 , +2.21091996e-04 , -2.82681966e-04 , +7.68664524e-04 , +1.27384559e-03 , +4.93996724e-05 , -2.77315521e-04 , +3.61506207e-05 , -1.44745550e-04 , +7.11678830e-05 , -1.51181286e-04 , -7.04579981e-05 , -6.94562657e-05 , -4.87365770e-05 , +8.65282814e-05 , -6.00152887e-05 , +7.69086531e-05 , -5.32406461e-05 , +6.22715882e-05 ], [ -1.41339773e+00 , -3.82240743e+00 , -6.05477906e+00 , -8.28852068e+00 , -8.57456944e+00 , -5.77888818e+00 , -2.20385299e+00 , -3.52383632e-01 , +3.54807040e+00 , +9.17792155e+00 , +1.22698387e+01 , +1.31115644e+01 , +1.10836104e+01 , +6.59289806e+00 , +2.41412065e+00 , +4.11800988e-01 , +6.24660325e+00 , +1.59800831e+01 , +1.90434018e+01 , +1.49211603e+01 , +7.27543922e+00 , +1.66312017e+00 , +1.45640551e-03 , -1.21083109e-02 , -1.45047950e+00 , -3.67240669e+00 , -4.28358540e+00 , -3.29872904e+00 , -1.59523802e+00 , -3.89997483e-01 , -1.31675617e-03 , +1.77345063e-03 , -3.76982768e-01 , -8.46203904e-01 , -7.28599609e-01 , -2.91672543e-01 , -8.36990627e-04 , +6.01830066e-03 , -7.85984173e-04 , +2.46703885e-03 , +4.62683573e-02 , +1.05003114e-01 , +8.92117267e-02 , +3.78034703e-02 , +8.55226172e-04 , -1.17062878e-03 , +6.09805568e-04 , -7.73371584e-04 , +2.24942036e-03 , +3.91588377e-03 , +1.62552119e-04 , -8.18544500e-04 , +1.23930017e-04 , -4.25165537e-04 , +2.04983160e-04 , -4.25056593e-04 , -2.16306940e-04 , -2.74310948e-04 , -1.35201659e-04 , +2.39988586e-04 , -1.68367469e-04 , +2.13344875e-04 , -1.45832037e-04 , +1.68245030e-04 ], [ +6.15364053e-01 , +1.32299678e+00 , -6.17105761e-01 , -5.66492617e+00 , -9.31626879e+00 , -7.67200655e+00 , -3.25886973e+00 , -5.54827710e-01 , +2.03380597e+00 , +5.01067651e+00 , +7.40432160e+00 , +1.06180809e+01 , +1.19768821e+01 , +8.78865428e+00 , +3.75298326e+00 , +7.12732912e-01 , +7.17060106e+00 , +1.90434018e+01 , +2.42370038e+01 , +2.04989214e+01 , +1.07594198e+01 , +2.61885414e+00 , +3.13791727e-03 , -1.83080465e-02 , -1.65494163e+00 , -4.34130262e+00 , -5.43315155e+00 , -4.60912534e+00 , -2.47956386e+00 , -6.75855854e-01 , -1.85558067e-03 , +2.53164340e-03 , -5.23933904e-01 , -1.20436098e+00 , -1.07780208e+00 , -4.59767965e-01 , -1.64529377e-03 , +9.19823674e-03 , -1.26700244e-03 , +3.64238943e-03 , +6.60718229e-02 , +1.55771547e-01 , +1.38563993e-01 , +6.59115957e-02 , +1.19626000e-03 , -1.65741613e-03 , +8.59617771e-04 , -1.08928361e-03 , +3.33563885e-03 , +6.20286492e-03 , +2.77925529e-04 , -1.25005940e-03 , +2.17892056e-04 , -6.44493632e-04 , +3.03740170e-04 , -6.10625321e-04 , -3.31812557e-04 , -5.18447445e-04 , -1.91711433e-04 , +3.41348789e-04 , -2.40944511e-04 , +3.02159478e-04 , -2.02581790e-04 , +2.31220011e-04 ], [ +2.54529067e+00 , +6.42484070e+00 , +5.79834361e+00 , -1.96714034e-01 , -6.25175245e+00 , -6.76301160e+00 , -3.21887372e+00 , -5.82599706e-01 , -2.41663982e-01 , -1.06577025e+00 , -4.52431124e-01 , +3.68943104e+00 , +7.99111670e+00 , +7.60698046e+00 , +3.76199857e+00 , +7.82377936e-01 , +5.36066562e+00 , +1.49211603e+01 , +2.04989214e+01 , +1.88082922e+01 , +1.06287695e+01 , +2.74834889e+00 , +4.43748176e-03 , -1.98970029e-02 , -1.22133268e+00 , -3.34052456e+00 , -4.50936393e+00 , -4.20303844e+00 , -2.48531738e+00 , -7.42300794e-01 , -1.85040212e-03 , +2.63832918e-03 , -4.88174286e-01 , -1.14780642e+00 , -1.06514748e+00 , -4.82144064e-01 , -2.14894147e-03 , +1.00585042e-02 , -1.45035502e-03 , +3.83341216e-03 , +6.17682332e-02 , +1.50688257e-01 , +1.38856067e-01 , +7.25666544e-02 , +1.15367984e-03 , -1.65868124e-03 , +8.53510160e-04 , -1.10608413e-03 , +3.30897023e-03 , +6.48262246e-03 , +3.22988798e-04 , -1.35039207e-03 , +2.57042358e-04 , -6.92016303e-04 , +3.22007848e-04 , -6.24981295e-04 , -3.31926744e-04 , -5.87907726e-04 , -1.88515033e-04 , +3.40225401e-04 , -2.36681751e-04 , +2.99310789e-04 , -1.98203430e-04 , +2.28622096e-04 ], [ +2.16101379e+00 , +5.61261494e+00 , +5.88129152e+00 , +2.14059304e+00 , -2.37985520e+00 , -3.65574211e+00 , -1.94562005e+00 , -3.73723060e-01 , -9.12497318e-01 , -2.70933544e+00 , -3.13631873e+00 , -7.07110278e-01 , +2.74211984e+00 , +3.72367866e+00 , +2.12858824e+00 , +4.81262017e-01 , +2.49005314e+00 , +7.27543922e+00 , +1.07594198e+01 , +1.06287695e+01 , +6.42551597e+00 , +1.76102482e+00 , +3.72959779e-03 , -1.40494294e-02 , -5.09308000e-01 , -1.46272160e+00 , -2.13632497e+00 , -2.18393347e+00 , -1.40628896e+00 , -4.56464149e-01 , -1.24076035e-03 , +1.87893338e-03 , -2.81219915e-01 , -6.74058102e-01 , -6.44272286e-01 , -3.08216741e-01 , -1.68247061e-03 , +7.07708656e-03 , -1.04388149e-03 , +2.59227648e-03 , +3.29878099e-02 , +8.30710060e-02 , +7.86214528e-02 , +4.45490536e-02 , +7.18689616e-04 , -1.10116235e-03 , +5.61108894e-04 , -7.54068948e-04 , +2.01058942e-03 , +4.10399803e-03 , +2.28514285e-04 , -9.28619389e-04 , +1.81676676e-04 , -4.70179015e-04 , +2.17537114e-04 , -4.10013431e-04 , -1.90841881e-04 , -3.53471382e-04 , -1.18957155e-04 , +2.20963041e-04 , -1.48684798e-04 , +1.93701402e-04 , -1.27701445e-04 , +1.51019338e-04 ], [ +6.60664612e-01 , +1.74814857e+00 , +1.95117019e+00 , +9.72812936e-01 , -3.69419383e-01 , -8.99584690e-01 , -5.32998889e-01 , -1.09099882e-01 , -3.63245859e-01 , -1.04960310e+00 , -1.32900028e+00 , -7.76503988e-01 , +2.33328776e-01 , +7.30042448e-01 , +4.90853806e-01 , +1.19680442e-01 , +5.44842201e-01 , +1.66312017e+00 , +2.61885414e+00 , +2.74834889e+00 , +1.76102482e+00 , +5.12625096e-01 , +1.80124197e-03 , -5.14696034e-03 , -7.74984365e-02 , -2.43240979e-01 , -3.99575643e-01 , -4.60656797e-01 , -3.24359936e-01 , -1.13369138e-01 , -3.98311416e-04 , +6.23680495e-04 , -7.43120842e-02 , -1.81044750e-01 , -1.76837465e-01 , -8.91120487e-02 , -7.33360666e-04 , +2.56171737e-03 , -4.02301065e-04 , +8.86632630e-04 , +7.17166737e-03 , +1.86510559e-02 , +1.81640335e-02 , +1.10010480e-02 , +2.08902712e-04 , -3.41560152e-04 , +1.72632755e-04 , -2.37645459e-04 , +5.57815810e-04 , +1.15228292e-03 , +8.56290963e-05 , -3.25310428e-04 , +6.67557419e-05 , -1.60728992e-04 , +7.51496669e-05 , -1.33122261e-04 , -4.55913623e-05 , -8.12195921e-05 , -3.41714846e-05 , +6.59235503e-05 , -4.28771927e-05 , +5.79188403e-05 , -3.80974837e-05 , +4.59077793e-05 ], [ +1.36501058e-03 , +3.73980972e-03 , +4.75788248e-03 , +3.73968914e-03 , +1.29040028e-03 , -6.76569047e-04 , -1.02024947e-03 , -3.75380612e-04 , -5.24309954e-04 , -1.21686405e-03 , -1.12028544e-03 , +1.42909780e-04 , +1.71236943e-03 , +2.42463779e-03 , +1.49512373e-03 , +3.08297799e-04 , +3.35290775e-04 , +1.45640552e-03 , +3.13791728e-03 , +4.43748178e-03 , +3.72959780e-03 , +1.80124197e-03 , +3.79366732e-04 , +6.20661660e-06 , -3.64477856e-04 , -1.00940102e-03 , -1.45031458e-03 , -1.41712009e-03 , -9.86905498e-04 , -2.93933287e-04 , -1.60146825e-08 , -1.28339567e-07 , -1.65396228e-04 , -4.20966460e-04 , -4.90834024e-04 , -3.28056189e-04 , -1.17291974e-04 , -3.63542275e-06 , -4.06165612e-05 , -1.12613356e-06 , +2.28753972e-05 , +5.40693739e-05 , +5.49030020e-05 , +2.94033428e-05 , +2.49843908e-08 , +7.41658905e-08 , -6.35909243e-08 , +1.48478834e-07 , +3.53863927e-06 , +5.20953220e-06 , +7.82865789e-06 , +4.50583886e-07 , +3.94662688e-06 , +2.79080358e-07 , +3.20705384e-06 , +1.53379090e-07 , -1.19565301e-07 , -3.05685857e-07 , -1.26922121e-08 , -6.93182287e-09 , +7.38522857e-10 , -2.14682175e-08 , +2.05157096e-08 , -4.08437804e-08 ], [ -2.32275170e-03 , -6.84283128e-03 , -9.34685370e-03 , -6.46977726e-03 , +7.28907337e-04 , +5.37599144e-03 , +4.25939321e-03 , +1.20382089e-03 , +1.08572082e-03 , +3.54745616e-03 , +5.98459993e-03 , +5.50818095e-03 , +9.07076363e-04 , -3.53129162e-03 , -2.98025001e-03 , -6.63926586e-04 , -4.15702501e-03 , -1.21083109e-02 , -1.83080465e-02 , -1.98970029e-02 , -1.40494294e-02 , -5.14696034e-03 , +6.20661661e-06 , +4.29086475e-04 , +3.49959305e-04 , +1.07184733e-03 , +1.88253682e-03 , +2.34239246e-03 , +1.96684140e-03 , +6.33369414e-04 , -1.84452144e-07 , +4.39075084e-07 , +5.68789498e-04 , +1.36777488e-03 , +1.40280625e-03 , +6.89033310e-04 , -2.53107624e-06 , -1.90489863e-04 , -1.41153381e-06 , -4.41054452e-05 , -4.07528186e-05 , -9.96923337e-05 , -1.09252353e-04 , -6.35669982e-05 , +1.39611343e-07 , -3.16671597e-07 , +2.04712131e-07 , -3.23815730e-07 , -4.18567259e-06 , +1.21992362e-06 , +2.71015917e-07 , +1.88840385e-05 , +2.51176259e-07 , +6.05998145e-06 , +2.44170352e-07 , +3.02285712e-06 , +2.29372615e-07 , +6.85623304e-07 , -1.18627081e-08 , +5.79563467e-08 , -4.11055809e-08 , +7.44950661e-08 , -5.81951310e-08 , +8.17899381e-08 ], [ +2.53968706e-01 , +6.00384512e-01 , +8.03385352e-01 , +9.45721976e-01 , +8.76527546e-01 , +5.19547284e-01 , +1.54178876e-01 , +1.64195614e-02 , -3.00087103e+00 , -8.41086157e+00 , -1.22804119e+01 , -1.38191645e+01 , -1.20965161e+01 , -7.65691083e+00 , -3.04054349e+00 , -5.38240281e-01 , -5.76362320e-01 , -1.45047951e+00 , -1.65494164e+00 , -1.22133269e+00 , -5.09308003e-01 , -7.74984372e-02 , -3.64477858e-04 , +3.49959313e-04 , +1.63341892e+00 , +4.17352151e+00 , +4.95922109e+00 , +3.91156465e+00 , +2.00704211e+00 , +5.12611319e-01 , +2.60646959e-04 , -4.67818302e-04 , +2.91360928e-02 , +6.21265778e-02 , +5.10120555e-02 , +1.37341177e-02 , +1.75011991e-04 , -2.28409250e-04 , +6.78169640e-05 , -3.57322226e-05 , -5.60667093e-02 , -1.28497482e-01 , -1.11597062e-01 , -5.10208078e-02 , -1.39350467e-04 , +2.40657329e-04 , -1.13730319e-04 , +1.72688470e-04 , -1.54341382e-04 , -2.02707611e-04 , -8.84152153e-06 , +2.56588554e-05 , -1.86690510e-05 , +1.65914269e-05 , -5.84519895e-06 , -3.61270472e-06 , +2.38746706e-04 , +5.12701768e-04 , +2.05357669e-05 , -4.43061417e-05 , +2.76745348e-05 , -3.85810496e-05 , +2.33674002e-05 , -3.08495728e-05 ], [ +3.74626666e-01 , +8.55253482e-01 , +1.34370771e+00 , +2.00614964e+00 , +2.16444406e+00 , +1.39609472e+00 , +4.42807015e-01 , +5.15047380e-02 , -7.24520358e+00 , -2.03596031e+01 , -3.00244533e+01 , -3.44213470e+01 , -3.07653629e+01 , -1.98246537e+01 , -7.97570913e+00 , -1.42428027e+00 , -1.42956699e+00 , -3.67240670e+00 , -4.34130264e+00 , -3.34052457e+00 , -1.46272161e+00 , -2.43240980e-01 , -1.00940103e-03 , +1.07184735e-03 , +4.17352151e+00 , +1.06946428e+01 , +1.27834392e+01 , +1.01671401e+01 , +5.26475989e+00 , +1.35641231e+00 , +7.14155351e-04 , -1.26893854e-03 , +8.01539925e-02 , +1.73847021e-01 , +1.46511969e-01 , +4.31149338e-02 , +4.87347323e-04 , -6.81811880e-04 , +1.92619388e-04 , -1.23171973e-04 , -1.45997441e-01 , -3.35647062e-01 , -2.92749264e-01 , -1.34983012e-01 , -3.85579211e-04 , +6.56763887e-04 , -3.09896625e-04 , +4.67425730e-04 , -4.44288989e-04 , -6.32107909e-04 , -2.73519819e-05 , +7.92361158e-05 , -5.23964985e-05 , +4.96411019e-05 , -1.81360992e-05 , -5.15246939e-06 , +6.26582335e-04 , +1.35467889e-03 , +5.70353201e-05 , -1.21568376e-04 , +7.63098574e-05 , -1.05203248e-04 , +6.34394317e-05 , -8.32291916e-05 ], [ -2.05813962e-01 , -6.02361335e-01 , -1.10156827e-01 , +1.38147406e+00 , +2.38328416e+00 , +1.82776666e+00 , +6.46723373e-01 , +8.46029283e-02 , -7.58791039e+00 , -2.14467427e+01 , -3.23575173e+01 , -3.86772354e+01 , -3.61629417e+01 , -2.41930022e+01 , -1.00022444e+01 , -1.81908652e+00 , -1.59546841e+00 , -4.28358541e+00 , -5.43315156e+00 , -4.50936394e+00 , -2.13632498e+00 , -3.99575645e-01 , -1.45031459e-03 , +1.88253684e-03 , +4.95922109e+00 , +1.27834392e+01 , +1.54670703e+01 , +1.25120015e+01 , +6.60256401e+00 , +1.73231109e+00 , +9.59437024e-04 , -1.68745023e-03 , +1.09305341e-01 , +2.43541012e-01 , +2.14025343e-01 , +7.07323678e-02 , +7.02895939e-04 , -1.13602156e-03 , +2.85735523e-04 , -2.50120866e-04 , -1.80410779e-01 , -4.17387445e-01 , -3.67168622e-01 , -1.72349175e-01 , -5.22271216e-04 , +8.77200639e-04 , -4.12357235e-04 , +6.18215580e-04 , -6.52348451e-04 , -1.02094074e-03 , -4.81816794e-05 , +1.38985149e-04 , -7.59528761e-05 , +8.12089328e-05 , -3.07911349e-05 , +7.23658831e-06 , +7.87058011e-04 , +1.72523469e-03 , +7.82414109e-05 , -1.63377462e-04 , +1.03003790e-04 , -1.40136769e-04 , +8.39617951e-05 , -1.09427817e-04 ], [ -8.44468626e-01 , -2.20369524e+00 , -1.96826295e+00 , -7.39925945e-02 , +1.62603650e+00 , +1.63324906e+00 , +6.61178352e-01 , +9.75224145e-02 , -4.88303220e+00 , -1.39341511e+01 , -2.18358194e+01 , -2.79165129e+01 , -2.79678907e+01 , -1.97825973e+01 , -8.51808184e+00 , -1.59339293e+00 , -1.14846077e+00 , -3.29872905e+00 , -4.60912535e+00 , -4.20303845e+00 , -2.18393347e+00 , -4.60656799e-01 , -1.41712009e-03 , +2.34239247e-03 , +3.91156465e+00 , +1.01671401e+01 , +1.25120015e+01 , +1.03676968e+01 , +5.62302818e+00 , +1.51714135e+00 , +9.71867237e-04 , -1.69141413e-03 , +1.03657307e-01 , +2.37964792e-01 , +2.18821221e-01 , +8.14414381e-02 , +6.79215123e-04 , -1.33629760e-03 , +2.97150261e-04 , -3.46092220e-04 , -1.50513165e-01 , -3.51433504e-01 , -3.12750788e-01 , -1.50837667e-01 , -5.21756654e-04 , +8.71536553e-04 , -4.08553737e-04 , +6.11696865e-04 , -6.69781540e-04 , -1.16017365e-03 , -5.37667756e-05 , +1.66671495e-04 , -7.34845303e-05 , +9.30942480e-05 , -3.75853918e-05 , +2.69455792e-05 , +6.73236043e-04 , +1.49902787e-03 , +7.85510454e-05 , -1.61807112e-04 , +1.01410471e-04 , -1.37522779e-04 , +8.25436469e-05 , -1.07792910e-04 ], [ -7.68127323e-01 , -2.01091687e+00 , -2.02953739e+00 , -7.38953238e-01 , +6.28271375e-01 , +9.24295296e-01 , +4.25761130e-01 , +6.87293531e-02 , -1.90682820e+00 , -5.51527141e+00 , -9.10838688e+00 , -1.27337323e+01 , -1.39131023e+01 , -1.05394613e+01 , -4.77559253e+00 , -9.26080584e-01 , -5.09858148e-01 , -1.59523802e+00 , -2.47956387e+00 , -2.48531738e+00 , -1.40628896e+00 , -3.24359937e-01 , -9.86905498e-04 , +1.96684141e-03 , +2.00704211e+00 , +5.26475989e+00 , +6.60256401e+00 , +5.62302818e+00 , +3.15264973e+00 , +8.81571955e-01 , +6.78479103e-04 , -1.19026676e-03 , +6.25809720e-02 , +1.47093047e-01 , +1.40952958e-01 , +5.71682856e-02 , +4.47969855e-04 , -1.06182374e-03 , +2.06971057e-04 , -2.94059449e-04 , -8.24329382e-02 , -1.94603239e-01 , -1.75391241e-01 , -8.75536892e-02 , -3.53254578e-04 , +5.89633619e-04 , -2.75367681e-04 , +4.18884270e-04 , -4.33701128e-04 , -8.00247191e-04 , -3.93489901e-05 , +1.30647868e-04 , -4.62845356e-05 , +6.89773924e-05 , -2.85407222e-05 , +2.94685717e-05 , +3.79553800e-04 , +8.61879037e-04 , +5.24321387e-05 , -1.08655060e-04 , +6.63847454e-05 , -9.05026141e-05 , +5.48512681e-05 , -7.31004204e-05 ], [ -2.69065920e-01 , -7.18947807e-01 , -7.79325366e-01 , -3.88652594e-01 , +9.32978715e-02 , +2.62905880e-01 , +1.38224307e-01 , +2.39908996e-02 , -3.54367279e-01 , -1.03788052e+00 , -1.82010155e+00 , -2.82532609e+00 , -3.40212609e+00 , -2.77833093e+00 , -1.33528020e+00 , -2.71222197e-01 , -1.12920345e-01 , -3.89997484e-01 , -6.75855855e-01 , -7.42300794e-01 , -4.56464149e-01 , -1.13369139e-01 , -2.93933287e-04 , +6.33369415e-04 , +5.12611319e-01 , +1.35641231e+00 , +1.73231109e+00 , +1.51714135e+00 , +8.81571955e-01 , +2.58085674e-01 , +2.98116625e-04 , -4.99926984e-04 , +1.92086777e-02 , +4.60101236e-02 , +4.57418352e-02 , +2.00308179e-02 , +1.17997503e-04 , -3.20710542e-04 , +5.26252708e-05 , -8.32226467e-05 , -2.25165989e-02 , -5.38602969e-02 , -4.90793707e-02 , -2.55654354e-02 , -1.34637006e-04 , +2.23059612e-04 , -1.11012063e-04 , +1.67164285e-04 , -1.40432775e-04 , -2.83845294e-04 , -9.54428270e-06 , +3.62361000e-05 , -9.74840164e-06 , +1.70616106e-05 , -6.62773849e-06 , +7.85548070e-06 , +1.07709515e-04 , +2.45745394e-04 , +2.06157944e-05 , -4.16021614e-05 , +2.40037513e-05 , -3.27956689e-05 , +2.11223256e-05 , -2.84748027e-05 ], [ -5.47673158e-05 , -2.65351684e-04 , -4.48896178e-04 , -2.44397712e-04 , +2.68823147e-04 , +5.63053977e-04 , +3.76128910e-04 , +8.34493595e-05 , -1.27406815e-04 , -2.82604567e-04 , -2.93535290e-04 , -4.62487938e-04 , -1.01258268e-03 , -1.35203770e-03 , -9.80559902e-04 , -3.11630207e-04 , -4.79882624e-04 , -1.31675616e-03 , -1.85558066e-03 , -1.85040212e-03 , -1.24076035e-03 , -3.98311418e-04 , -1.60146832e-08 , -1.84452137e-07 , +2.60646955e-04 , +7.14155344e-04 , +9.59437016e-04 , +9.71867232e-04 , +6.78479102e-04 , +2.98116625e-04 , +6.77784999e-05 , +9.14351850e-07 , +5.23077218e-05 , +1.30000555e-04 , +1.24001658e-04 , +7.18864251e-05 , -5.49476755e-08 , +7.30725384e-08 , +5.76974491e-08 , -1.39623290e-08 , -1.86865840e-05 , -4.39403655e-05 , -5.07064198e-05 , -3.01818438e-05 , -1.32935771e-05 , -4.70388580e-07 , -1.62046751e-05 , -3.52439031e-07 , -3.70467907e-07 , -1.10719001e-06 , +1.77786370e-08 , -2.12041577e-08 , +2.41328517e-09 , +9.19787256e-09 , -1.77057783e-08 , +1.01900611e-08 , +4.39468050e-07 , +3.45871283e-07 , +1.34657038e-06 , +6.65514132e-08 , +1.09219668e-06 , +7.55690007e-08 , +1.79042333e-06 , +7.01705633e-08 ], [ -1.61579955e-05 , +1.96742562e-04 , +5.99194946e-04 , +5.40516236e-04 , -1.68692495e-04 , -7.58338683e-04 , -5.69574089e-04 , -1.30629457e-04 , +3.80646356e-04 , +9.23143984e-04 , +9.83278232e-04 , +1.03979952e-03 , +1.79971428e-03 , +2.41686301e-03 , +1.80431522e-03 , +5.78111554e-04 , +6.47214310e-04 , +1.77345063e-03 , +2.53164340e-03 , +2.63832918e-03 , +1.87893338e-03 , +6.23680494e-04 , -1.28339565e-07 , +4.39075085e-07 , -4.67818304e-04 , -1.26893854e-03 , -1.68745024e-03 , -1.69141414e-03 , -1.19026676e-03 , -4.99926984e-04 , +9.14351854e-07 , +7.72673899e-05 , -7.68120839e-05 , -1.92503844e-04 , -1.87753657e-04 , -1.12618766e-04 , +1.18002440e-07 , -2.17727703e-07 , -2.80655884e-08 , -3.51277604e-08 , +2.72183217e-05 , +6.02108866e-05 , +6.58977204e-05 , +2.40612214e-05 , -3.56488114e-07 , -2.16371197e-05 , -4.20527899e-07 , -1.81558926e-05 , +5.62053615e-07 , +1.73453456e-06 , -2.10426269e-08 , +3.52707077e-08 , -3.83544861e-09 , -9.81415352e-10 , +1.28395117e-08 , -8.28072662e-10 , -1.27407012e-07 , +1.40440073e-06 , +4.92708624e-08 , +2.87985084e-06 , +7.16792636e-08 , +1.71813132e-06 , +9.67577628e-08 , +1.91466896e-06 ], [ -6.88223683e-02 , -1.76403390e-01 , -1.67760280e-01 , -1.46118793e-02 , +1.49610663e-01 , +1.73158663e-01 , +8.51518736e-02 , +1.57617385e-02 , +9.40583353e-03 , +3.67389268e-02 , +2.88386014e-02 , -7.00237214e-02 , -1.83045532e-01 , -1.84685837e-01 , -9.47227841e-02 , -2.02534543e-02 , -1.34611496e-01 , -3.76982768e-01 , -5.23933904e-01 , -4.88174286e-01 , -2.81219915e-01 , -7.43120842e-02 , -1.65396228e-04 , +5.68789498e-04 , +2.91360927e-02 , +8.01539921e-02 , +1.09305341e-01 , +1.03657307e-01 , +6.25809719e-02 , +1.92086777e-02 , +5.23077217e-05 , -7.68120839e-05 , +1.27642410e-02 , +3.01516400e-02 , +2.81978664e-02 , +1.30195063e-02 , +7.32276381e-05 , -2.86285584e-04 , +4.58530585e-05 , -1.07221510e-04 , -1.53554158e-03 , -3.77583979e-03 , -3.49817214e-03 , -1.87432732e-03 , -3.13412423e-05 , +4.65085224e-05 , -2.38273751e-05 , +3.14495864e-05 , -8.83832050e-05 , -1.74134011e-04 , -9.84069350e-06 , +3.79333705e-05 , -7.72996727e-06 , +1.93059463e-05 , -9.56212026e-06 , +1.72571565e-05 , +8.45130747e-06 , +1.48393318e-05 , +5.13365990e-06 , -9.40782090e-06 , +6.42768184e-06 , -8.27186291e-06 , +5.48195854e-06 , -6.40967968e-06 ], [ -1.92158622e-01 , -4.94927723e-01 , -4.92967115e-01 , -1.12839853e-01 , +3.14498460e-01 , +4.02083923e-01 , +2.04093210e-01 , +3.83959866e-02 , +5.60428709e-02 , +1.77488858e-01 , +1.85626396e-01 , -6.20066650e-02 , -3.72925704e-01 , -4.17784409e-01 , -2.22636089e-01 , -4.85196775e-02 , -2.97387715e-01 , -8.46203904e-01 , -1.20436098e+00 , -1.14780642e+00 , -6.74058102e-01 , -1.81044750e-01 , -4.20966459e-04 , +1.36777488e-03 , +6.21265774e-02 , +1.73847020e-01 , +2.43541011e-01 , +2.37964792e-01 , +1.47093047e-01 , +4.60101235e-02 , +1.30000555e-04 , -1.92503844e-04 , +3.01516400e-02 , +7.16892713e-02 , +6.75972310e-02 , +3.17285975e-02 , +1.86082824e-04 , -6.90470766e-04 , +1.13712594e-04 , -2.56938042e-04 , -3.54588185e-03 , -8.79688589e-03 , -8.22371176e-03 , -4.48694248e-03 , -7.60491051e-05 , +1.14611236e-04 , -5.85902587e-05 , +7.77212500e-05 , -2.11135313e-04 , -4.26077508e-04 , -2.48202751e-05 , +9.18151084e-05 , -1.95801498e-05 , +4.67740141e-05 , -2.34247990e-05 , +4.12484662e-05 , +1.99454788e-05 , +3.52870578e-05 , +1.24291020e-05 , -2.29822248e-05 , +1.56080544e-05 , -2.02146516e-05 , +1.33563694e-05 , -1.56615859e-05 ], [ -2.16638370e-01 , -5.62730486e-01 , -5.89983941e-01 , -2.15407057e-01 , +2.37733052e-01 , +3.66068969e-01 , +1.95048293e-01 , +3.75256494e-02 , +9.15661482e-02 , +2.71784500e-01 , +3.14674603e-01 , +7.13071808e-02 , -2.74416634e-01 , -3.73078532e-01 , -2.13349891e-01 , -4.82261437e-02 , -2.49319125e-01 , -7.28599608e-01 , -1.07780208e+00 , -1.06514748e+00 , -6.44272286e-01 , -1.76837465e-01 , -4.90834023e-04 , +1.40280625e-03 , +5.10120552e-02 , +1.46511968e-01 , +2.14025342e-01 , +2.18821220e-01 , +1.40952958e-01 , +4.57418351e-02 , +1.24001658e-04 , -1.87753657e-04 , +2.81978664e-02 , +6.75972310e-02 , +6.46467202e-02 , +3.09553532e-02 , +2.07469415e-04 , -7.06490932e-04 , +1.22050635e-04 , -2.58860315e-04 , -3.30589145e-03 , -8.32391033e-03 , -7.88014948e-03 , -4.46450270e-03 , -7.18407088e-05 , +1.10038839e-04 , -5.60639523e-05 , +7.53249029e-05 , -2.02490738e-04 , -4.12519737e-04 , -2.80203761e-05 , +9.26981260e-05 , -2.02414836e-05 , +4.69309281e-05 , -2.40793886e-05 , +4.09542803e-05 , +1.91221702e-05 , +3.54521568e-05 , +1.18943691e-05 , -2.20842884e-05 , +1.48622105e-05 , -1.93553187e-05 , +1.27582384e-05 , -1.50820404e-05 ], [ -1.17358804e-01 , -3.10118352e-01 , -3.45130767e-01 , -1.71061497e-01 , +6.58688847e-02 , +1.58454175e-01 , +9.32815939e-02 , +1.89047321e-02 , +6.45647473e-02 , +1.86331669e-01 , +2.35073680e-01 , +1.36189586e-01 , -4.24452280e-02 , -1.29104628e-01 , -8.65102742e-02 , -2.11488684e-02 , -9.54390147e-02 , -2.91672543e-01 , -4.59767964e-01 , -4.82144064e-01 , -3.08216741e-01 , -8.91120487e-02 , -3.28056188e-04 , +6.89033310e-04 , +1.37341176e-02 , +4.31149334e-02 , +7.07323674e-02 , +8.14414378e-02 , +5.71682855e-02 , +2.00308179e-02 , +7.18864249e-05 , -1.12618766e-04 , +1.30195063e-02 , +3.17285975e-02 , +3.09553532e-02 , +1.56207824e-02 , +1.33628631e-04 , -3.48981349e-04 , +7.32910488e-05 , -1.25462139e-04 , -1.26556799e-03 , -3.29596371e-03 , -3.20196737e-03 , -1.94244457e-03 , -3.77185026e-05 , +6.17244983e-05 , -3.12274123e-05 , +4.30090197e-05 , -9.77979573e-05 , -2.08579409e-04 , -1.55952399e-05 , +4.31143648e-05 , -1.21826092e-05 , +2.34761998e-05 , -1.36791757e-05 , +1.97889218e-05 , +8.06524096e-06 , +1.42084608e-05 , +6.16145585e-06 , -1.19094499e-05 , +7.74806700e-06 , -1.04787929e-05 , +6.89900544e-06 , -8.32073693e-06 ], [ -6.77575337e-04 , -1.84143143e-03 , -2.24934808e-03 , -1.58842691e-03 , -3.62660943e-04 , +4.38421028e-04 , +4.66944604e-04 , +1.52795123e-04 , +3.04697353e-04 , +7.38936230e-04 , +6.96656794e-04 , -6.97719003e-05 , -9.68149000e-04 , -1.23615787e-03 , -6.78738775e-04 , -1.23668355e-04 , -2.14497673e-04 , -8.36990631e-04 , -1.64529377e-03 , -2.14894148e-03 , -1.68247061e-03 , -7.33360667e-04 , -1.17291974e-04 , -2.53107624e-06 , +1.75011991e-04 , +4.87347324e-04 , +7.02895940e-04 , +6.79215124e-04 , +4.47969855e-04 , +1.17997504e-04 , -5.49476781e-08 , +1.18002440e-07 , +7.32276382e-05 , +1.86082824e-04 , +2.07469416e-04 , +1.33628631e-04 , +5.44060100e-05 , +1.52936308e-06 , +1.74491609e-05 , +4.70004375e-07 , -1.05944751e-05 , -2.43405076e-05 , -2.49116631e-05 , -1.18291438e-05 , +1.07054390e-08 , -6.90929055e-08 , +5.06574836e-08 , -8.88483074e-08 , -1.54943670e-06 , -2.12840754e-06 , -3.49805441e-06 , -1.98334725e-07 , -5.63136915e-06 , -1.24090727e-07 , -2.27199365e-06 , -6.40903333e-08 , +5.39559348e-08 , +1.24705131e-07 , +4.03252891e-09 , +7.62682488e-09 , -3.77593799e-09 , +1.52456861e-08 , -1.36899923e-08 , +2.28011833e-08 ], [ +1.32077265e-03 , +3.84450132e-03 , +5.12873097e-03 , +3.47750190e-03 , -3.46243400e-04 , -2.73248171e-03 , -2.14579453e-03 , -6.00125848e-04 , -6.13531409e-04 , -1.92155853e-03 , -3.04659267e-03 , -2.50011129e-03 , +2.35277063e-05 , +2.14567677e-03 , +1.60887340e-03 , +3.36213414e-04 , +2.04442703e-03 , +6.01830066e-03 , +9.19823674e-03 , +1.00585042e-02 , +7.07708657e-03 , +2.56171737e-03 , -3.63542276e-06 , -1.90489863e-04 , -2.28409244e-04 , -6.81811866e-04 , -1.13602154e-03 , -1.33629759e-03 , -1.06182374e-03 , -3.20710541e-04 , +7.30725430e-08 , -2.17727699e-07 , -2.86285584e-04 , -6.90470767e-04 , -7.06490932e-04 , -3.48981349e-04 , +1.52936308e-06 , +1.07702053e-04 , +8.71439545e-07 , +2.70196523e-05 , +2.25707859e-05 , +5.40583108e-05 , +5.89865955e-05 , +3.21854211e-05 , -6.25407244e-08 , +1.60830073e-07 , -1.09219495e-07 , +1.80323736e-07 , +2.10620308e-06 , -1.48664831e-06 , -1.52490322e-07 , -1.09950088e-05 , -1.58932007e-07 , -8.46877791e-06 , -1.56695740e-07 , -3.21771641e-06 , -1.23917824e-07 , -3.47705891e-07 , +5.45447564e-09 , -3.03353052e-08 , +2.08784325e-08 , -4.01478702e-08 , +3.23142889e-08 , -4.70655305e-08 ], [ -2.51835863e-04 , -7.23669471e-04 , -9.43933588e-04 , -6.57672845e-04 , -2.69261303e-05 , +3.69728163e-04 , +3.03633026e-04 , +8.38734411e-05 , +1.05151519e-04 , +2.93355305e-04 , +3.90216451e-04 , +1.74239040e-04 , -2.80476933e-04 , -5.37324962e-04 , -3.13509246e-04 , -5.52757781e-05 , -2.54681477e-04 , -7.85984173e-04 , -1.26700244e-03 , -1.45035502e-03 , -1.04388150e-03 , -4.02301065e-04 , -4.06165612e-05 , -1.41153381e-06 , +6.78169631e-05 , +1.92619386e-04 , +2.85735521e-04 , +2.97150259e-04 , +2.06971057e-04 , +5.26252707e-05 , +5.76974486e-08 , -2.80655886e-08 , +4.58530586e-05 , +1.13712594e-04 , +1.22050635e-04 , +7.32910488e-05 , +1.74491609e-05 , +8.71439546e-07 , +2.37983361e-05 , +3.41862028e-07 , -4.70471087e-06 , -1.07216943e-05 , -1.15032991e-05 , -5.26032061e-06 , -1.18126235e-08 , +5.52943870e-09 , +2.54324610e-09 , -1.93615165e-08 , -1.05555805e-06 , -1.16449478e-06 , -2.78814086e-06 , -1.10009545e-07 , -2.32547548e-06 , -8.57000152e-08 , -5.47053709e-06 , -6.13771757e-08 , +2.40476217e-08 , +5.64589224e-08 , -3.79689035e-10 , +2.56728248e-09 , -1.27853965e-09 , +3.66057841e-09 , -3.60935948e-09 , +7.58988369e-09 ], [ +3.96250935e-04 , +1.19393383e-03 , +1.62428179e-03 , +1.00975957e-03 , -3.61194366e-04 , -1.11920657e-03 , -7.85859258e-04 , -1.99694876e-04 , -2.11409282e-04 , -7.19998353e-04 , -1.25546626e-03 , -1.18157254e-03 , -2.69656224e-04 , +5.55056946e-04 , +4.45545000e-04 , +8.72816070e-05 , +8.60109745e-04 , +2.46703885e-03 , +3.64238943e-03 , +3.83341216e-03 , +2.59227648e-03 , +8.86632630e-04 , -1.12613356e-06 , -4.41054452e-05 , -3.57322209e-05 , -1.23171969e-04 , -2.50120862e-04 , -3.46092217e-04 , -2.94059448e-04 , -8.32226465e-05 , -1.39623279e-08 , -3.51277600e-08 , -1.07221510e-04 , -2.56938042e-04 , -2.58860315e-04 , -1.25462139e-04 , +4.70004376e-07 , +2.70196523e-05 , +3.41862028e-07 , +2.58431126e-05 , +5.93894002e-06 , +1.40245244e-05 , +1.63215346e-05 , +8.36404527e-06 , -2.06846804e-08 , +4.01609448e-08 , -2.76609304e-08 , +5.03220537e-08 , +7.74342836e-07 , -1.36390918e-06 , -4.57356519e-08 , -5.71580034e-06 , -5.49405841e-08 , -3.53039967e-06 , -7.09043689e-08 , -5.80686451e-06 , -3.31836277e-08 , -9.34668200e-08 , +5.55902426e-09 , -1.23561222e-08 , +8.72314706e-09 , -1.29510501e-08 , +9.95776036e-09 , -1.44173771e-08 ], [ +1.33956923e-02 , +3.53809131e-02 , +3.33558699e-02 , +5.38674909e-03 , -2.15182353e-02 , -2.36814915e-02 , -9.98695835e-03 , -1.51926328e-03 , +6.69606087e-02 , +1.91279273e-01 , +3.01290750e-01 , +3.89970453e-01 , +3.97093770e-01 , +2.85606165e-01 , +1.24869469e-01 , +2.36500679e-02 , +1.58700003e-02 , +4.62683574e-02 , +6.60718230e-02 , +6.17682333e-02 , +3.29878100e-02 , +7.17166739e-03 , +2.28753972e-05 , -4.07528187e-05 , -5.60667093e-02 , -1.45997441e-01 , -1.80410779e-01 , -1.50513165e-01 , -8.24329382e-02 , -2.25165989e-02 , -1.86865841e-05 , +2.72183216e-05 , -1.53554158e-03 , -3.54588186e-03 , -3.30589145e-03 , -1.26556799e-03 , -1.05944751e-05 , +2.25707860e-05 , -4.70471089e-06 , +5.93894006e-06 , +2.19331813e-03 , +5.13537670e-03 , +4.58592800e-03 , +2.23774938e-03 , +9.00025643e-06 , -1.36785981e-05 , +7.48114004e-06 , -9.69165660e-06 , +1.01422888e-05 , +1.78676713e-05 , +8.66688855e-07 , -2.77415469e-06 , +1.11083978e-06 , -1.50100393e-06 , +6.06641099e-07 , -5.08415220e-07 , -1.01528223e-05 , -2.21723748e-05 , -1.30745796e-06 , +2.52500810e-06 , -1.67073899e-06 , +2.12478461e-06 , -1.47531268e-06 , +1.69783919e-06 ], [ +3.87302168e-02 , +1.02174628e-01 , +1.00645901e-01 , +2.85395154e-02 , -4.50862491e-02 , -5.68516880e-02 , -2.51514750e-02 , -3.94815365e-03 , +1.40696276e-01 , +4.03391305e-01 , +6.45674346e-01 , +8.60008166e-01 , +9.00935744e-01 , +6.62710415e-01 , +2.94783588e-01 , +5.65674106e-02 , +3.49651641e-02 , +1.05003114e-01 , +1.55771547e-01 , +1.50688257e-01 , +8.30710062e-02 , +1.86510559e-02 , +5.40693740e-05 , -9.96923341e-05 , -1.28497482e-01 , -3.35647062e-01 , -4.17387445e-01 , -3.51433504e-01 , -1.94603239e-01 , -5.38602969e-02 , -4.39403656e-05 , +6.02108866e-05 , -3.77583980e-03 , -8.79688591e-03 , -8.32391035e-03 , -3.29596371e-03 , -2.43405076e-05 , +5.40583111e-05 , -1.07216943e-05 , +1.40245245e-05 , +5.13537670e-03 , +1.20823972e-02 , +1.08271195e-02 , +5.35385860e-03 , +2.18452665e-05 , -3.10007720e-05 , +1.74997308e-05 , -2.12450646e-05 , +2.55096850e-05 , +4.68176169e-05 , +1.94026871e-06 , -6.48045038e-06 , +2.42222631e-06 , -3.40012419e-06 , +1.35645476e-06 , -1.19281840e-06 , -2.34571503e-05 , -5.37775756e-05 , -3.32338669e-06 , +5.95324480e-06 , -4.09986001e-06 , +4.88476330e-06 , -3.44935894e-06 , +3.69110775e-06 ], [ +4.27005394e-02 , +1.11818628e-01 , +1.12908315e-01 , +4.11033431e-02 , -3.50723338e-02 , -5.16074563e-02 , -2.38031652e-02 , -3.84851853e-03 , +1.05964317e-01 , +3.06444642e-01 , +5.06049294e-01 , +7.07567767e-01 , +7.73352363e-01 , +5.86050234e-01 , +2.65670205e-01 , +5.15568750e-02 , +2.85412382e-02 , +8.92117269e-02 , +1.38563993e-01 , +1.38856068e-01 , +7.86214529e-02 , +1.81640335e-02 , +5.49030020e-05 , -1.09252353e-04 , -1.11597062e-01 , -2.92749264e-01 , -3.67168622e-01 , -3.12750788e-01 , -1.75391241e-01 , -4.90793707e-02 , -5.07064198e-05 , +6.58977204e-05 , -3.49817214e-03 , -8.22371177e-03 , -7.88014950e-03 , -3.20196737e-03 , -2.49116631e-05 , +5.89865957e-05 , -1.15032991e-05 , +1.63215347e-05 , +4.58592800e-03 , +1.08271195e-02 , +9.76480860e-03 , +4.87457616e-03 , +2.28463772e-05 , -3.26335078e-05 , +1.97044193e-05 , -2.31786234e-05 , +2.42443142e-05 , +4.48531634e-05 , +2.18827378e-06 , -7.25850970e-06 , +2.57532349e-06 , -3.83166802e-06 , +1.58339070e-06 , -1.63002748e-06 , -2.12120837e-05 , -4.80151805e-05 , -4.47434163e-06 , +6.00144005e-06 , -4.10563669e-06 , +5.00544985e-06 , -3.82774906e-06 , +4.04170529e-06 ], [ +2.68638059e-02 , +7.16897926e-02 , +7.75632007e-02 , +3.86636488e-02 , -9.06358511e-03 , -2.57667258e-02 , -1.34898398e-02 , -2.32871615e-03 , +3.53205177e-02 , +1.03541509e-01 , +1.81749205e-01 , +2.82067885e-01 , +3.39186852e-01 , +2.76512615e-01 , +1.32613143e-01 , +2.68472703e-02 , +1.08545710e-02 , +3.78034704e-02 , +6.59115958e-02 , +7.25666545e-02 , +4.45490536e-02 , +1.10010480e-02 , +2.94033428e-05 , -6.35669983e-05 , -5.10208078e-02 , -1.34983012e-01 , -1.72349175e-01 , -1.50837667e-01 , -8.75536892e-02 , -2.55654354e-02 , -3.01818438e-05 , +2.40612214e-05 , -1.87432733e-03 , -4.48694248e-03 , -4.46450270e-03 , -1.94244457e-03 , -1.18291438e-05 , +3.21854212e-05 , -5.26032062e-06 , +8.36404529e-06 , +2.23774938e-03 , +5.35385860e-03 , +4.87457616e-03 , +2.54819581e-03 , +1.36581046e-05 , -1.33971291e-05 , +1.12830699e-05 , -8.07687560e-06 , +1.37133410e-05 , +2.74522800e-05 , +9.60517944e-07 , -3.64003418e-06 , +9.74213391e-07 , -1.70992266e-06 , +6.62893016e-07 , -7.94551896e-07 , -1.07106899e-05 , -2.52220937e-05 , -2.10091240e-06 , +1.15262849e-06 , -2.44272584e-06 , +2.18283709e-06 , -2.15575165e-06 , +1.35376435e-06 ], [ +8.89902191e-05 , +2.62494641e-04 , +3.21010497e-04 , +9.57096228e-05 , -2.59958960e-04 , -3.82509997e-04 , -2.17819014e-04 , -4.37745731e-05 , -3.52702158e-06 , -4.53700181e-05 , -3.16347296e-05 , +2.31769580e-04 , +6.69024117e-04 , +8.07577100e-04 , +5.08491360e-04 , +1.40798929e-04 , +3.10016370e-04 , +8.55226171e-04 , +1.19626000e-03 , +1.15367984e-03 , +7.18689619e-04 , +2.08902714e-04 , +2.49843946e-08 , +1.39611335e-07 , -1.39350465e-04 , -3.85579206e-04 , -5.22271211e-04 , -5.21756651e-04 , -3.53254578e-04 , -1.34637006e-04 , -1.32935771e-05 , -3.56488111e-07 , -3.13412425e-05 , -7.60491054e-05 , -7.18407092e-05 , -3.77185028e-05 , +1.07054392e-08 , -6.25407189e-08 , -1.18126243e-08 , -2.06846789e-08 , +9.00025640e-06 , +2.18452664e-05 , +2.28463772e-05 , +1.36581046e-05 , +1.11143656e-05 , +1.97588894e-07 , +4.47875195e-06 , +1.43546403e-07 , +2.15964800e-07 , +5.80802465e-07 , -5.42039709e-09 , +1.18477971e-08 , -1.10491023e-10 , +7.86214544e-10 , +2.39384608e-09 , +3.48270539e-09 , -1.89053342e-07 , -1.64176246e-07 , -5.42527744e-07 , -3.87744115e-08 , -2.49184856e-06 , -3.42927754e-08 , -7.87495431e-07 , -2.94688914e-08 ], [ -7.44173547e-05 , -2.86897993e-04 , -4.47617437e-04 , -2.43325477e-04 , +2.47794971e-04 , +5.17098493e-04 , +3.33790789e-04 , +7.15227056e-05 , -1.19507600e-04 , -2.69889071e-04 , -3.15328144e-04 , -5.33793630e-04 , -1.06832997e-03 , -1.32187708e-03 , -8.93882920e-04 , -2.63852214e-04 , -4.24269089e-04 , -1.17062878e-03 , -1.65741613e-03 , -1.65868124e-03 , -1.10116235e-03 , -3.41560152e-04 , +7.41658900e-08 , -3.16671595e-07 , +2.40657330e-04 , +6.56763888e-04 , +8.77200639e-04 , +8.71536553e-04 , +5.89633619e-04 , +2.23059612e-04 , -4.70388582e-07 , -2.16371197e-05 , +4.65085224e-05 , +1.14611236e-04 , +1.10038839e-04 , +6.17244983e-05 , -6.90929056e-08 , +1.60830073e-07 , +5.52943871e-09 , +4.01609444e-08 , -1.36785981e-05 , -3.10007720e-05 , -3.26335078e-05 , -1.33971291e-05 , +1.97588895e-07 , +1.66331968e-05 , +2.20875624e-07 , +7.12761551e-06 , -3.29663054e-07 , -9.53824281e-07 , +1.28959138e-08 , -2.62805425e-08 , +4.57472177e-09 , -4.24086890e-09 , -4.40163363e-09 , -3.28666556e-09 , +6.25772695e-08 , -7.47439346e-07 , -2.75413553e-08 , -1.48140357e-06 , -4.06087420e-08 , -3.34008174e-06 , -5.13884676e-08 , -1.21130717e-06 ], [ +3.99261016e-05 , +1.51714938e-04 , +2.26457043e-04 , +1.11219530e-04 , -1.39142537e-04 , -2.68592722e-04 , -1.70099933e-04 , -3.61306006e-05 , +6.41980475e-05 , +1.48738753e-04 , +1.73354946e-04 , +2.69570203e-04 , +5.09598887e-04 , +6.14527577e-04 , +4.04714748e-04 , +1.15985617e-04 , +2.21091995e-04 , +6.09805566e-04 , +8.59617770e-04 , +8.53510160e-04 , +5.61108895e-04 , +1.72632756e-04 , -6.35909243e-08 , +2.04712129e-07 , -1.13730318e-04 , -3.09896623e-04 , -4.12357233e-04 , -4.08553735e-04 , -2.75367681e-04 , -1.11012063e-04 , -1.62046751e-05 , -4.20527898e-07 , -2.38273751e-05 , -5.85902588e-05 , -5.60639523e-05 , -3.12274123e-05 , +5.06574831e-08 , -1.09219494e-07 , +2.54324597e-09 , -2.76609301e-08 , +7.48114002e-06 , +1.74997307e-05 , +1.97044193e-05 , +1.12830699e-05 , +4.47875195e-06 , +2.20875623e-07 , +1.17952621e-05 , +1.79740047e-07 , +1.67646577e-07 , +4.84654772e-07 , -8.48601946e-09 , +1.78518094e-08 , -4.69732057e-09 , +4.40391715e-09 , +1.93971820e-09 , +1.76816987e-09 , -2.46316821e-07 , -1.34380638e-07 , -8.50507007e-07 , -3.45004306e-08 , -7.94562212e-07 , -3.88149262e-08 , -3.10196062e-06 , -3.85222831e-08 ], [ -4.28746390e-06 , -1.00094344e-04 , -2.41331300e-04 , -1.73906204e-04 , +1.30483975e-04 , +3.36979790e-04 , +2.28610888e-04 , +4.97187484e-05 , -1.43862305e-04 , -3.49671973e-04 , -3.84477799e-04 , -4.40507550e-04 , -7.37809356e-04 , -9.18102799e-04 , -6.34999593e-04 , -1.89201177e-04 , -2.82681967e-04 , -7.73371586e-04 , -1.08928361e-03 , -1.10608413e-03 , -7.54068948e-04 , -2.37645459e-04 , +1.48478834e-07 , -3.23815730e-07 , +1.72688470e-04 , +4.67425730e-04 , +6.18215581e-04 , +6.11696865e-04 , +4.18884270e-04 , +1.67164285e-04 , -3.52439032e-07 , -1.81558926e-05 , +3.14495864e-05 , +7.77212500e-05 , +7.53249029e-05 , +4.30090197e-05 , -8.88483076e-08 , +1.80323737e-07 , -1.93615165e-08 , +5.03220537e-08 , -9.69165661e-06 , -2.12450646e-05 , -2.31786234e-05 , -8.07687560e-06 , +1.43546404e-07 , +7.12761551e-06 , +1.79740047e-07 , +1.31760341e-05 , -2.25067081e-07 , -6.68343700e-07 , +1.13549279e-08 , -2.57782317e-08 , +6.90223664e-09 , -9.18474880e-09 , +7.23812558e-10 , -5.59919050e-09 , +4.41680628e-08 , -8.68229130e-07 , -2.04285726e-08 , -1.71798778e-06 , -3.08151599e-08 , -1.24564543e-06 , -4.36963815e-08 , -3.43582728e-06 ], [ +6.75748632e-04 , +1.75643965e-03 , +1.85038644e-03 , +6.94735979e-04 , -7.18171793e-04 , -1.13047468e-03 , -6.08005395e-04 , -1.18293305e-04 , -2.90647143e-04 , -8.61971739e-04 , -1.00664775e-03 , -2.59229181e-04 , +8.17788380e-04 , +1.14059317e-03 , +6.56476324e-04 , +1.48041102e-04 , +7.68664523e-04 , +2.24942036e-03 , +3.33563885e-03 , +3.30897023e-03 , +2.01058942e-03 , +5.57815810e-04 , +3.53863927e-06 , -4.18567258e-06 , -1.54341381e-04 , -4.44288986e-04 , -6.52348448e-04 , -6.69781538e-04 , -4.33701127e-04 , -1.40432775e-04 , -3.70467906e-07 , +5.62053615e-07 , -8.83832050e-05 , -2.11135313e-04 , -2.02490738e-04 , -9.77979573e-05 , -1.54943669e-06 , +2.10620308e-06 , -1.05555804e-06 , +7.74342836e-07 , +1.01422887e-05 , +2.55096849e-05 , +2.42443141e-05 , +1.37133410e-05 , +2.15964799e-07 , -3.29663054e-07 , +1.67646577e-07 , -2.25067081e-07 , +8.28073897e-07 , +1.31395837e-06 , +1.78283657e-07 , -2.75691643e-07 , +1.67805233e-07 , -1.40174270e-07 , +2.13234679e-07 , -1.23019113e-07 , -5.87403195e-08 , -1.09485174e-07 , -3.60213967e-08 , +6.64534243e-08 , -4.47470790e-08 , +5.80240075e-08 , -3.81627948e-08 , +4.49909000e-08 ], [ +1.66816940e-03 , +4.38501160e-03 , +4.81901217e-03 , +2.32756351e-03 , -9.46516812e-04 , -2.16750570e-03 , -1.24177211e-03 , -2.41147735e-04 , -9.11748749e-04 , -2.61228009e-03 , -3.22833337e-03 , -1.76341575e-03 , +7.26501199e-04 , +1.84389411e-03 , +1.21083239e-03 , +2.99858329e-04 , +1.27384559e-03 , +3.91588376e-03 , +6.20286491e-03 , +6.48262245e-03 , +4.10399803e-03 , +1.15228292e-03 , +5.20953219e-06 , +1.21992362e-06 , -2.02707609e-04 , -6.32107906e-04 , -1.02094074e-03 , -1.16017364e-03 , -8.00247190e-04 , -2.83845294e-04 , -1.10719001e-06 , +1.73453456e-06 , -1.74134011e-04 , -4.26077508e-04 , -4.12519737e-04 , -2.08579409e-04 , -2.12840753e-06 , -1.48664832e-06 , -1.16449478e-06 , -1.36390918e-06 , +1.78676713e-05 , +4.68176168e-05 , +4.48531633e-05 , +2.74522799e-05 , +5.80802462e-07 , -9.53824281e-07 , +4.84654772e-07 , -6.68343700e-07 , +1.31395837e-06 , +3.79886814e-06 , +2.49689303e-07 , +2.77993234e-07 , +1.95564723e-07 , +2.94726707e-07 , +2.16554000e-07 , +3.13977485e-07 , -1.14526203e-07 , -1.93506925e-07 , -9.40786353e-08 , +1.83548774e-07 , -1.19583834e-07 , +1.62608774e-07 , -1.07504319e-07 , +1.30099000e-07 ], [ +8.45332954e-05 , +2.24783065e-04 , +2.68751415e-04 , +1.72534545e-04 , +5.74404149e-06 , -8.54703012e-05 , -6.65943613e-05 , -1.78582518e-05 , -5.40864394e-05 , -1.50283047e-04 , -1.85085729e-04 , -1.06360909e-04 , +2.68606757e-05 , +9.72361732e-05 , +5.96368581e-05 , +9.98230612e-06 , +4.93996719e-05 , +1.62552118e-04 , +2.77925528e-04 , +3.22988798e-04 , +2.28514284e-04 , +8.56290963e-05 , +7.82865789e-06 , +2.71015918e-07 , -8.84152126e-06 , -2.73519812e-05 , -4.81816787e-05 , -5.37667751e-05 , -3.93489899e-05 , -9.54428266e-06 , +1.77786372e-08 , -2.10426264e-08 , -9.84069348e-06 , -2.48202750e-05 , -2.80203761e-05 , -1.55952399e-05 , -3.49805441e-06 , -1.52490323e-07 , -2.78814086e-06 , -4.57356521e-08 , +8.66688848e-07 , +1.94026870e-06 , +2.18827377e-06 , +9.60517939e-07 , -5.42039727e-09 , +1.28959137e-08 , -8.48601952e-09 , +1.13549279e-08 , +1.78283657e-07 , +2.49689303e-07 , +1.22732507e-06 , +2.23900067e-08 , +4.09211518e-07 , +1.06767255e-08 , +5.80339376e-07 , +5.43889660e-09 , -4.84036749e-09 , -1.00874401e-08 , -3.82446646e-10 , -1.29025224e-09 , +9.62402969e-10 , -2.34475172e-09 , +1.96028423e-09 , -2.66859099e-09 ], [ -1.96576974e-04 , -5.58567198e-04 , -7.17942226e-04 , -4.54457177e-04 , +8.23988489e-05 , +3.83708324e-04 , +2.81559820e-04 , +7.43243106e-05 , +1.05168713e-04 , +3.24108042e-04 , +4.85316787e-04 , +3.75452576e-04 , +5.61500997e-07 , -2.79821980e-04 , -1.97973667e-04 , -3.79678967e-05 , -2.77315521e-04 , -8.18544499e-04 , -1.25005940e-03 , -1.35039207e-03 , -9.28619389e-04 , -3.25310428e-04 , +4.50583888e-07 , +1.88840385e-05 , +2.56588549e-05 , +7.92361146e-05 , +1.38985148e-04 , +1.66671494e-04 , +1.30647867e-04 , +3.62360999e-05 , -2.12041581e-08 , +3.52707074e-08 , +3.79333705e-05 , +9.18151084e-05 , +9.26981260e-05 , +4.31143648e-05 , -1.98334725e-07 , -1.09950088e-05 , -1.10009545e-07 , -5.71580034e-06 , -2.77415468e-06 , -6.48045036e-06 , -7.25850969e-06 , -3.64003418e-06 , +1.18477976e-08 , -2.62805425e-08 , +1.78518095e-08 , -2.57782317e-08 , -2.75691643e-07 , +2.77993234e-07 , +2.23900066e-08 , +2.77357551e-06 , +2.19070010e-08 , +1.08198728e-06 , +1.98896719e-08 , +1.10315591e-06 , +1.53923267e-08 , +3.92487886e-08 , -5.00165545e-10 , +4.22831563e-09 , -3.22129967e-09 , +6.05527520e-09 , -4.89007227e-09 , +6.56603904e-09 ], [ +7.61037965e-05 , +2.03670441e-04 , +2.38973420e-04 , +1.48573809e-04 , +5.20180577e-06 , -6.91558747e-05 , -5.31061367e-05 , -1.39029361e-05 , -3.49416991e-05 , -9.09262800e-05 , -9.24057103e-05 , -2.90607787e-07 , +1.14307375e-04 , +1.43484908e-04 , +7.01242201e-05 , +1.02222637e-05 , +3.61506205e-05 , +1.23930016e-04 , +2.17892055e-04 , +2.57042357e-04 , +1.81676676e-04 , +6.67557419e-05 , +3.94662688e-06 , +2.51176259e-07 , -1.86690509e-05 , -5.23964982e-05 , -7.59528758e-05 , -7.34845301e-05 , -4.62845355e-05 , -9.74840162e-06 , +2.41328549e-09 , -3.83544848e-09 , -7.72996726e-06 , -1.95801497e-05 , -2.02414836e-05 , -1.21826092e-05 , -5.63136915e-06 , -1.58932007e-07 , -2.32547548e-06 , -5.49405841e-08 , +1.11083978e-06 , +2.42222630e-06 , +2.57532349e-06 , +9.74213388e-07 , -1.10491136e-10 , +4.57472176e-09 , -4.69732065e-09 , +6.90223662e-09 , +1.67805233e-07 , +1.95564723e-07 , +4.09211518e-07 , +2.19070010e-08 , +1.75933767e-06 , +1.52006128e-08 , +5.31186074e-07 , +8.64990893e-09 , -5.67955417e-09 , -9.85488773e-09 , -7.32403561e-10 , -2.68025416e-10 , +3.51825298e-10 , -1.45146029e-09 , +1.43849972e-09 , -2.05616894e-09 ], [ -9.43608486e-05 , -2.74524727e-04 , -3.56454345e-04 , -2.21570152e-04 , +5.16178168e-05 , +2.00204398e-04 , +1.42569467e-04 , +3.61955020e-05 , +4.64931611e-05 , +1.44464628e-04 , +2.20975558e-04 , +1.60742006e-04 , -3.33589772e-05 , -1.66500583e-04 , -1.04499532e-04 , -1.79057051e-05 , -1.44745550e-04 , -4.25165537e-04 , -6.44493632e-04 , -6.92016303e-04 , -4.70179015e-04 , -1.60728992e-04 , +2.79080358e-07 , +6.05998145e-06 , +1.65914265e-05 , +4.96411009e-05 , +8.12089317e-05 , +9.30942474e-05 , +6.89773921e-05 , +1.70616106e-05 , +9.19787223e-09 , -9.81415498e-10 , +1.93059463e-05 , +4.67740141e-05 , +4.69309281e-05 , +2.34761999e-05 , -1.24090727e-07 , -8.46877791e-06 , -8.57000151e-08 , -3.53039967e-06 , -1.50100392e-06 , -3.40012417e-06 , -3.83166800e-06 , -1.70992265e-06 , +7.86214911e-10 , -4.24086896e-09 , +4.40391722e-09 , -9.18474877e-09 , -1.40174270e-07 , +2.94726707e-07 , +1.06767254e-08 , +1.08198728e-06 , +1.52006128e-08 , +2.33982871e-06 , +1.78217752e-08 , +7.75372489e-07 , +7.94763812e-09 , +1.86785955e-08 , -5.72901033e-10 , +1.75784888e-09 , -1.26768762e-09 , +2.25067476e-09 , -1.94269186e-09 , +3.03210691e-09 ], [ +3.16431621e-05 , +1.00265251e-04 , +1.40452020e-04 , +8.92714599e-05 , -2.85216959e-05 , -9.33756339e-05 , -6.47466824e-05 , -1.56800116e-05 , -1.78809296e-05 , -5.86154526e-05 , -1.00341381e-04 , -8.44068118e-05 , +1.82422446e-06 , +6.80194994e-05 , +4.32259648e-05 , +6.97543730e-06 , +7.11678828e-05 , +2.04983160e-04 , +3.03740170e-04 , +3.22007848e-04 , +2.17537114e-04 , +7.51496669e-05 , +3.20705384e-06 , +2.44170352e-07 , -5.84519878e-06 , -1.81360988e-05 , -3.07911344e-05 , -3.75853915e-05 , -2.85407221e-05 , -6.62773847e-06 , -1.77057782e-08 , +1.28395118e-08 , -9.56212025e-06 , -2.34247990e-05 , -2.40793886e-05 , -1.36791757e-05 , -2.27199365e-06 , -1.56695740e-07 , -5.47053709e-06 , -7.09043690e-08 , +6.06641095e-07 , +1.35645475e-06 , +1.58339070e-06 , +6.62893014e-07 , +2.39384594e-09 , -4.40163364e-09 , +1.93971816e-09 , +7.23812549e-10 , +2.13234679e-07 , +2.16554000e-07 , +5.80339377e-07 , +1.98896719e-08 , +5.31186074e-07 , +1.78217752e-08 , +2.13948748e-06 , +1.44666361e-08 , -3.04220981e-09 , -7.71524455e-09 , +8.83276352e-10 , -8.12012682e-10 , +4.34840145e-10 , -3.03790881e-10 , +2.67317774e-10 , -9.01771216e-10 ], [ -4.45517633e-05 , -1.47525320e-04 , -2.13945345e-04 , -1.22428828e-04 , +8.67492297e-05 , +1.91551440e-04 , +1.24280760e-04 , +2.90415623e-05 , +2.95185435e-05 , +1.11307866e-04 , +2.18862708e-04 , +2.37405479e-04 , +1.03373340e-04 , -3.87250758e-05 , -4.46472025e-05 , -8.24734874e-06 , -1.51181286e-04 , -4.25056593e-04 , -6.10625321e-04 , -6.24981295e-04 , -4.10013431e-04 , -1.33122261e-04 , +1.53379090e-07 , +3.02285712e-06 , -3.61270499e-06 , -5.15247005e-06 , +7.23658762e-06 , +2.69455787e-05 , +2.94685716e-05 , +7.85548066e-06 , +1.01900610e-08 , -8.28072726e-10 , +1.72571565e-05 , +4.12484662e-05 , +4.09542804e-05 , +1.97889218e-05 , -6.40903336e-08 , -3.21771641e-06 , -6.13771758e-08 , -5.80686451e-06 , -5.08415214e-07 , -1.19281839e-06 , -1.63002747e-06 , -7.94551892e-07 , +3.48270561e-09 , -3.28666561e-09 , +1.76816990e-09 , -5.59919049e-09 , -1.23019113e-07 , +3.13977485e-07 , +5.43889657e-09 , +1.10315591e-06 , +8.64990892e-09 , +7.75372489e-07 , +1.44666361e-08 , +2.30188338e-06 , +2.85795476e-09 , +1.01450933e-08 , -2.11237387e-09 , +2.70716365e-09 , -1.74231373e-09 , +1.74807362e-09 , -1.16452732e-09 , +1.88792713e-09 ], [ -9.17705335e-05 , -2.41998964e-04 , -2.48072180e-04 , -9.15028133e-05 , +8.12470743e-05 , +1.21629453e-04 , +5.77842166e-05 , +9.64489118e-06 , -2.23824279e-04 , -6.44720522e-04 , -1.06226522e-03 , -1.49022835e-03 , -1.64168366e-03 , -1.25488176e-03 , -5.74559892e-04 , -1.13128644e-04 , -7.04579982e-05 , -2.16306941e-04 , -3.31812558e-04 , -3.31926745e-04 , -1.90841882e-04 , -4.55913624e-05 , -1.19565301e-07 , +2.29372616e-07 , +2.38746706e-04 , +6.26582335e-04 , +7.87058011e-04 , +6.73236043e-04 , +3.79553800e-04 , +1.07709515e-04 , +4.39468050e-07 , -1.27407012e-07 , +8.45130749e-06 , +1.99454789e-05 , +1.91221703e-05 , +8.06524098e-06 , +5.39559347e-08 , -1.23917824e-07 , +2.40476218e-08 , -3.31836278e-08 , -1.01528223e-05 , -2.34571503e-05 , -2.12120837e-05 , -1.07106899e-05 , -1.89053342e-07 , +6.25772695e-08 , -2.46316821e-07 , +4.41680629e-08 , -5.87403196e-08 , -1.14526203e-07 , -4.84036752e-09 , +1.53923268e-08 , -5.67955419e-09 , +7.94763815e-09 , -3.04220983e-09 , +2.85795478e-09 , +1.49818911e-07 , +1.07315592e-07 , +2.43096987e-08 , -1.04835117e-08 , +3.70098722e-08 , -9.38097077e-09 , +5.91066723e-08 , -7.52969843e-09 ], [ -2.75099179e-04 , -7.24967137e-04 , -7.67791110e-04 , -3.79520424e-04 , +6.80502615e-05 , +2.15064263e-04 , +1.07006895e-04 , +1.72632626e-05 , -3.58437845e-04 , -1.06199882e-03 , -1.88370223e-03 , -2.91783739e-03 , -3.46165373e-03 , -2.77577780e-03 , -1.30536890e-03 , -2.56436193e-04 , -6.94562658e-05 , -2.74310948e-04 , -5.18447446e-04 , -5.87907727e-04 , -3.53471383e-04 , -8.12195922e-05 , -3.05685857e-07 , +6.85623305e-07 , +5.12701768e-04 , +1.35467889e-03 , +1.72523469e-03 , +1.49902787e-03 , +8.61879037e-04 , +2.45745394e-04 , +3.45871283e-07 , +1.40440073e-06 , +1.48393318e-05 , +3.52870578e-05 , +3.54521568e-05 , +1.42084608e-05 , +1.24705132e-07 , -3.47705892e-07 , +5.64589225e-08 , -9.34668202e-08 , -2.21723748e-05 , -5.37775756e-05 , -4.80151805e-05 , -2.52220937e-05 , -1.64176246e-07 , -7.47439346e-07 , -1.34380638e-07 , -8.68229130e-07 , -1.09485174e-07 , -1.93506925e-07 , -1.00874401e-08 , +3.92487886e-08 , -9.85488776e-09 , +1.86785956e-08 , -7.71524458e-09 , +1.01450934e-08 , +1.07315592e-07 , +6.26364215e-07 , +2.76985553e-08 , +1.25031812e-07 , +3.05519869e-08 , +1.44763809e-07 , +2.66707985e-08 , +2.15408864e-07 ], [ -1.51884840e-05 , -4.49685998e-05 , -5.90737882e-05 , -2.47685285e-05 , +3.76643889e-05 , +6.24680716e-05 , +3.60446395e-05 , +7.16729875e-06 , -1.36616074e-06 , +5.46427391e-06 , +9.27544352e-06 , -2.52032582e-05 , -9.40183914e-05 , -1.20393457e-04 , -7.80257295e-05 , -2.15720741e-05 , -4.87365768e-05 , -1.35201659e-04 , -1.91711433e-04 , -1.88515033e-04 , -1.18957155e-04 , -3.41714846e-05 , -1.26922119e-08 , -1.18627080e-08 , +2.05357668e-05 , +5.70353198e-05 , +7.82414106e-05 , +7.85510452e-05 , +5.24321386e-05 , +2.06157944e-05 , +1.34657038e-06 , +4.92708623e-08 , +5.13365990e-06 , +1.24291020e-05 , +1.18943691e-05 , +6.16145585e-06 , +4.03252894e-09 , +5.45447561e-09 , -3.79689042e-10 , +5.55902425e-09 , -1.30745796e-06 , -3.32338668e-06 , -4.47434162e-06 , -2.10091240e-06 , -5.42527744e-07 , -2.75413553e-08 , -8.50507007e-07 , -2.04285726e-08 , -3.60213968e-08 , -9.40786354e-08 , -3.82446647e-10 , -5.00165541e-10 , -7.32403572e-10 , -5.72901030e-10 , +8.83276350e-10 , -2.11237387e-09 , +2.43096987e-08 , +2.76985553e-08 , +5.62760007e-07 , +8.44739599e-09 , +1.07905222e-07 , +5.17215342e-09 , +2.13823888e-07 , +4.32828039e-09 ], [ +2.25081009e-05 , +7.30327853e-05 , +1.03390024e-04 , +5.14415520e-05 , -5.72730088e-05 , -1.09361373e-04 , -6.69690940e-05 , -1.38098126e-05 , +1.48464038e-05 , +2.66530661e-05 , +3.02061922e-05 , +8.61237387e-05 , +2.04384183e-04 , +2.51975822e-04 , +1.64720522e-04 , +4.64143704e-05 , +8.65282814e-05 , +2.39988586e-04 , +3.41348789e-04 , +3.40225401e-04 , +2.20963040e-04 , +6.59235503e-05 , -6.93182306e-09 , +5.79563470e-08 , -4.43061417e-05 , -1.21568375e-04 , -1.63377462e-04 , -1.61807112e-04 , -1.08655060e-04 , -4.16021614e-05 , +6.65514134e-08 , +2.87985084e-06 , -9.40782090e-06 , -2.29822248e-05 , -2.20842884e-05 , -1.19094499e-05 , +7.62682497e-09 , -3.03353055e-08 , +2.56728251e-09 , -1.23561222e-08 , +2.52500810e-06 , +5.95324480e-06 , +6.00144005e-06 , +1.15262849e-06 , -3.87744116e-08 , -1.48140357e-06 , -3.45004306e-08 , -1.71798778e-06 , +6.64534243e-08 , +1.83548774e-07 , -1.29025226e-09 , +4.22831564e-09 , -2.68025420e-10 , +1.75784889e-09 , -8.12012686e-10 , +2.70716366e-09 , -1.04835117e-08 , +1.25031812e-07 , +8.44739600e-09 , +9.44803685e-07 , +8.79855127e-09 , +2.77132783e-07 , +8.47311881e-09 , +4.19466777e-07 ], [ -2.68193562e-05 , -7.40137185e-05 , -8.70430426e-05 , -3.38221023e-05 , +4.81831224e-05 , +7.84590748e-05 , +4.50608719e-05 , +8.98217712e-06 , +1.39163332e-07 , +7.93198086e-06 , +2.11085001e-06 , -5.54383563e-05 , -1.43188311e-04 , -1.63937326e-04 , -9.77939517e-05 , -2.50973326e-05 , -6.00152886e-05 , -1.68367469e-04 , -2.40944512e-04 , -2.36681751e-04 , -1.48684798e-04 , -4.28771927e-05 , +7.38522813e-10 , -4.11055805e-08 , +2.76745346e-05 , +7.63098570e-05 , +1.03003789e-04 , +1.01410471e-04 , +6.63847453e-05 , +2.40037513e-05 , +1.09219668e-06 , +7.16792635e-08 , +6.42768184e-06 , +1.56080544e-05 , +1.48622105e-05 , +7.74806701e-06 , -3.77593803e-09 , +2.08784323e-08 , -1.27853961e-09 , +8.72314699e-09 , -1.67073899e-06 , -4.09986001e-06 , -4.10563669e-06 , -2.44272584e-06 , -2.49184856e-06 , -4.06087420e-08 , -7.94562212e-07 , -3.08151599e-08 , -4.47470791e-08 , -1.19583835e-07 , +9.62402953e-10 , -3.22129964e-09 , +3.51825290e-10 , -1.26768760e-09 , +4.34840136e-10 , -1.74231372e-09 , +3.70098722e-08 , +3.05519869e-08 , +1.07905222e-07 , +8.79855126e-09 , +9.51013091e-07 , +7.52845576e-09 , +2.07883245e-07 , +6.60032449e-09 ], [ +2.04396573e-05 , +6.59539213e-05 , +8.92952513e-05 , +4.08127877e-05 , -5.26892601e-05 , -9.62804318e-05 , -5.87147592e-05 , -1.21227397e-05 , +1.75021100e-05 , +3.81841069e-05 , +4.83814965e-05 , +9.53166232e-05 , +1.87544957e-04 , +2.18045341e-04 , +1.37205629e-04 , +3.73472480e-05 , +7.69086532e-05 , +2.13344876e-04 , +3.02159478e-04 , +2.99310789e-04 , +1.93701402e-04 , +5.79188403e-05 , -2.14682176e-08 , +7.44950660e-08 , -3.85810496e-05 , -1.05203248e-04 , -1.40136769e-04 , -1.37522779e-04 , -9.05026140e-05 , -3.27956689e-05 , +7.55690008e-08 , +1.71813132e-06 , -8.27186291e-06 , -2.02146516e-05 , -1.93553188e-05 , -1.04787929e-05 , +1.52456862e-08 , -4.01478702e-08 , +3.66057840e-09 , -1.29510501e-08 , +2.12478461e-06 , +4.88476330e-06 , +5.00544985e-06 , +2.18283709e-06 , -3.42927755e-08 , -3.34008174e-06 , -3.88149263e-08 , -1.24564543e-06 , +5.80240075e-08 , +1.62608774e-07 , -2.34475172e-09 , +6.05527520e-09 , -1.45146029e-09 , +2.25067476e-09 , -3.03790878e-10 , +1.74807361e-09 , -9.38097076e-09 , +1.44763809e-07 , +5.17215343e-09 , +2.77132783e-07 , +7.52845577e-09 , +1.21059609e-06 , +9.45991156e-09 , +3.20829504e-07 ], [ -6.98162707e-06 , -2.88277020e-05 , -4.41152940e-05 , -1.79855450e-05 , +3.76242630e-05 , +6.39648556e-05 , +3.87120823e-05 , +7.96991794e-06 , -1.64920055e-05 , -3.82509353e-05 , -4.29649476e-05 , -6.07664635e-05 , -1.09339980e-04 , -1.28374787e-04 , -8.14635492e-05 , -2.20548302e-05 , -5.32406460e-05 , -1.45832037e-04 , -2.02581790e-04 , -1.98203430e-04 , -1.27701445e-04 , -3.80974837e-05 , +2.05157096e-08 , -5.81951308e-08 , +2.33674001e-05 , +6.34394314e-05 , +8.39617948e-05 , +8.25436467e-05 , +5.48512680e-05 , +2.11223256e-05 , +1.79042333e-06 , +9.67577627e-08 , +5.48195855e-06 , +1.33563694e-05 , +1.27582384e-05 , +6.89900545e-06 , -1.36899923e-08 , +3.23142888e-08 , -3.60935946e-09 , +9.95776033e-09 , -1.47531267e-06 , -3.44935893e-06 , -3.82774906e-06 , -2.15575165e-06 , -7.87495431e-07 , -5.13884676e-08 , -3.10196062e-06 , -4.36963814e-08 , -3.81627948e-08 , -1.07504320e-07 , +1.96028422e-09 , -4.89007226e-09 , +1.43849970e-09 , -1.94269185e-09 , +2.67317769e-10 , -1.16452732e-09 , +5.91066723e-08 , +2.66707985e-08 , +2.13823888e-07 , +8.47311880e-09 , +2.07883245e-07 , +9.45991156e-09 , +1.27442343e-06 , +9.72610493e-09 ], [ -4.44246381e-06 , +7.01714613e-06 , +3.28087410e-05 , +2.01134774e-05 , -3.73320891e-05 , -7.22203672e-05 , -4.57872945e-05 , -9.59765553e-06 , +3.08317964e-05 , +7.47396898e-05 , +7.97249392e-05 , +8.47178527e-05 , +1.35368384e-04 , +1.64992498e-04 , +1.10821099e-04 , +3.16066186e-05 , +6.22715883e-05 , +1.68245030e-04 , +2.31220011e-04 , +2.28622096e-04 , +1.51019338e-04 , +4.59077793e-05 , -4.08437804e-08 , +8.17899381e-08 , -3.08495727e-05 , -8.32291915e-05 , -1.09427817e-04 , -1.07792910e-04 , -7.31004203e-05 , -2.84748026e-05 , +7.01705634e-08 , +1.91466896e-06 , -6.40967968e-06 , -1.56615859e-05 , -1.50820404e-05 , -8.32073693e-06 , +2.28011834e-08 , -4.70655306e-08 , +7.58988369e-09 , -1.44173771e-08 , +1.69783919e-06 , +3.69110775e-06 , +4.04170529e-06 , +1.35376434e-06 , -2.94688915e-08 , -1.21130717e-06 , -3.85222831e-08 , -3.43582728e-06 , +4.49909001e-08 , +1.30099000e-07 , -2.66859099e-09 , +6.56603904e-09 , -2.05616894e-09 , +3.03210691e-09 , -9.01771215e-10 , +1.88792713e-09 , -7.52969842e-09 , +2.15408864e-07 , +4.32828039e-09 , +4.19466777e-07 , +6.60032450e-09 , +3.20829504e-07 , +9.72610493e-09 , +1.42018284e-06 ]]) python-ase-3.9.1.4567/ase/dft/stm.py0000664000175000017500000001420012553425527017176 0ustar jensjjensj00000000000000import pickle import numpy as np class STM: def __init__(self, atoms, symmetries=None, use_density=False): """Scanning tunneling microscope. atoms: Atoms object or filename Atoms to scan or name of file to read LDOS from. symmetries: list of int List of integers 0, 1, and/or 2 indicating which surface symmetries have been used to reduce the number of k-points for the DFT calculation. The three integers correspond to the following three symmetry operations:: [-1 0] [ 1 0] [ 0 1] [ 0 1] [ 0 -1] [ 1 0] use_density: bool Use the electron density instead of the LDOS. """ self.use_density = use_density if isinstance(atoms, str): with open(atoms, 'rb') as f: self.ldos, self.bias, self.cell = pickle.load(f) self.atoms = None else: self.atoms = atoms self.cell = atoms.cell self.bias = None self.ldos = None assert not self.cell[2, :2].any() and not self.cell[:2, 2].any() self.symmetries = symmetries or [] def calculate_ldos(self, bias): """Calculate local density of states for given bias.""" if self.ldos is not None and bias == self.bias: return self.bias = bias calc = self.atoms.calc if self.use_density: self.ldos = calc.get_pseudo_density() return if bias < 0: emin = bias emax = 0.0 else: emin = 0 emax = bias nbands = calc.get_number_of_bands() weights = calc.get_k_point_weights() nkpts = len(weights) nspins = calc.get_number_of_spins() eigs = np.array([[calc.get_eigenvalues(k, s) for k in range(nkpts)] for s in range(nspins)]) eigs -= calc.get_fermi_level() ldos = 0.0 for s in range(nspins): for k in range(nkpts): for n in range(nbands): e = eigs[s, k, n] if emin < e < emax: psi = calc.get_pseudo_wave_function(n, k, s) ldos += weights[k] * (psi * np.conj(psi)).real if 0 in self.symmetries: # (x,y) -> (-x,y) ldos[1:] += ldos[:0:-1].copy() ldos[1:] *= 0.5 if 1 in self.symmetries: # (x,y) -> (x,-y) ldos[:, 1:] += ldos[:, :0:-1].copy() ldos[:, 1:] *= 0.5 if 2 in self.symmetries: # (x,y) -> (y,x) ldos += ldos.transpose((1, 0, 2)).copy() ldos *= 0.5 self.ldos = ldos def write(self, filename='stm.pckl'): """Write local density of states to pickle file.""" with open(filename, 'wb') as f: pickle.dump((self.ldos, self.bias, self.cell), f, protocol=pickle.HIGHEST_PROTOCOL) def get_averaged_current(self, bias, z): """Calculate avarage current at height z. Use this to get an idea of what current to use when scanning.""" self.calculate_ldos(bias) nz = self.ldos.shape[2] # Find grid point: n = z / self.cell[2, 2] * nz dn = n - np.floor(n) n = int(n) % nz # Average and do linear interpolation: return ((1 - dn) * self.ldos[:, :, n].mean() + dn * self.ldos[:, :, (n + 1) % nz].mean()) def scan(self, bias, current, z0=None, repeat=(1, 1)): """Constant current 2-d scan. Returns three 2-d arrays (x, y, z) containing x-coordinates, y-coordinates and heights. These three arrays can be passed to matplotlibs contourf() function like this: >>> import matplotlib.pyplot as plt >>> plt.gca(aspect='equal') >>> plt.contourf(x, y, z) >>> plt.show() """ self.calculate_ldos(bias) L = self.cell[2, 2] nz = self.ldos.shape[2] h = L / nz ldos = self.ldos.reshape((-1, nz)) heights = np.empty(ldos.shape[0]) for i, a in enumerate(ldos): heights[i] = find_height(a, current, h, z0) s0 = heights.shape = self.ldos.shape[:2] heights = np.tile(heights, repeat) s = heights.shape ij = np.indices(s, dtype=float).reshape((2, -1)).T x, y = np.dot(ij / s0, self.cell[:2, :2]).T.reshape((2,) + s) return x, y, heights def linescan(self, bias, current, p1, p2, npoints=50, z0=None): """Constant current line scan. Example:: stm = STM(...) z = ... # tip position c = stm.get_averaged_current(-1.0, z) stm.linescan(-1.0, c, (1.2, 0.0), (1.2, 3.0)) """ heights = self.scan(bias, current, z0)[2] p1 = np.asarray(p1, float) p2 = np.asarray(p2, float) d = p2 - p1 s = np.dot(d, d)**0.5 cell = self.cell[:2, :2] shape = np.array(heights.shape, float) M = np.linalg.inv(cell) line = np.empty(npoints) for i in range(npoints): p = p1 + i * d / (npoints - 1) q = np.dot(p, M) * shape line[i] = interpolate(q, heights) return np.linspace(0, s, npoints), line def interpolate(q, heights): qi = q.astype(int) f = q - qi g = 1 - f qi %= heights.shape n0, m0 = qi n1, m1 = (qi + 1) % heights.shape z = (g[0] * g[1] * heights[n0, m0] + f[0] * g[1] * heights[n1, m0] + g[0] * f[1] * heights[n0, m1] + f[0] * f[1] * heights[n1, m1]) return z def find_height(ldos, current, h, z0=None): if z0 is None: n = len(ldos) - 2 else: n = int(z0 / h) while n >= 0: if ldos[n] > current: break n -= 1 else: return 0.0 c2, c1 = ldos[n:n + 2] return (n + 1 - (current - c1) / (c2 - c1)) * h python-ase-3.9.1.4567/ase/dft/bee.py0000664000175000017500000001246212553425527017136 0ustar jensjjensj00000000000000from __future__ import print_function import os import pickle import numpy as np from ase.atoms import Atoms from ase.parallel import rank def ensemble(energy, contributions, xc, verbose=False): """Returns an array of ensemble total energies.""" ensemble = BEEFEnsemble(None, energy, contributions, xc, verbose) return ensemble.get_ensemble_energies() class BEEFEnsemble: """BEEF type ensemble error estimation""" def __init__(self, atoms=None, e=None, contribs=None, xc=None, verbose=True): if (atoms is not None or contribs is not None or xc is not None): if atoms is None: assert e is not None assert contribs is not None assert xc is not None else: if isinstance(atoms, Atoms): calc = atoms.get_calculator() self.atoms = atoms else: calc = atoms self.atoms = calc.atoms self.calc = calc xc = self.calc.get_xc_functional() self.e = e self.contribs = contribs self.xc = xc self.verbose = verbose self.done = False if self.xc in ['BEEF-vdW', 'BEEF', 'PBE']: self.beef_type = 'beefvdw' elif self.xc == 'mBEEF': self.beef_type = 'mbeef' elif self.xc == 'mBEEF-vdW': self.beef_type = 'mbeefvdw' else: raise NotImplementedError('No ensemble for xc = %s' % self.xc) def get_ensemble_energies(self, size=2000, seed=0): """Returns an array of ensemble total energies""" self.seed = seed if rank == 0 and self.verbose: print(self.beef_type, 'ensemble started') if self.contribs is None: self.contribs = self.calc.get_nonselfconsistent_energies( self.beef_type) self.e = self.calc.get_potential_energy(self.atoms) if self.beef_type == 'beefvdw': assert len(self.contribs) == 32 coefs = self.get_beefvdw_ensemble_coefs(size, seed) elif self.beef_type == 'mbeef': assert len(self.contribs) == 64 coefs = self.get_mbeef_ensemble_coefs(size, seed) elif self.beef_type == 'mbeefvdw': assert len(self.contribs) == 28 coefs = self.get_mbeefvdw_ensemble_coefs(size, seed) self.de = np.dot(coefs, self.contribs) self.done = True if rank == 0 and self.verbose: print(self.beef_type, 'ensemble finished') return self.e + self.de def get_beefvdw_ensemble_coefs(self, size=2000, seed=0): """Pertubation coefficients of the BEEF-vdW ensemble""" from ase.dft.pars_beefvdw import uiOmega as omega assert np.shape(omega) == (31, 31) W, V, generator = self.eigendecomposition(omega, seed) RandV = generator.randn(31, size) for j in range(size): v = RandV[:, j] coefs_i = (np.dot(np.dot(V, np.diag(np.sqrt(W))), v)[:]) if j == 0: ensemble_coefs = coefs_i else: ensemble_coefs = np.vstack((ensemble_coefs, coefs_i)) PBEc_ens = -ensemble_coefs[:, 30] return (np.vstack((ensemble_coefs.T, PBEc_ens))).T def get_mbeef_ensemble_coefs(self, size=2000, seed=0): """Pertubation coefficients of the mBEEF ensemble""" from ase.dft.pars_mbeef import uiOmega as omega assert np.shape(omega) == (64, 64) W, V, generator = self.eigendecomposition(omega, seed) mu, sigma = 0.0, 1.0 rand = np.array(generator.normal(mu, sigma, (len(W), size))) return (np.sqrt(2) * np.dot(np.dot(V, np.diag(np.sqrt(W))), rand)[:]).T def get_mbeefvdw_ensemble_coefs(self, size=2000, seed=0): """Pertubation coefficients of the mBEEF-vdW ensemble""" from ase.dft.pars_mbeefvdw import uiOmega as omega assert np.shape(omega) == (28, 28) W, V, generator = self.eigendecomposition(omega, seed) mu, sigma = 0.0, 1.0 rand = np.array(generator.normal(mu, sigma, (len(W), size))) return (np.sqrt(2) * np.dot(np.dot(V, np.diag(np.sqrt(W))), rand)[:]).T def eigendecomposition(self, omega, seed=0): u, s, v = np.linalg.svd(omega) # unsafe: W, V = np.linalg.eig(omega) generator = np.random.RandomState(seed) return s, v.T, generator def write(self, fname): """Write ensemble data file""" if not fname.endswith('.bee'): fname += '.bee' assert self.done if rank == 0: if os.path.isfile(fname): os.rename(fname, fname + '.old') obj = [self.e, self.de, self.contribs, self.seed, self.xc] with open(fname, 'wb') as f: pickle.dump(obj, f) def readbee(fname, all=False): if not fname.endswith('.bee'): fname += '.bee' with open(fname, 'rb') as f: e, de, contribs, seed, xc = pickle.load(f) if all: return e, de, contribs, seed, xc else: return e + de def BEEF_Ensemble(*args, **kwargs): import warnings warnings.warn('Please use BEEFEnsemble instead of BEEF_Ensemble.') return BEEFEnsemble(*args, **kwargs) python-ase-3.9.1.4567/ase/dft/kpoints.py0000664000175000017500000002654712553425527020103 0ustar jensjjensj00000000000000from __future__ import division import warnings import numpy as np def monkhorst_pack(size): """Construct a uniform sampling of k-space of given size.""" if np.less_equal(size, 0).any(): raise ValueError('Illegal size: %s' % list(size)) kpts = np.indices(size).transpose((1, 2, 3, 0)).reshape((-1, 3)) return (kpts + 0.5) / size - 0.5 def get_monkhorst_pack_size_and_offset(kpts): """Find Monkhorst-Pack size and offset. Returns (size, offset), where:: kpts = monkhorst_pack(size) + offset. The set of k-points must not have been symmetry reduced.""" if len(kpts) == 1: return np.ones(3, int), np.array(kpts[0], dtype=float) size = np.zeros(3, int) for c in range(3): # Determine increment between k-points along current axis delta = max(np.diff(np.sort(kpts[:, c]))) # Determine number of k-points as inverse of distance between kpoints if delta > 1e-8: size[c] = int(round(1.0 / delta)) else: size[c] = 1 if size.prod() == len(kpts): kpts0 = monkhorst_pack(size) offsets = kpts - kpts0 # All offsets must be identical: if (offsets.ptp(axis=0) < 1e-9).all(): return size, offsets[0].copy() raise ValueError('Not an ASE-style Monkhorst-Pack grid!') def get_monkhorst_shape(kpts): warnings.warn('Use get_monkhorst_pack_size_and_offset()[0] instead.') return get_monkhorst_pack_size_and_offset(kpts)[0] def kpoint_convert(cell_cv, skpts_kc=None, ckpts_kv=None): """Convert k-points between scaled and cartesian coordinates. Given the atomic unit cell, and either the scaled or cartesian k-point coordinates, the other is determined. The k-point arrays can be either a single point, or a list of points, i.e. the dimension k can be empty or multidimensional. """ if ckpts_kv is None: icell_cv = 2 * np.pi * np.linalg.inv(cell_cv).T return np.dot(skpts_kc, icell_cv) elif skpts_kc is None: return np.dot(ckpts_kv, cell_cv.T) / (2 * np.pi) else: raise KeyError('Either scaled or cartesian coordinates must be given.') def get_bandpath(points, cell, npoints=50): """Make a list of kpoints defining the path between the given points. points: list List of special IBZ point pairs, e.g. ``points = [W, L, Gamma, X, W, K]``. These should be given in scaled coordinates. cell: 3x3 ndarray Unit cell of the atoms. npoints: int Length of the output kpts list. Return list of k-points, list of x-coordinates and list of x-coordinates of special points.""" points = np.asarray(points) dists = points[1:] - points[:-1] lengths = [np.linalg.norm(d) for d in kpoint_convert(cell, skpts_kc=dists)] length = sum(lengths) kpts = [] x0 = 0 x = [] X = [0] for P, d, L in zip(points[:-1], dists, lengths): n = int(round(L * (npoints - 1 - len(x)) / (length - x0))) for t in np.linspace(0, 1, n, endpoint=False): kpts.append(P + t * d) x.append(x0 + t * L) x0 += L X.append(x0) kpts.append(points[-1]) x.append(x0) return np.array(kpts), np.array(x), np.array(X) # The following is a list of the critical points in the 1. Brillouin zone # for some typical crystal structures. # (In units of the reciprocal basis vectors) # See http://en.wikipedia.org/wiki/Brillouin_zone ibz_points = {'cubic': {'Gamma': [0, 0, 0 ], 'X': [0, 0 / 2, 1 / 2], 'R': [1 / 2, 1 / 2, 1 / 2], 'M': [0 / 2, 1 / 2, 1 / 2]}, 'fcc': {'Gamma': [0, 0, 0 ], 'X': [1 / 2, 0, 1 / 2], 'W': [1 / 2, 1 / 4, 3 / 4], 'K': [3 / 8, 3 / 8, 3 / 4], 'U': [5 / 8, 1 / 4, 5 / 8], 'L': [1 / 2, 1 / 2, 1 / 2]}, 'bcc': {'Gamma': [0, 0, 0 ], 'H': [1 / 2, -1 / 2, 1 / 2], 'N': [0, 0, 1 / 2], 'P': [1 / 4, 1 / 4, 1 / 4]}, 'hexagonal': {'Gamma': [0, 0, 0 ], 'M': [0, 1 / 2, 0 ], 'K': [-1 / 3, 1 / 3, 0 ], 'A': [0, 0, 1 / 2 ], 'L': [0, 1 / 2, 1 / 2 ], 'H': [-1 / 3, 1 / 3, 1 / 2 ]}, 'tetragonal': {'Gamma': [0, 0, 0 ], 'X': [1 / 2, 0, 0 ], 'M': [1 / 2, 1 / 2, 0 ], 'Z': [0, 0, 1 / 2 ], 'R': [1 / 2, 0, 1 / 2 ], 'A': [1 / 2, 1 / 2, 1 / 2 ]}, 'orthorhombic': {'Gamma': [0, 0, 0 ], 'R': [1 / 2, 1 / 2, 1 / 2 ], 'S': [1 / 2, 1 / 2, 0 ], 'T': [0, 1 / 2, 1 / 2 ], 'U': [1 / 2, 0, 1 / 2 ], 'X': [1 / 2, 0, 0 ], 'Y': [0, 1 / 2, 0 ], 'Z': [0, 0, 1 / 2 ]}, } # ChadiCohen k point grids. The k point grids are given in units of the # reciprocal unit cell. The variables are named after the following # convention: cc+''+_+'shape'. For example an 18 k point # sq(3)xsq(3) is named 'cc18_sq3xsq3'. cc6_1x1 = np.array([ 1, 1, 0, 1, 0, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0, 0, 1, 0]).reshape((6, 3)) / 3.0 cc12_2x3 = np.array([ 3, 4, 0, 3, 10, 0, 6, 8, 0, 3, -2, 0, 6, -4, 0, 6, 2, 0, -3, 8, 0, -3, 2, 0, -3, -4, 0, -6, 4, 0, -6, -2, 0, -6, -8, 0]).reshape((12, 3)) / 18.0 cc18_sq3xsq3 = np.array([ 2, 2, 0, 4, 4, 0, 8, 2, 0, 4, -2, 0, 8, -4, 0, 10, -2, 0, 10, -8, 0, 8, -10, 0, 2, -10, 0, 4, -8, 0, -2, -8, 0, 2, -4, 0, -4, -4, 0, -2, -2, 0, -4, 2, 0, -2, 4, 0, -8, 4, 0, -4, 8, 0]).reshape((18, 3)) / 18.0 cc18_1x1 = np.array([ 2, 4, 0, 2, 10, 0, 4, 8, 0, 8, 4, 0, 8, 10, 0, 10, 8, 0, 2, -2, 0, 4, -4, 0, 4, 2, 0, -2, 8, 0, -2, 2, 0, -2, -4, 0, -4, 4, 0, -4, -2, 0, -4, -8, 0, -8, 2, 0, -8, -4, 0, -10, -2, 0]).reshape((18, 3)) / 18.0 cc54_sq3xsq3 = np.array([ 4, -10, 0, 6, -10, 0, 0, -8, 0, 2, -8, 0, 6, -8, 0, 8, -8, 0, -4, -6, 0, -2, -6, 0, 2, -6, 0, 4, -6, 0, 8, -6, 0, 10, -6, 0, -6, -4, 0, -2, -4, 0, 0, -4, 0, 4, -4, 0, 6, -4, 0, 10, -4, 0, -6, -2, 0, -4, -2, 0, 0, -2, 0, 2, -2, 0, 6, -2, 0, 8, -2, 0, -8, 0, 0, -4, 0, 0, -2, 0, 0, 2, 0, 0, 4, 0, 0, 8, 0, 0, -8, 2, 0, -6, 2, 0, -2, 2, 0, 0, 2, 0, 4, 2, 0, 6, 2, 0, -10, 4, 0, -6, 4, 0, -4, 4, 0, 0, 4, 0, 2, 4, 0, 6, 4, 0, -10, 6, 0, -8, 6, 0, -4, 6, 0, -2, 6, 0, 2, 6, 0, 4, 6, 0, -8, 8, 0, -6, 8, 0, -2, 8, 0, 0, 8, 0, -6, 10, 0, -4, 10, 0]).reshape((54, 3)) / 18.0 cc54_1x1 = np.array([ 2, 2, 0, 4, 4, 0, 8, 8, 0, 6, 8, 0, 4, 6, 0, 6, 10, 0, 4, 10, 0, 2, 6, 0, 2, 8, 0, 0, 2, 0, 0, 4, 0, 0, 8, 0, -2, 6, 0, -2, 4, 0, -4, 6, 0, -6, 4, 0, -4, 2, 0, -6, 2, 0, -2, 0, 0, -4, 0, 0, -8, 0, 0, -8, -2, 0, -6, -2, 0, -10, -4, 0, -10, -6, 0, -6, -4, 0, -8, -6, 0, -2, -2, 0, -4, -4, 0, -8, -8, 0, 4, -2, 0, 6, -2, 0, 6, -4, 0, 2, 0, 0, 4, 0, 0, 6, 2, 0, 6, 4, 0, 8, 6, 0, 8, 0, 0, 8, 2, 0, 10, 4, 0, 10, 6, 0, 2, -4, 0, 2, -6, 0, 4, -6, 0, 0, -2, 0, 0, -4, 0, -2, -6, 0, -4, -6, 0, -6, -8, 0, 0, -8, 0, -2, -8, 0, -4, -10, 0, -6, -10, 0]).reshape((54, 3)) / 18.0 cc162_sq3xsq3 = np.array([ -8, 16, 0, -10, 14, 0, -7, 14, 0, -4, 14, 0, -11, 13, 0, -8, 13, 0, -5, 13, 0, -2, 13, 0, -13, 11, 0, -10, 11, 0, -7, 11, 0, -4, 11, 0, -1, 11, 0, 2, 11, 0, -14, 10, 0, -11, 10, 0, -8, 10, 0, -5, 10, 0, -2, 10, 0, 1, 10, 0, 4, 10, 0, -16, 8, 0, -13, 8, 0, -10, 8, 0, -7, 8, 0, -4, 8, 0, -1, 8, 0, 2, 8, 0, 5, 8, 0, 8, 8, 0, -14, 7, 0, -11, 7, 0, -8, 7, 0, -5, 7, 0, -2, 7, 0, 1, 7, 0, 4, 7, 0, 7, 7, 0, 10, 7, 0, -13, 5, 0, -10, 5, 0, -7, 5, 0, -4, 5, 0, -1, 5, 0, 2, 5, 0, 5, 5, 0, 8, 5, 0, 11, 5, 0, -14, 4, 0, -11, 4, 0, -8, 4, 0, -5, 4, 0, -2, 4, 0, 1, 4, 0, 4, 4, 0, 7, 4, 0, 10, 4, 0, -13, 2, 0, -10, 2, 0, -7, 2, 0, -4, 2, 0, -1, 2, 0, 2, 2, 0, 5, 2, 0, 8, 2, 0, 11, 2, 0, -11, 1, 0, -8, 1, 0, -5, 1, 0, -2, 1, 0, 1, 1, 0, 4, 1, 0, 7, 1, 0, 10, 1, 0, 13, 1, 0, -10, -1, 0, -7, -1, 0, -4, -1, 0, -1, -1, 0, 2, -1, 0, 5, -1, 0, 8, -1, 0, 11, -1, 0, 14, -1, 0, -11, -2, 0, -8, -2, 0, -5, -2, 0, -2, -2, 0, 1, -2, 0, 4, -2, 0, 7, -2, 0, 10, -2, 0, 13, -2, 0, -10, -4, 0, -7, -4, 0, -4, -4, 0, -1, -4, 0, 2, -4, 0, 5, -4, 0, 8, -4, 0, 11, -4, 0, 14, -4, 0, -8, -5, 0, -5, -5, 0, -2, -5, 0, 1, -5, 0, 4, -5, 0, 7, -5, 0, 10, -5, 0, 13, -5, 0, 16, -5, 0, -7, -7, 0, -4, -7, 0, -1, -7, 0, 2, -7, 0, 5, -7, 0, 8, -7, 0, 11, -7, 0, 14, -7, 0, 17, -7, 0, -8, -8, 0, -5, -8, 0, -2, -8, 0, 1, -8, 0, 4, -8, 0, 7, -8, 0, 10, -8, 0, 13, -8, 0, 16, -8, 0, -7, -10, 0, -4, -10, 0, -1, -10, 0, 2, -10, 0, 5, -10, 0, 8, -10, 0, 11, -10, 0, 14, -10, 0, 17, -10, 0, -5, -11, 0, -2, -11, 0, 1, -11, 0, 4, -11, 0, 7, -11, 0, 10, -11, 0, 13, -11, 0, 16, -11, 0, -1, -13, 0, 2, -13, 0, 5, -13, 0, 8, -13, 0, 11, -13, 0, 14, -13, 0, 1, -14, 0, 4, -14, 0, 7, -14, 0, 10, -14, 0, 13, -14, 0, 5, -16, 0, 8, -16, 0, 11, -16, 0, 7, -17, 0, 10, -17, 0]).reshape((162, 3)) / 27.0 cc162_1x1 = np.array([ -8, -16, 0, -10, -14, 0, -7, -14, 0, -4, -14, 0, -11, -13, 0, -8, -13, 0, -5, -13, 0, -2, -13, 0, -13, -11, 0, -10, -11, 0, -7, -11, 0, -4, -11, 0, -1, -11, 0, 2, -11, 0, -14, -10, 0, -11, -10, 0, -8, -10, 0, -5, -10, 0, -2, -10, 0, 1, -10, 0, 4, -10, 0, -16, -8, 0, -13, -8, 0, -10, -8, 0, -7, -8, 0, -4, -8, 0, -1, -8, 0, 2, -8, 0, 5, -8, 0, 8, -8, 0, -14, -7, 0, -11, -7, 0, -8, -7, 0, -5, -7, 0, -2, -7, 0, 1, -7, 0, 4, -7, 0, 7, -7, 0, 10, -7, 0, -13, -5, 0, -10, -5, 0, -7, -5, 0, -4, -5, 0, -1, -5, 0, 2, -5, 0, 5, -5, 0, 8, -5, 0, 11, -5, 0, -14, -4, 0, -11, -4, 0, -8, -4, 0, -5, -4, 0, -2, -4, 0, 1, -4, 0, 4, -4, 0, 7, -4, 0, 10, -4, 0, -13, -2, 0, -10, -2, 0, -7, -2, 0, -4, -2, 0, -1, -2, 0, 2, -2, 0, 5, -2, 0, 8, -2, 0, 11, -2, 0, -11, -1, 0, -8, -1, 0, -5, -1, 0, -2, -1, 0, 1, -1, 0, 4, -1, 0, 7, -1, 0, 10, -1, 0, 13, -1, 0, -10, 1, 0, -7, 1, 0, -4, 1, 0, -1, 1, 0, 2, 1, 0, 5, 1, 0, 8, 1, 0, 11, 1, 0, 14, 1, 0, -11, 2, 0, -8, 2, 0, -5, 2, 0, -2, 2, 0, 1, 2, 0, 4, 2, 0, 7, 2, 0, 10, 2, 0, 13, 2, 0, -10, 4, 0, -7, 4, 0, -4, 4, 0, -1, 4, 0, 2, 4, 0, 5, 4, 0, 8, 4, 0, 11, 4, 0, 14, 4, 0, -8, 5, 0, -5, 5, 0, -2, 5, 0, 1, 5, 0, 4, 5, 0, 7, 5, 0, 10, 5, 0, 13, 5, 0, 16, 5, 0, -7, 7, 0, -4, 7, 0, -1, 7, 0, 2, 7, 0, 5, 7, 0, 8, 7, 0, 11, 7, 0, 14, 7, 0, 17, 7, 0, -8, 8, 0, -5, 8, 0, -2, 8, 0, 1, 8, 0, 4, 8, 0, 7, 8, 0, 10, 8, 0, 13, 8, 0, 16, 8, 0, -7, 10, 0, -4, 10, 0, -1, 10, 0, 2, 10, 0, 5, 10, 0, 8, 10, 0, 11, 10, 0, 14, 10, 0, 17, 10, 0, -5, 11, 0, -2, 11, 0, 1, 11, 0, 4, 11, 0, 7, 11, 0, 10, 11, 0, 13, 11, 0, 16, 11, 0, -1, 13, 0, 2, 13, 0, 5, 13, 0, 8, 13, 0, 11, 13, 0, 14, 13, 0, 1, 14, 0, 4, 14, 0, 7, 14, 0, 10, 14, 0, 13, 14, 0, 5, 16, 0, 8, 16, 0, 11, 16, 0, 7, 17, 0, 10, 17, 0]).reshape((162, 3)) / 27.0 python-ase-3.9.1.4567/ase/vibrations/0000775000175000017500000000000012553427753017432 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/vibrations/__init__.py0000664000175000017500000003643612553425526021553 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- """Vibrational modes.""" import pickle from math import sin, pi, sqrt, log from os import remove from os.path import isfile, getsize import sys import numpy as np import ase.units as units from ase.io.trajectory import Trajectory 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.emt import EMT >>> from ase.optimize import BFGS >>> from ase.vibrations import Vibrations >>> n2 = Atoms('N2', [(0, 0, 0), (0, 0, 1.1)], ... calculator=EMT()) >>> BFGS(n2).run(fmax=0.01) BFGS: 0 16:01:21 0.440339 3.2518 BFGS: 1 16:01:21 0.271928 0.8211 BFGS: 2 16:01:21 0.263278 0.1994 BFGS: 3 16:01:21 0.262777 0.0088 >>> vib = Vibrations(n2) >>> vib.run() Writing vib.eq.pckl Writing vib.0x-.pckl Writing vib.0x+.pckl Writing vib.0y-.pckl Writing vib.0y+.pckl Writing vib.0z-.pckl Writing vib.0z+.pckl Writing vib.1x-.pckl Writing vib.1x+.pckl Writing vib.1y-.pckl Writing vib.1y+.pckl Writing vib.1z-.pckl Writing vib.1z+.pckl >>> vib.summary() --------------------- # meV cm^-1 --------------------- 0 0.0 0.0 1 0.0 0.0 2 0.0 0.0 3 2.5 20.4 4 2.5 20.4 5 152.6 1230.8 --------------------- Zero-point energy: 0.079 eV >>> vib.write_mode(-1) # write last mode to trajectory file """ 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])) if (isfile(filename) and getsize(filename) == 0 and rank == 0): remove(filename) 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'] def load(fname): f = pickle.load(open(fname, 'rb')) if not hasattr(f, 'shape'): # output from InfraRed return f[0] return f n = 3 * len(self.indices) H = np.empty((n, n)) r = 0 if direction != 'central': feq = load(self.name + '.eq.pckl') for a in self.indices: for i in 'xyz': name = '%s.%d%s' % (self.name, a, i) fminus = load(name + '-.pckl') fplus = load(name + '+.pckl') if self.method == 'frederiksen': fminus[a] -= fminus.sum(0) fplus[a] -= fplus.sum(0) if self.nfree == 4: fminusminus = load(name + '--.pckl') fplusplus = load(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 = 1. / units.invcm 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): """Get mode number .""" 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=None, kT=units.kB * 300, nimages=30): """Write mode number n to trajectory file. If n is not specified, writes all non-zero modes.""" if n == None: for index, energy in enumerate(self.get_energies()): if abs(energy) > 1e-5: self.write_mode(n=index, kT=kT, nimages=nimages) return mode = self.get_mode(n) * sqrt(kT / abs(self.hnu[n])) p = self.atoms.positions.copy() n %= 3 * len(self.indices) traj = Trajectory('%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() def fold(self, frequencies, intensities, start=800, end=4000, npts=None, width=4, type='Gaussian', normalize=False): """Fold frequencies and intensities within the given range and folding method (Gaussian/Lorentzian). The energy unit is cm^-1. normalize=True ensures the integral over the peaks to give the intensity. """ self.type = type.lower() assert self.type in ['gaussian', 'lorentzian'] if not npts: npts = (end - start) / width * 10 + 1 prefactor = 1 if type == 'lorentzian': intensities = intensities * width * pi / 2. if normalize: prefactor = 2. / width / pi else: sigma = width / 2. / sqrt(2. * log(2.)) if normalize: prefactor = 1. / sigma / sqrt(2 * pi) # 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, prefactor * spectrum] def write_dos(self, out='vib-dos.dat', start=800, end=4000, npts=None, width=10, type='Gaussian', method='standard', direction='central'): """Write out the vibrational density of states to file. First column is the wavenumber in cm^-1, the second column the folded vibrational density of states. Start and end points, and width of the Gaussian/Lorentzian should be given in cm^-1.""" frequencies = self.get_frequencies(method, direction).real intensities = np.ones(len(frequencies)) energies, spectrum = self.fold(frequencies, intensities, start, end, npts, width, type) # Write out spectrum in file. outdata = np.empty([len(energies), 2]) outdata.T[0] = energies outdata.T[1] = spectrum fd = open(out, 'w') fd.write('# %s folded, width=%g cm^-1\n' % (type.title(), width)) fd.write('# [cm^-1] arbitrary\n') for row in outdata: fd.write('%.3f %15.5e\n' % (row[0], row[1])) fd.close() python-ase-3.9.1.4567/ase/vibrations/infrared.py0000664000175000017500000003166112553425526021601 0ustar jensjjensj00000000000000 # -*- coding: utf-8 -*- """Infrared intensities""" import pickle from math import sqrt from sys import stdout import numpy as np import ase.units as units from ase.parallel import parprint, paropen 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.vibrations.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 = (1.0 / units.Debye)**2 * units._amu / units._me self.intensities = intensities * conv def intensity_prefactor(self, intensity_unit): if intensity_unit == '(D/A)2/amu': return 1.0, '(D/Å)^2 amu^-1' elif intensity_unit == 'km/mol': # conversion factor from Porezag PRB 54 (1996) 7830 return 42.255, 'km/mol' else: raise RuntimeError('Intensity unit >' + intensity_unit + '< unknown.') def summary(self, method='standard', direction='central', intensity_unit='(D/A)2/amu', log=stdout): hnu = self.get_energies(method, direction) s = 0.01 * units._e / units._c / units._hplanck iu, iu_string = self.intensity_prefactor(intensity_unit) if intensity_unit == '(D/A)2/amu': iu_format = '%9.4f' elif intensity_unit == 'km/mol': iu_string = ' ' + iu_string iu_format = ' %7.1f' if isinstance(log, str): log = paropen(log, 'a') parprint('-------------------------------------', file=log) parprint(' Mode Frequency Intensity', file=log) parprint(' # meV cm^-1 ' + iu_string, file=log) parprint('-------------------------------------', file=log) for n, e in enumerate(hnu): if e.imag != 0: c = 'i' e = e.imag else: c = ' ' e = e.real parprint(('%3d %6.1f%s %7.1f%s ' + iu_format) % (n, 1000 * e, c, s * e, c, iu * self.intensities[n]), file=log) parprint('-------------------------------------', file=log) parprint('Zero-point energy: %.3f eV' % self.get_zero_point_energy(), file=log) parprint('Static dipole moment: %.3f D' % self.dipole_zero, file=log) parprint('Maximum force on atom in `equilibrium`: %.4f eV/Å' % self.force_zero, file=log) parprint(file=log) def get_spectrum(self, start=800, end=4000, npts=None, width=4, type='Gaussian', method='standard', direction='central', intensity_unit='(D/A)2/amu', normalize=False): """Get infrared spectrum. The method returns wavenumbers in cm^-1 with corresponding absolute infrared intensity. Start and end point, and width of the Gaussian/Lorentzian should be given in cm^-1. normalize=True ensures the integral over the peaks to give the intensity. """ frequencies = self.get_frequencies(method, direction).real intensities = self.intensities return self.fold(frequencies, intensities, start, end, npts, width, type, normalize) def write_spectra(self, out='ir-spectra.dat', start=800, end=4000, npts=None, width=10, type='Gaussian', method='standard', direction='central', intensity_unit='(D/A)2/amu', normalize=False): """Write out infrared spectrum to file. First column is the wavenumber in cm^-1, the second column the absolute infrared intensities, and the third column the absorbance scaled so that data runs from 1 to 0. Start and end point, and width of the Gaussian/Lorentzian should be given in cm^-1.""" energies, spectrum = self.get_spectrum(start, end, npts, width, type, method, direction, normalize) #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') fd.write('# %s folded, width=%g cm^-1\n' % (type.title(), width)) iu, iu_string = self.intensity_prefactor(intensity_unit) if normalize: iu_string = 'cm ' + iu_string fd.write('# [cm^-1] %14s\n' % ('[' + iu_string + ']')) for row in outdata: fd.write('%.3f %15.5e %15.5e \n' % (row[0], iu * row[1], row[2])) fd.close() #np.savetxt(out, outdata, fmt='%.3f %15.5e %15.5e') python-ase-3.9.1.4567/ase/vibrations/franck_condon.py0000664000175000017500000001574012553425526022613 0ustar jensjjensj00000000000000from operator import mul from itertools import combinations, product, chain from math import factorial import numpy as np from array import * from ase.units import kg, C, _hbar, kB from ase.vibrations import Vibrations from functools import reduce class FranckCondon: def __init__(self, atoms, vibname, minfreq=None, maxfreq=None): """Input is a atoms object and the corresponding vibrations. With minfreq and maxfreq frequencies can be excluded from the calculation""" self.atoms = atoms # V = a * v is the combined atom and xyz-index self.mm05_V = np.repeat(1. / np.sqrt(atoms.get_masses()), 3) self.minfreq = minfreq self.maxfreq = maxfreq self.shape = (len(self.atoms), 3) vib = Vibrations(atoms, name=vibname) self.energies = np.real(vib.get_energies(method='frederiksen')) # [eV] self.frequencies = np.real( vib.get_frequencies(method='frederiksen')) # [cm^-1] self.modes = vib.modes self.H = vib.H def get_Huang_Rhys_factors(self, forces): """Evaluate Huang-Rhys factors and corresponding frequencies from forces on atoms in the exited electronic state. The double harmonic approximation is used. HR factors are the first approximation of FC factors, no combinations or higher quanta (>1) exitations are considered""" assert(forces.shape == self.shape) # Hesse matrix H_VV = self.H # sqrt of inverse mass matrix mm05_V = self.mm05_V # mass weighted Hesse matrix Hm_VV = mm05_V[:, None] * H_VV * mm05_V # mass weighted displacements Fm_V = forces.flat * mm05_V X_V = np.linalg.solve(Hm_VV, Fm_V) # projection onto the modes modes_VV = self.modes #d_V=np.dot([mode for mode in modes_VV] ,X_V) d_V = np.dot(modes_VV, X_V) # Huang-Rhys factors S s = 1.e-20 / kg / C / _hbar**2 # SI units S = s * d_V**2 * self.energies / 2 # reshape for minfreq indices = np.where(self.frequencies <= self.minfreq) np.append(indices, np.where(self.frequencies >= self.maxfreq)) S=np.delete(S, indices) frequencies = np.delete(self.frequencies, indices) return S, frequencies def get_Franck_Condon_factors(self, order, temp, forces): """Return FC factors and corresponding frequencies up to given order. order= number of quanta taken into account T= temperature in K. Vibronic levels are occupied by a Boltzman distribution. forces= forces on atoms in the exited electronic state""" S, f = self.get_Huang_Rhys_factors(forces) n = order + 1 T = temp freq = np.array(f) # frequencies freq_n = [[]*i for i in range(n-1)] freq_neg = [[]*i for i in range(n-1)] for i in range(1,n): freq_n[i-1]=freq*i freq_neg[i-1]=freq*(-i) # combinations freq_nn=[x for x in combinations(chain(*freq_n), 2)] for i in range(len(freq_nn)): freq_nn[i] = freq_nn[i][0] + freq_nn[i][1] indices2 = [] for i, y in enumerate(freq): ind = [j for j,x in enumerate(freq_nn) if x%y==0.]# or x/y==3.] indices2.append(ind) indices2 = [x for x in chain(*indices2)] freq_nn = np.delete(freq_nn, indices2) frequencies= [[] * x for x in range(3)] frequencies[0].append(freq_neg[0]) frequencies[0].append([0]) frequencies[0].append(freq_n[0]) frequencies[0]=[x for x in chain(*frequencies[0])] for i in range(1,n-1): frequencies[1].append(freq_neg[i]) frequencies[1].append(freq_n[i]) frequencies[1]=[x for x in chain(*frequencies[1])] frequencies[2]=freq_nn ##Franck-Condon factors E = freq / 8065.5 f_n = [[] * i for i in range(n)] for j in range(0,n): f_n[j] = np.exp(-E * j /( kB * T)) #partition function Z=np.empty(len(S)) Z=np.sum(f_n,0) #occupation probability w_n=[[]*k for k in range(n)] for l in range(n): w_n[l]=f_n[l]/Z # overlap wavefunctions O_n = [[] * m for m in range(n)] O_neg = [[] * m for m in range(n)] for o in range(n): O_n[o] = [[] * p for p in range(n)] O_neg[o] = [[] * p for p in range(n - 1)] for q in range(o, n + o): a = np.minimum(o, q) summe=[] for k in range(a+1): s = ((-1)**(q - k) * np.sqrt(S)**(o + q - 2 * k) * factorial(o) * factorial(q) / (factorial(k) * factorial(o - k) * factorial(q - k))) summe.append(s) summe = np.sum(summe, 0) O_n[o][q-o] = (np.exp(-S / 2) / (factorial(o) * factorial(q))**(0.5) * summe)**2 * w_n[o] for q in range(n - 1): O_neg[o][q] = [0 * b for b in range(len(S))] for q in range(o-1, -1, -1): a = np.minimum(o,q) summe = [] for k in range(a+1): s=((-1)**(q - k) * np.sqrt(S)**(o + q - 2 * k) * factorial(o) * factorial(q) / (factorial(k) * factorial(o - k) * factorial(q - k))) summe.append(s) summe = np.sum(summe, 0) O_neg[o][q] = (np.exp(-S / 2) / (factorial(o) * factorial(q))**(0.5) * summe)**2 * w_n[o] O_neg = np.delete(O_neg, 0, 0) #Franck-Condon factors FC_n=[[]*i for i in range(n)] FC_n=np.sum(O_n,0) zero=reduce(mul,FC_n[0]) FC_neg=[[]*i for i in range(n-2)] FC_neg=np.sum(O_neg,0) FC_n=np.delete(FC_n,0,0) #combination FC factors FC_nn=[x for x in combinations(chain(*FC_n),2)] for i in range(len(FC_nn)): FC_nn[i]=FC_nn[i][0]*FC_nn[i][1] FC_nn=np.delete(FC_nn, indices2) FC=[[]*x for x in range(3)] FC[0].append(FC_neg[0]) FC[0].append([zero]) FC[0].append(FC_n[0]) FC[0]=[x for x in chain(*FC[0])] for i in range(1,n-1): FC[1].append(FC_neg[i]) FC[1].append(FC_n[i]) FC[1]=[x for x in chain(*FC[1])] FC[2]=FC_nn """Returned are two 3-dimensional lists. First inner list contains frequencies and FC-factors of vibrations exited with |1| quanta and the 0-0 transition. Second list contains frequencies and FC-factors from higher quanta exitations. Third list are combinations of two normal modes (including combinations of higher quanta exitations). """ return FC, frequencies python-ase-3.9.1.4567/ase/vibrations/raman.py0000664000175000017500000002324612553425526021105 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- """Resonant Raman intensities""" from __future__ import print_function import pickle import os import sys import numpy as np import ase.units as units from ase.parallel import rank, parprint, paropen from ase.vibrations import Vibrations from ase.utils.timing import Timer # XXX remove gpaw dependence from gpaw.output import get_txt class ResonantRaman(Vibrations): """Class for calculating vibrational modes and resonant Raman intensities using finite difference. atoms: Atoms object Excitations: Class to calculate the excitations. The class object is initialized as:: Excitations(atoms.get_calculator()) or by reading form a file as:: Excitations('filename', **exkwargs) The file is written by calling the method Excitations.write('filename'). """ def __init__(self, atoms, Excitations, indices=None, gsname='rraman', # name for ground state calculations exname=None, # name for excited state calculations delta=0.01, nfree=2, directions=None, exkwargs={}, # kwargs to be passed to Excitations txt='-'): assert(nfree == 2) Vibrations.__init__(self, atoms, indices, gsname, delta, nfree) self.name = gsname + '-d%.3f' % delta if exname is None: exname = gsname self.exname = exname + '-d%.3f' % delta if directions is None: self.directions = np.array([0, 1, 2]) else: self.directions = np.array(directions) self.exobj = Excitations self.exkwargs = exkwargs self.timer = Timer() self.txt = get_txt(txt, rank) def calculate(self, filename, fd): """Call ground and excited state calculation""" self.timer.start('Ground state') forces = self.atoms.get_forces() if rank == 0: pickle.dump(forces, fd) fd.close() self.timer.stop('Ground state') self.timer.start('Excitations') basename, _ = os.path.splitext(filename) excitations = self.exobj(self.atoms.get_calculator()) excitations.write(basename + '.excitations') self.timer.stop('Excitations') def get_intensity_tensor(self, omega, gamma=0.1): if not hasattr(self, 'modes'): self.read() if not hasattr(self, 'ex0'): eu = units.Hartree def get_me_tensor(exname, n, form='v'): def outer(ex): me = ex.get_dipole_me(form=form) return np.outer(me, me.conj()) ex_p = self.exobj(exname, **self.exkwargs) if len(ex_p) != n: raise RuntimeError( ('excitations {0} of wrong length: {1} != {2}' + ' exkwargs={3}').format( exname, len(ex_p), n, self.exkwargs)) m_ccp = np.empty((3, 3, len(ex_p)), dtype=complex) for p, ex in enumerate(ex_p): m_ccp[:, :, p] = outer(ex) return m_ccp self.timer.start('reading excitations') ex_p = self.exobj(self.exname + '.eq.excitations', **self.exkwargs) n = len(ex_p) self.ex0 = np.array([ex.energy * eu for ex in ex_p]) self.exminus = [] self.explus = [] for a in self.indices: for i in 'xyz': name = '%s.%d%s' % (self.exname, a, i) self.exminus.append(get_me_tensor( name + '-.excitations', n)) self.explus.append(get_me_tensor( name + '+.excitations', n)) self.timer.stop('reading excitations') self.timer.start('amplitudes') self.timer.start('init') ndof = 3 * len(self.indices) amplitudes = np.zeros((ndof, 3, 3), dtype=complex) pre = 1. / (2 * self.delta) self.timer.stop('init') def kappa(me_ccp, e_p, omega, gamma, form='v'): """Kappa tensor after Profeta and Mauri PRB 63 (2001) 245415""" result = (me_ccp / (e_p - omega - 1j * gamma) + me_ccp.conj() / (e_p + omega + 1j * gamma)) return result.sum(2) r = 0 for a in self.indices: for i in 'xyz': amplitudes[r] = pre * ( kappa(self.explus[r], self.ex0, omega, gamma) - kappa(self.exminus[r], self.ex0, omega, gamma)) r += 1 self.timer.stop('amplitudes') # map to modes am = np.dot(amplitudes.T, self.modes.T).T return omega**4 * (am * am.conj()).real def get_intensities(self, omega, gamma=0.1): return self.get_intensity_tensor(omega, gamma).sum(axis=1).sum(axis=1) def get_spectrum(self, omega, gamma=0.1, start=200, end=4000, npts=None, width=4, type='Gaussian', method='standard', direction='central', intensity_unit='????', normalize=False): """Get resonant Raman spectrum. The method returns wavenumbers in cm^-1 with corresponding absolute infrared intensity. Start and end point, and width of the Gaussian/Lorentzian should be given in cm^-1. normalize=True ensures the integral over the peaks to give the intensity. """ 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.get_intensities(omega, gamma) prefactor = 1 if type == 'lorentzian': intensities = intensities * width * np.pi / 2. if normalize: prefactor = 2. / width / np.pi else: sigma = width / 2. / np.sqrt(2. * np.log(2.)) if normalize: prefactor = 1. / sigma / np.sqrt(2 * np.pi) #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 / np.pi / ( (frequencies - energy)**2 + 0.25 * width**2)).sum() else: spectrum[i] = (intensities * np.exp(-(frequencies - energy)**2 / 2. / sigma**2)).sum() return [energies, prefactor * spectrum] def write_spectra(self, omega, gamma, out='resonant-raman-spectra.dat', start=200, end=4000, npts=None, width=10, type='Gaussian', method='standard', direction='central'): """Write out 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(omega, gamma, start, end, npts, width, type, method, direction) #Write out spectrum in file. First column is absolute intensities. outdata = np.empty([len(energies), 3]) outdata.T[0] = energies outdata.T[1] = spectrum fd = open(out, 'w') fd.write('# Resonat Raman spectrum\n') fd.write('# omega={0:g} eV, gamma={1:g} eV\n'.format(omega, gamma)) fd.write('# %s folded, width=%g cm^-1\n' % (type.title(), width)) fd.write('# [cm^-1] [a.u.]\n') for row in outdata: fd.write('%.3f %15.5g\n' % (row[0], row[1])) fd.close() def summary(self, omega, gamma=0.1, method='standard', direction='central', intensity_unit='(D/A)2/amu', log=sys.stdout): """Print summary for given omega [eV]""" hnu = self.get_energies(method, direction) s = 0.01 * units._e / units._c / units._hplanck intensities = self.get_intensities(omega, gamma) if isinstance(log, str): log = paropen(log, 'a') parprint('-------------------------------------', file=log) parprint(' excitation at ' + str(omega) + ' eV', file=log) parprint(' gamma ' + str(gamma) + ' eV\n', file=log) parprint(' Mode Frequency Intensity', file=log) parprint(' # meV cm^-1 [a.u.]', file=log) parprint('-------------------------------------', file=log) for n, e in enumerate(hnu): if e.imag != 0: c = 'i' e = e.imag else: c = ' ' e = e.real parprint('%3d %6.1f%s %7.1f%s %9.3g' % (n, 1000 * e, c, s * e, c, intensities[n]), file=log) parprint('-------------------------------------', file=log) parprint('Zero-point energy: %.3f eV' % self.get_zero_point_energy(), file=log) def __del__(self): self.timer.write(self.txt) python-ase-3.9.1.4567/ase/infrared.py0000664000175000017500000000005112553425527017407 0ustar jensjjensj00000000000000from vibrations.infrared import InfraRed python-ase-3.9.1.4567/ase/all.py0000664000175000017500000000242512553425527016374 0ustar jensjjensj00000000000000"""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 Trajectory 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.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.structure import * #from ase.lattice import bulk from math import pi, sqrt import numpy as np python-ase-3.9.1.4567/ase/test/0000775000175000017500000000000012553427753016231 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/fio/0000775000175000017500000000000012553427753017006 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/fio/__init__.py0000664000175000017500000000000012553425527021102 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/fio/extxyz.py0000664000175000017500000000161512553425550020727 0ustar jensjjensj00000000000000# additional tests of the extended XYZ file I/O # (which is also included in oi.py test case) # maintainted by James Kermode import os import numpy as np import ase.io from ase.lattice import bulk # array data of shape (N, 1) squeezed down to shape (N, ) -- bug fixed in commit r4541 at = bulk('Si') ase.io.write('to.extxyz', at) at.arrays['ns_extra_data'] = np.zeros( (len(at), 1) ) assert at.arrays["ns_extra_data"].shape == (2, 1) ase.io.write('to_new.extxyz', at) at_new = ase.io.read('to_new.extxyz') assert at_new.arrays["ns_extra_data"].shape == (2, ) os.unlink('to.extxyz') os.unlink('to_new.extxyz') # write sequence of images with different numbers of atoms -- bug fixed in commit r4542 images = [at, at*(2, 1, 1), at*(3, 1, 1) ] ase.io.write('multi.extxyz', images) read_images = ase.io.read('multi.extxyz@:') assert read_images == images os.unlink('multi.extxyz') python-ase-3.9.1.4567/ase/test/fio/netcdftrajectory.py0000664000175000017500000000512512553425527022732 0ustar jensjjensj00000000000000from ase.test import NotAvailable import ase.io.netcdftrajectory as netcdftrajectory if not netcdftrajectory.have_nc: raise NotAvailable('No NetCDF module available (netCDF4-python, ' 'scipy.io.netcdf)') import os from ase import Atom, Atoms from ase.io import NetCDFTrajectory co = Atoms([Atom('C', (0, 0, 0)), Atom('O', (0, 0, 1.2))], pbc=True) traj = NetCDFTrajectory('1.nc', 'w', co) for i in range(5): co.positions[:, 2] += 0.1 traj.write() del traj if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4: traj = NetCDFTrajectory('1.nc', 'a') co = traj[-1] print(co.positions) co.positions[:] += 1 traj.write(co) del traj t = NetCDFTrajectory('1.nc', 'a') else: t = NetCDFTrajectory('1.nc', 'r') print(t[-1].positions) print('.--------') for i, a in enumerate(t): if i < 4: print(1, a.positions[-1, 2], 1.3 + i * 0.1) assert abs(a.positions[-1, 2] - 1.3 - i * 0.1) < 1e-6 assert a.pbc.all() else: print(1, a.positions[-1, 2], 1.7 + i - 4) assert abs(a.positions[-1, 2] - 1.7 - i + 4) < 1e-6 assert a.pbc.all() if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4: co.positions[:] += 1 t.write(co) for i, a in enumerate(t): if i < 4: print(2, a.positions[-1, 2], 1.3 + i * 0.1) assert abs(a.positions[-1, 2] - 1.3 - i * 0.1) < 1e-6 else: print(2, a.positions[-1, 2], 1.7 + i - 4) assert abs(a.positions[-1, 2] - 1.7 - i + 4) < 1e-6 assert len(t) == 7 else: assert len(t) == 5 # Change atom type and append co[0].number = 1 t.write(co) t2 = NetCDFTrajectory('1.nc', 'r') co2 = t2[-1] assert (co2.numbers == co.numbers).all() del t2 if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4: co[0].number = 6 co.pbc = True t.write(co) co.pbc = False o = co.pop(1) try: t.write(co) except ValueError: pass else: assert False co.append(o) co.pbc = True t.write(co) del t # append to a nonexisting file if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4: fname = '2.nc' if os.path.isfile(fname): os.remove(fname) t = NetCDFTrajectory(fname, 'a', co) del t fname = '3.nc' t = NetCDFTrajectory(fname, 'w', co) # File is not created before first write co.set_pbc([True, False, False]) d = co.get_distance(0, 1) t.write(co) del t # Check pbc t = NetCDFTrajectory(fname) a = t[-1] assert a.pbc[0] and not a.pbc[1] and not a.pbc[2] assert abs(a.get_distance(0, 1) - d) < 1e-6 del t os.remove(fname) python-ase-3.9.1.4567/ase/test/fio/magmom.py0000664000175000017500000000050612553425527020633 0ustar jensjjensj00000000000000from ase import Atoms from ase.io import read, write atoms = Atoms('HH', [[.0,.0,.0], [.0,.0,.74]], pbc=True, cell=[5, 5, 5]) atoms.set_initial_magnetic_moments([1, -1]) moms = atoms.get_initial_magnetic_moments() write('test.traj',atoms) atoms = read('test.traj') assert (atoms.get_initial_magnetic_moments() == moms).all() python-ase-3.9.1.4567/ase/test/fio/res.py0000664000175000017500000003060412553425527020151 0ustar jensjjensj00000000000000#!/usr/bin/env python import os from ase.atoms import Atoms from ase.calculators.singlepoint import SinglePointCalculator from ase.io.res import * test_res = """ TITL 23221-ZDsSsJoEW14-3 -2.7839600000000004 1 -31005.480500000001 0 0 254 (P1) n - 1 CELL 1.0 33.998511000000001 19.938282999999998 6.7999999999999998 90 90 89.981431000000001 LATT -1 SFAC C H H 2 0.419886000 0.142864000 0.243969000 1.0 H 2 0.449139000 0.135683000 0.670836000 1.0 H 2 0.284474000 0.165357000 0.236375000 1.0 H 2 0.326693000 0.119478000 0.609186000 1.0 H 2 0.09748500 0.08739500 0.484880000 1.0 H 2 0.02442900 0.08613700 0.524346000 1.0 H 2 0.198055000 0.153611000 0.757328000 1.0 H 2 0.175429000 0.133959000 0.325265000 1.0 H 2 0.398735000 0.09679800 0.440684000 1.0 H 2 0.471401000 0.09914900 0.463208000 1.0 H 2 0.266722000 0.108997000 0.413839000 1.0 H 2 0.339879000 0.104829000 0.360835000 1.0 H 2 0.07338100 0.131550000 0.294675000 1.0 H 2 0.04794100 0.124129000 0.727225000 1.0 H 2 0.225211000 0.105804000 0.585777000 1.0 H 2 0.152409000 0.09545300 0.529334000 1.0 H 2 0.483562000 0.846988000 0.185931000 1.0 H 2 0.412203000 0.881051000 0.503357000 1.0 H 2 0.334140000 0.872886000 0.548314000 1.0 H 2 0.04479200 0.837706000 0.669058000 1.0 H 2 0.123455000 0.859052000 0.614144000 1.0 H 2 0.179423000 0.845556000 0.356632000 1.0 H 2 0.482063000 0.887844000 0.415000000 1.0 H 2 0.406955000 0.863603000 0.254068000 1.0 H 2 0.336814000 0.868085000 0.292107000 1.0 H 2 0.06542800 0.847667000 0.435941000 1.0 H 2 0.129674000 0.805885000 0.820551000 1.0 H 2 0.198388000 0.859228000 0.590843000 1.0 H 2 0.261362000 0.875683000 0.445400000 1.0 H 2 0.261638000 0.837239000 0.213067000 1.0 H 2 0.922430000 0.133381000 0.326458000 1.0 H 2 0.945221000 0.143541000 0.761125000 1.0 H 2 0.796117000 0.143497000 0.270665000 1.0 H 2 0.823422000 0.134958000 0.699562000 1.0 H 2 0.597937000 0.105913000 0.422276000 1.0 H 2 0.525383000 0.103158000 0.471170000 1.0 H 2 0.718676000 0.09931000 0.508464000 1.0 H 2 0.645826000 0.104835000 0.550140000 1.0 H 2 0.897235000 0.09693900 0.527122000 1.0 H 2 0.969022000 0.09324000 0.583187000 1.0 H 2 0.773836000 0.09751500 0.463093000 1.0 H 2 0.845975000 0.09728100 0.493986000 1.0 H 2 0.573655000 0.154922000 0.243396000 1.0 H 2 0.548290000 0.142797000 0.673915000 1.0 H 2 0.696822000 0.135939000 0.298545000 1.0 H 2 0.670484000 0.154425000 0.726137000 1.0 H 2 0.993967000 0.805476000 0.209721000 1.0 H 2 0.925002000 0.847111000 0.584177000 1.0 H 2 0.848353000 0.844978000 0.660109000 1.0 H 2 0.548459000 0.874976000 0.574384000 1.0 H 2 0.629129000 0.889040000 0.458485000 1.0 H 2 0.701418000 0.868349000 0.357223000 1.0 H 2 0.990692000 0.856777000 0.420401000 1.0 H 2 0.916085000 0.849572000 0.331757000 1.0 H 2 0.847830000 0.863225000 0.409754000 1.0 H 2 0.559835000 0.876727000 0.325807000 1.0 H 2 0.626500000 0.856782000 0.697646000 1.0 H 2 0.704670000 0.873144000 0.612507000 1.0 H 2 0.776989000 0.865351000 0.609983000 1.0 H 2 0.777771000 0.862294000 0.354035000 1.0 C 1 0.01794100 0.194517000 0.539562000 1.0 C 1 0.03913900 0.253871000 0.514899000 1.0 C 1 0.02459800 0.319523000 0.514860000 1.0 C 1 0.08047700 0.254851000 0.513051000 1.0 C 1 0.09390100 0.321005000 0.525070000 1.0 C 1 0.135544000 0.326265000 0.537909000 1.0 C 1 0.160118000 0.266948000 0.537269000 1.0 C 1 0.143168000 0.202253000 0.508563000 1.0 C 1 0.102721000 0.196410000 0.495795000 1.0 C 1 0.08016000 0.132766000 0.454453000 1.0 C 1 0.04134100 0.130791000 0.568495000 1.0 C 1 0.168324000 0.140886000 0.483336000 1.0 C 1 0.205677000 0.149395000 0.599179000 1.0 C 1 0.225390000 0.213268000 0.541040000 1.0 C 1 0.202924000 0.273399000 0.543543000 1.0 C 1 0.222717000 0.336658000 0.541106000 1.0 C 1 0.265722000 0.338220000 0.544351000 1.0 C 1 0.286146000 0.275315000 0.510965000 1.0 C 1 0.264627000 0.214628000 0.489721000 1.0 C 1 0.284365000 0.154659000 0.396444000 1.0 C 1 0.326395000 0.141923000 0.459913000 1.0 C 1 0.349834000 0.206050000 0.468495000 1.0 C 1 0.329052000 0.267406000 0.508318000 1.0 C 1 0.351096000 0.323391000 0.565284000 1.0 C 1 0.393102000 0.321771000 0.553431000 1.0 C 1 0.413186000 0.264423000 0.490903000 1.0 C 1 0.391056000 0.204937000 0.456991000 1.0 C 1 0.414597000 0.143259000 0.405011000 1.0 C 1 0.454381000 0.143030000 0.511205000 1.0 C 1 0.477501000 0.207590000 0.483482000 1.0 C 1 0.455793000 0.267949000 0.481510000 1.0 C 1 0.476229000 0.330977000 0.490515000 1.0 C 1 0.517927000 0.334708000 0.476110000 1.0 C 1 0.538971000 0.273269000 0.465467000 1.0 C 1 0.581176000 0.275318000 0.464382000 1.0 C 1 0.602425000 0.213636000 0.460758000 1.0 C 1 0.580370000 0.151600000 0.402822000 1.0 C 1 0.541989000 0.148064000 0.514347000 1.0 C 1 0.518444000 0.210779000 0.482198000 1.0 C 1 0.641824000 0.212664000 0.508219000 1.0 C 1 0.663763000 0.150242000 0.566920000 1.0 C 1 0.702588000 0.143874000 0.457599000 1.0 C 1 0.726468000 0.206767000 0.487713000 1.0 C 1 0.705521000 0.268832000 0.510616000 1.0 C 1 0.726720000 0.329679000 0.513874000 1.0 C 1 0.768508000 0.326543000 0.516794000 1.0 C 1 0.789560000 0.265699000 0.509986000 1.0 C 1 0.767597000 0.205421000 0.483013000 1.0 C 1 0.790573000 0.143396000 0.431567000 1.0 C 1 0.829573000 0.141851000 0.540459000 1.0 C 1 0.852990000 0.205809000 0.515729000 1.0 C 1 0.832248000 0.267723000 0.513436000 1.0 C 1 0.853934000 0.330250000 0.513810000 1.0 C 1 0.896612000 0.329331000 0.515192000 1.0 C 1 0.916234000 0.266229000 0.514897000 1.0 C 1 0.893705000 0.205356000 0.508679000 1.0 C 1 0.915210000 0.140161000 0.484505000 1.0 C 1 0.952772000 0.140428000 0.602463000 1.0 C 1 0.977331000 0.199804000 0.549262000 1.0 C 1 0.959053000 0.263208000 0.521439000 1.0 C 1 0.982836000 0.323414000 0.515000000 1.0 C 1 0.663404000 0.273466000 0.508025000 1.0 C 1 0.643457000 0.336491000 0.492667000 1.0 C 1 0.601415000 0.337627000 0.481582000 1.0 C 1 0.09613400 0.479995000 0.539265000 1.0 C 1 0.135896000 0.453141000 0.542245000 1.0 C 1 0.154500000 0.388296000 0.543473000 1.0 C 1 0.196896000 0.393408000 0.543828000 1.0 C 1 0.205657000 0.462762000 0.539655000 1.0 C 1 0.241364000 0.498860000 0.542657000 1.0 C 1 0.279121000 0.468631000 0.589891000 1.0 C 1 0.289883000 0.397780000 0.590070000 1.0 C 1 0.330855000 0.382727000 0.627307000 1.0 C 1 0.355317000 0.431754000 0.706274000 1.0 C 1 0.397022000 0.430985000 0.689661000 1.0 C 1 0.415866000 0.379639000 0.597475000 1.0 C 1 0.455416000 0.390709000 0.539969000 1.0 C 1 0.473164000 0.456528000 0.542346000 1.0 C 1 0.447730000 0.515284000 0.594838000 1.0 C 1 0.412433000 0.496298000 0.686780000 1.0 C 1 0.379001000 0.538334000 0.705783000 1.0 C 1 0.344264000 0.498496000 0.714088000 1.0 C 1 0.308706000 0.518284000 0.633411000 1.0 C 1 0.307240000 0.586831000 0.574246000 1.0 C 1 0.271443000 0.613497000 0.508288000 1.0 C 1 0.238141000 0.569912000 0.515445000 1.0 C 1 0.201204000 0.603510000 0.513332000 1.0 C 1 0.166253000 0.565735000 0.538533000 1.0 C 1 0.168848000 0.497096000 0.539230000 1.0 C 1 0.128660000 0.594729000 0.557453000 1.0 C 1 0.09402600 0.552572000 0.548038000 1.0 C 1 0.05757600 0.588352000 0.532770000 1.0 C 1 0.02152400 0.551578000 0.509056000 1.0 C 1 0.02048700 0.478858000 0.515228000 1.0 C 1 0.05851300 0.440042000 0.525788000 1.0 C 1 0.05888400 0.367680000 0.521406000 1.0 C 1 0.378536000 0.600675000 0.625366000 1.0 C 1 0.449475000 0.586932000 0.546085000 1.0 C 1 0.484310000 0.621585000 0.485403000 1.0 C 1 0.521296000 0.588152000 0.483997000 1.0 C 1 0.535536000 0.520951000 0.491653000 1.0 C 1 0.578664000 0.522255000 0.487048000 1.0 C 1 0.589538000 0.590300000 0.484659000 1.0 C 1 0.625482000 0.624676000 0.487672000 1.0 C 1 0.660699000 0.588479000 0.485887000 1.0 C 1 0.669402000 0.519599000 0.487599000 1.0 C 1 0.644748000 0.461151000 0.488946000 1.0 C 1 0.665196000 0.397748000 0.495207000 1.0 C 1 0.707365000 0.393348000 0.507693000 1.0 C 1 0.730917000 0.453181000 0.505280000 1.0 C 1 0.771816000 0.449346000 0.512143000 1.0 C 1 0.789813000 0.386183000 0.517783000 1.0 C 1 0.831256000 0.390806000 0.515080000 1.0 C 1 0.839385000 0.461422000 0.510979000 1.0 C 1 0.803229000 0.498721000 0.506717000 1.0 C 1 0.803046000 0.569184000 0.494652000 1.0 C 1 0.840663000 0.603268000 0.491666000 1.0 C 1 0.876373000 0.565370000 0.494733000 1.0 C 1 0.875832000 0.494281000 0.506735000 1.0 C 1 0.911563000 0.458087000 0.511290000 1.0 C 1 0.920912000 0.388659000 0.515311000 1.0 C 1 0.963362000 0.385116000 0.514150000 1.0 C 1 0.981113000 0.450779000 0.511755000 1.0 C 1 0.947657000 0.493847000 0.507161000 1.0 C 1 0.948852000 0.562366000 0.489902000 1.0 C 1 0.986523000 0.592473000 0.483853000 1.0 C 1 0.913107000 0.599703000 0.485384000 1.0 C 1 0.767622000 0.609578000 0.487796000 1.0 C 1 0.729166000 0.580335000 0.486762000 1.0 C 1 0.712088000 0.515526000 0.490898000 1.0 C 1 0.602087000 0.462219000 0.487277000 1.0 C 1 0.580271000 0.400158000 0.484177000 1.0 C 1 0.537581000 0.398662000 0.485171000 1.0 C 1 0.514602000 0.459384000 0.502213000 1.0 C 1 0.990939000 0.803735000 0.373410000 1.0 C 1 0.953580000 0.770110000 0.426145000 1.0 C 1 0.919118000 0.813418000 0.455956000 1.0 C 1 0.881770000 0.777151000 0.483940000 1.0 C 1 0.847096000 0.819629000 0.512592000 1.0 C 1 0.809644000 0.783435000 0.492531000 1.0 C 1 0.775342000 0.828788000 0.485485000 1.0 C 1 0.737479000 0.793289000 0.486370000 1.0 C 1 0.701834000 0.835982000 0.490995000 1.0 C 1 0.663877000 0.800103000 0.505701000 1.0 C 1 0.627655000 0.840784000 0.539693000 1.0 C 1 0.591383000 0.803037000 0.486762000 1.0 C 1 0.554733000 0.840652000 0.448253000 1.0 C 1 0.518891000 0.800524000 0.409871000 1.0 C 1 0.482917000 0.836989000 0.348107000 1.0 C 1 0.447079000 0.798463000 0.402285000 1.0 C 1 0.447920000 0.730820000 0.446717000 1.0 C 1 0.412942000 0.696106000 0.498425000 1.0 C 1 0.375825000 0.731701000 0.486834000 1.0 C 1 0.374259000 0.798522000 0.439397000 1.0 C 1 0.410117000 0.837760000 0.399457000 1.0 C 1 0.336384000 0.835680000 0.425650000 1.0 C 1 0.300964000 0.792387000 0.422190000 1.0 C 1 0.263011000 0.825530000 0.374205000 1.0 C 1 0.228873000 0.783388000 0.434272000 1.0 C 1 0.191879000 0.817881000 0.485715000 1.0 C 1 0.160643000 0.773960000 0.564103000 1.0 C 1 0.126050000 0.805850000 0.657127000 1.0 C 1 0.09056700 0.767672000 0.597612000 1.0 C 1 0.05630600 0.807865000 0.541752000 1.0 C 1 0.02436500 0.766728000 0.461523000 1.0 C 1 0.02330200 0.697908000 0.482438000 1.0 C 1 0.05729800 0.659846000 0.535401000 1.0 C 1 0.09144300 0.699123000 0.576601000 1.0 C 1 0.127749000 0.664359000 0.575836000 1.0 C 1 0.162179000 0.704817000 0.546855000 1.0 C 1 0.198453000 0.673358000 0.499095000 1.0 C 1 0.231773000 0.714679000 0.455751000 1.0 C 1 0.269070000 0.682171000 0.461557000 1.0 C 1 0.303211000 0.724424000 0.460036000 1.0 C 1 0.339999000 0.694453000 0.509757000 1.0 C 1 0.341334000 0.628677000 0.575314000 1.0 C 1 0.414614000 0.628788000 0.560270000 1.0 C 1 0.483592000 0.692141000 0.449201000 1.0 C 1 0.518732000 0.732106000 0.436492000 1.0 C 1 0.555089000 0.698529000 0.464888000 1.0 C 1 0.555016000 0.629689000 0.477655000 1.0 C 1 0.591384000 0.734166000 0.481431000 1.0 C 1 0.626381000 0.695017000 0.492822000 1.0 C 1 0.662628000 0.731573000 0.493304000 1.0 C 1 0.698206000 0.693358000 0.485021000 1.0 C 1 0.735934000 0.724332000 0.485093000 1.0 C 1 0.770097000 0.680802000 0.484874000 1.0 C 1 0.807458000 0.714133000 0.488127000 1.0 C 1 0.842410000 0.673725000 0.489316000 1.0 C 1 0.879581000 0.708390000 0.482618000 1.0 C 1 0.914733000 0.669363000 0.474005000 1.0 C 1 0.952018000 0.701703000 0.451744000 1.0 C 1 0.987402000 0.662138000 0.459246000 1.0 C 1 0.696482000 0.624775000 0.484183000 1.0 END """ filepath = 'test.res' f = open(filepath, 'w') f.write(test_res) f.close() res = Res.from_file(filepath) assert res.atoms.get_chemical_formula() == 'C194H60' #print res atoms = read_res(filepath) assert res.atoms == atoms assert res.energy == atoms.get_potential_energy() spc = SinglePointCalculator(atoms, energy=res.energy) atoms.set_calculator(spc) write_res('test2.res', atoms) atoms2 = read_res(filepath) assert atoms2 == atoms write_res('test3.res', atoms, write_info=False, significant_figures=9) atoms3 = read_res('test3.res') assert atoms3 == atoms res_string = """TITL CELL 1.0 1.0 1.0 1.0 90.0 90.0 90.0 LATT -1 SFAC Si F Si 1 0.000000 0.000000 0.000000 1.0 F 2 0.750000 0.500000 0.750000 1.0""" res = Res.from_string(res_string) assert res.atoms.get_chemical_formula() == 'FSi' assert len(res.atoms) == 2 #print res struct = Atoms(cell=[2.5, 3.5, 7.0], symbols=['Na', 'Cl'], positions=[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) res = Res(struct) res_string = str(res) lines = res_string.splitlines() assert lines[1] == 'CELL 1.0 2.500000 3.500000 7.000000 90.000000 90.000000 90.000000' os.unlink('test.res') os.unlink('test2.res') os.unlink('test3.res') python-ase-3.9.1.4567/ase/test/fio/netcdf.py0000664000175000017500000000116512553425527020623 0ustar jensjjensj00000000000000import numpy as np from ase.test import NotAvailable try: from scipy.io.netcdf import NetCDFFile except ImportError: raise NotAvailable('Scipy too old') # Write array a1 = np.random.rand(5, 5) a2 = a1 * 2 - 5 nc = NetCDFFile('test.nc', 'w') nc.createDimension('dimx', a1.shape[0]) nc.createDimension('dimy', a1.shape[1]) nc.createVariable('matrix1', 'd', ('dimx', 'dimy'))[:] = a1 nc.createVariable('matrix2', 'd', ('dimx', 'dimy'))[:] = a2 nc.sync() nc.close() # Read array nc = NetCDFFile('test.nc', 'r') b1 = nc.variables['matrix1'][:] b2 = nc.variables['matrix2'][:] assert np.all(a1 == b1) and np.all(a2 == b2) python-ase-3.9.1.4567/ase/test/fio/abinit.py0000664000175000017500000000146712553425527020633 0ustar jensjjensj00000000000000import numpy as np def array_almost_equal(a1, a2, tol=np.finfo(type(1.0)).eps): """Replacement for old numpy.testing.utils.array_almost_equal.""" return (np.abs(a1 - a2) < tol).all() # this test should be run with abinit! from ase.calculators.emt import EMT from ase.io import read, write from ase.structure import molecule m1 = molecule('O2', pbc=True) m1.center(2.0) write('abinit_save.in', images=m1, format='abinit') m1.set_calculator(EMT()) e1 = m1.get_potential_energy() f1 = m1.get_forces() m2 = read('abinit_save.in', format='abinit') m2.set_calculator(EMT()) e2 = m2.get_potential_energy() f2 = m1.get_forces() # assume atoms definitions are the same if energy/forces are the same: can we do better? assert abs(e1-e2) < 1.e-6, str(e1) + ' ' + str(e2) assert array_almost_equal(f1, f2, tol=1.e-6) python-ase-3.9.1.4567/ase/test/fio/info.py0000664000175000017500000000201012553425527020301 0ustar jensjjensj00000000000000from ase import Atoms from ase.io import Trajectory class Foo(object): def __init__(self, value): self.value = value def __cmp__(self, other): return int(self.value - other.value) if __name__ == '__main__': from . import info # import ourselves to make info.Foo reachable # Create a molecule with an info attribute info = dict(creation_date='2011-06-27', chemical_name='Hydrogen', # custom classes also works provided that it is # imported and pickleable... foo=info.Foo(7), ) molecule = Atoms('H2', positions=[(0., 0., 0.), (0., 0., 1.1)], info=info) assert molecule.info == info # Copy molecule atoms = molecule.copy() assert atoms.info == info # Save molecule to trajectory traj = Trajectory('info.traj', 'w', atoms=molecule) traj.write() del traj # Load molecule from trajectory t = Trajectory('info.traj') atoms = t[-1] assert atoms.info == info python-ase-3.9.1.4567/ase/test/fio/oldtraj.py0000664000175000017500000000307612553425527021022 0ustar jensjjensj00000000000000"""Check that we can read old version 1 Trajectories.""" import functools import pickle import sys from io import BytesIO from ase import Atoms from ase.constraints import FixAtoms from ase.io.pickletrajectory import PickleTrajectory from ase.test import NotAvailable if sys.version_info[0] == 3: raise NotAvailable Trajectory = functools.partial(PickleTrajectory, _warn=False) a = Atoms('FOO') def v1(a): """Create old version-1 trajectory.""" fd = BytesIO() fd.write(b'PickleTrajectory') d = {'pbc': a.pbc, 'numbers': a.numbers, 'tags': None, 'masses': None, 'constraints': a.constraints} pickle.dump(d, fd, protocol=-1) d = {'positions': a.positions, 'cell': a.cell, 'momenta': None} pickle.dump(d, fd, protocol=-1) return BytesIO(fd.getvalue()) def v2(a): """Create new version-2 trajectory.""" fd = BytesIO() t = Trajectory(fd, 'w') t.write(a) return BytesIO(fd.getvalue()) class MyFixAtoms(FixAtoms): pass a.constraints = FixAtoms(indices=[2]) t1 = v1(a) t2 = v2(a) # Read old trajectory: c1 = Trajectory(t1)[0].constraints assert c1[0].index[0] == 2 # Read new trajectory: c2 = Trajectory(t2)[0].constraints assert c2[0].index[0] == 2 a.constraints = MyFixAtoms(indices=[1]) t3 = v2(a) # Read new trajectory with missing constraint class. This should # ignore the constraint and issue a warning: del MyFixAtoms, a import warnings warnings.filterwarnings('error') try: c3 = Trajectory(t3)[0].constraints except UserWarning: pass else: assert False python-ase-3.9.1.4567/ase/test/fio/oi.py0000664000175000017500000000676012553425527017775 0ustar jensjjensj00000000000000from __future__ import print_function import sys import numpy as np from ase import Atoms from ase.io import write, read from ase.calculators.singlepoint import SinglePointCalculator a = 5.0 d = 1.9 c = a / 2 atoms = Atoms('AuH', positions=[(c, c, 0), (c, c, d)], cell=(a, a, 2 * d), pbc=(0, 0, 1)) extra = np.array([2.3, 4.2]) atoms.set_array('extra', extra) atoms *= (1, 1, 2) images = [atoms.copy(), atoms.copy()] r = ['xyz', 'traj', 'cube', 'pdb', 'cfg', 'struct', 'cif', 'gen', 'extxyz', 'res'] # attach some results to the Atoms. These are serialised by the extxyz writer. spc = SinglePointCalculator(atoms, energy=-1.0, stress=[1.0, 2.0, 3.0, 4.0, 5.0, 6.0], forces=-1.0*atoms.get_positions()) atoms.set_calculator(spc) try: import json except ImportError: pass else: r += ['json', 'db'] try: import Scientific version = Scientific.__version__.split('.') print('Found ScientificPython version: ', Scientific.__version__) if list(map(int, version)) < [2, 8]: print('ScientificPython 2.8 or greater required for numpy support') raise ImportError except ImportError: print('No Scientific python found. Check your PYTHONPATH') else: r += ['etsf'] w = r + ['xsf', 'findsym'] try: import matplotlib except ImportError: pass else: w += ['png', 'eps'] if sys.version_info[0] == 3: r.remove('cif') only_one_image = ['cube', 'png', 'eps', 'cfg', 'struct', 'etsf', 'gen', 'json', 'db', 'res'] for format in w: print(format, 'O', end=' ') fname1 = 'io-test.1.' + format fname2 = 'io-test.2.' + format if format == 'xsf': # The xsf format supports only pbc=000, 100, 110, or 111. # No crazy ideas like 001. So let's try all the combinations # writing all the files on top of each other. atoms1 = atoms.copy() for pbc in [1, 0, 0], [1, 1, 0], [1, 1, 1]: atoms1.pbc = pbc images1 = [atoms1] * 2 write(fname2, images1, format='xsf') atoms2 = read(fname2) else: write(fname1, atoms, format=format) if format not in only_one_image: write(fname2, images, format=format) if format in r: print('I') a1 = read(fname1) assert np.all(np.abs(a1.get_positions() - atoms.get_positions()) < 1e-6) if format in ['traj', 'cube', 'cfg', 'struct', 'gen', 'extxyz']: assert np.all(np.abs(a1.get_cell() - atoms.get_cell()) < 1e-6) if format in ['cfg', 'extxyz']: assert np.all(np.abs(a1.get_array('extra') - atoms.get_array('extra')) < 1e-6) if format in ['extxyz']: assert np.all(a1.get_pbc() == atoms.get_pbc()) assert np.all(a1.get_potential_energy() == atoms.get_potential_energy()) assert np.all(a1.get_stress() == atoms.get_stress()) assert np.all(abs(a1.get_forces() - atoms.get_forces()) < 1e-6) if format not in only_one_image: a2 = read(fname2) a3 = read(fname2, index=0) a4 = read(fname2, index=slice(None)) if format in ['cif'] and sys.platform in ['win32']: # Fails on Windows: # https://trac.fysik.dtu.dk/projects/ase/ticket/62 pass else: assert len(a4) == 2 else: print() python-ase-3.9.1.4567/ase/test/fio/v_sim.py0000664000175000017500000000103412553425527020470 0ustar jensjjensj00000000000000try: from urllib.request import urlretrieve from urllib.error import URLError except ImportError: from urllib import urlretrieve from urllib2 import URLError from socket import error as SocketError from ase.test import NotAvailable from ase.io import read raise NotAvailable dest = 'demo.ascii' src = 'http://inac.cea.fr/L_Sim/V_Sim/files/' + dest try: urlretrieve(src, filename=dest) except (IOError, URLError, SocketError): raise NotAvailable('Retrieval of ' + src + ' failed') a = read(dest, format='v_sim') python-ase-3.9.1.4567/ase/test/fio/nwchem.py0000664000175000017500000000056512553425527020644 0ustar jensjjensj00000000000000"""Checks that writing and reading of NWChem input files is consistent.""" from ase.structure import molecule from ase.calculators.nwchem import NWChem from ase import io atoms = molecule('CH3COOH') calc = NWChem() calc.write_input(atoms) atoms2 = io.read('nwchem.nw') tol = 1e-8 check = sum(abs((atoms.positions - atoms2.positions).ravel()) > tol) assert check == 0 python-ase-3.9.1.4567/ase/test/fio/cfg.py0000664000175000017500000000037612553425527020122 0ustar jensjjensj00000000000000import numpy as np from ase.structure import molecule from ase.io import read, write a = molecule('CO2') f = np.array([[1,2,3],[4,5,6],[7,8,9]]) a.set_array('test', f) write('test.cfg', a) b = read('test.cfg') assert np.all(b.get_array('test') == f) python-ase-3.9.1.4567/ase/test/fio/trajectory.py0000664000175000017500000000352212553425550021541 0ustar jensjjensj00000000000000import sys from ase.test import NotAvailable, must_raise if sys.platform in ['win32']: raise NotAvailable('Fails on Windows ' 'https://trac.fysik.dtu.dk/projects/ase/ticket/62') import os from ase import Atom, Atoms from ase.io import Trajectory, read from ase.constraints import FixBondLength co = Atoms([Atom('C', (0, 0, 0)), Atom('O', (0, 0, 1.2))]) traj = Trajectory('1.traj', 'w', co) for i in range(5): co.positions[:, 2] += 0.1 traj.write() traj = Trajectory('1.traj', 'a') co = read('1.traj') print(co.positions) co.positions[:] += 1 traj.write(co) for a in Trajectory('1.traj'): print(1, a.positions[-1, 2]) co.positions[:] += 1 t = Trajectory('1.traj', 'a') t.write(co) assert len(t) == 7 co[0].number = 1 with must_raise(ValueError): t.write(co) co[0].number = 6 co.pbc = True with must_raise(ValueError): t.write(co) co.pbc = False o = co.pop(1) with must_raise(ValueError): t.write(co) co.append(o) t.write(co) # append to a nonexisting file: fname = '2.traj' if os.path.isfile(fname): os.remove(fname) t = Trajectory(fname, 'a', co) os.remove(fname) t = Trajectory('empty.traj', 'w') t.close() assert os.path.getsize('empty.traj') == 0 t = Trajectory('fake.traj', 'w') t.write(Atoms('H'), energy=-42.0, forces=[[1, 2, 3]]) t = Trajectory('only-energy.traj', 'w', properties=['energy']) a = read('fake.traj') t.write(a) b = read('only-energy.traj') e = b.get_potential_energy() assert e + 42 == 0 with must_raise(NotImplementedError): f = b.get_forces() # Make sure constraints play well with momenta: a = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1)], momenta=[(1, 0, 0), (0, 0, 0)]) a.constraints = [FixBondLength(0, 1)] t = Trajectory('constraint.traj', 'w', a) t.write() b = read('constraint.traj') assert not (b.get_momenta() - a.get_momenta()).any() python-ase-3.9.1.4567/ase/test/coverage.py0000664000175000017500000000007612553425527020376 0ustar jensjjensj00000000000000from ase import Atoms print(Atoms()) print(Atoms('H2O')) #... python-ase-3.9.1.4567/ase/test/dftb/0000775000175000017500000000000012553427753017150 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/dftb/__init__.py0000664000175000017500000000051712553425527021261 0ustar jensjjensj00000000000000def installed(): import os from ase.test import NotAvailable dcmd = os.getenv('DFTB_COMMAND') dpre = os.getenv('DFTB_PREFIX') if dcmd == None: raise NotAvailable('DFTB_COMMAND not defined') if dpre == None: raise NotAvailable('DFTB_PREFIX not defined (for slater koster files)') return True python-ase-3.9.1.4567/ase/test/dftb/test_tricky.py0000775000175000017500000000400412553425527022064 0ustar jensjjensj00000000000000""" test run for DFTB+ calculator the tolerance is extremely loose, beause different sk files give different results """ from ase.test.dftb import installed assert installed() from ase import Atoms from ase.visualize import view from ase.calculators.dftb import Dftb from ase.constraints import FixAtoms from ase.optimize import QuasiNewton from ase.lattice.surface import * from ase.lattice.surface import add_adsorbate import os, sys h = 1.85 d = 1.10 slab = fcc111('Ni', size=(2,2,3), vacuum=10.0) calc1=\ Dftb(label='slab', kpts=[2,2,1], Hamiltonian_MaxAngularMomentum_ = '', Hamiltonian_MaxAngularMomentum_Ni = '"d"', Hamiltonian_SCC='YES' ) slab.set_calculator(calc1) dyn = QuasiNewton(slab, trajectory='slab.traj') dyn.run(fmax=0.05) e_slab = slab.get_potential_energy() os.system('rm dftb_in.hsd') molecule = Atoms('2N', positions=[(0., 0., 0.), (0., 0., d)]) calc2=\ Dftb(label='n2', Hamiltonian_MaxAngularMomentum_ = '', Hamiltonian_MaxAngularMomentum_N = '"p"', Hamiltonian_SCC='YES' ) molecule.set_calculator(calc2) dyn = QuasiNewton(molecule, trajectory='n2.traj') dyn.run(fmax=0.05) e_N2 = molecule.get_potential_energy() slab2 = slab add_adsorbate(slab2, molecule, h, 'ontop') constraint = FixAtoms(mask=[a.symbol != 'N' for a in slab2]) slab2.set_constraint(constraint) calc3=\ Dftb(label='slab2', kpts=[2,2,1], Hamiltonian_MaxAngularMomentum_ = '', Hamiltonian_MaxAngularMomentum_N = '"p"', Hamiltonian_MaxAngularMomentum_Ni = '"d"', Hamiltonian_SCC='YES' ) slab2.set_calculator(calc3) dyn = QuasiNewton(slab2, trajectory='slab2.traj') dyn.run(fmax=0.05) adsorption_energy = e_slab + e_N2 - slab2.get_potential_energy() assert abs(adsorption_energy + 0.4227415) < 0.3 files = ['band.out', 'detailed.out', 'dftb_in.hsd', 'dftb_pin.hsd', \ 'geo_end.gen', 'geo_end.xyz', 'results.tag', \ 'n2.traj', 'n2.traj.bak', 'n2.out', \ 'slab.traj', 'slab.traj.bak', 'slab.out', \ 'slab2.traj', 'slab2.traj.bak', 'slab2.out' \ ] for file in files: try: os.remove(file) except OSError: pass python-ase-3.9.1.4567/ase/test/dftb/test_simple.py0000775000175000017500000000176612553425527022064 0ustar jensjjensj00000000000000""" test run for DFTB+ calculator the tolerance is extremely loose, beause different sk files give different results """ from ase.test.dftb import installed assert installed() from ase.calculators.dftb import Dftb import os from ase.optimize import QuasiNewton from ase.structure import molecule test = molecule('H2O') test.set_calculator(Dftb(label='h2o', atoms=test, Hamiltonian_MaxAngularMomentum_='', Hamiltonian_MaxAngularMomentum_O='"p"', Hamiltonian_MaxAngularMomentum_H='"s"', )) dyn = QuasiNewton(test, trajectory='test.traj') dyn.run(fmax=0.01) final_energy = test.get_potential_energy() assert abs(final_energy + 111.141945) < 1.0 files = ['band.out', 'detailed.out', 'dftb_in.hsd', 'dftb_pin.hsd', 'geo_end.gen', 'geo_end.xyz', 'h2o.out', 'results.tag', 'test.traj', 'test.traj.bak'] for file in files: try: os.remove(file) except OSError: pass python-ase-3.9.1.4567/ase/test/aims/0000775000175000017500000000000012553427753017162 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/aims/__init__.py0000664000175000017500000000000012553425527021256 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/aims/H2O_aims.py0000664000175000017500000000132512553425527021133 0ustar jensjjensj00000000000000import os from ase import Atoms from ase.calculators.aims import Aims, AimsCube from ase.optimize import QuasiNewton water = Atoms('HOH', [(1, 0, 0), (0, 0, 0), (0, 1, 0)]) water_cube = AimsCube(points=(29, 29, 29), plots=('total_density', 'delta_density', 'eigenstate 5', 'eigenstate 6')) calc=Aims(xc='PBE', output=['dipole'], sc_accuracy_etot=1e-6, sc_accuracy_eev=1e-3, sc_accuracy_rho=1e-6, sc_accuracy_forces=1e-4, cubes=water_cube) water.set_calculator(calc) dynamics = QuasiNewton(water,trajectory='square_water.traj') dynamics.run(fmax=0.01) python-ase-3.9.1.4567/ase/test/aims/aims_cmdline.py0000664000175000017500000000044612553425527022161 0ustar jensjjensj00000000000000from ase.test import cli, require require('aims') # warning! parameters are not converged - only an illustration! cli("""ase-build -x bcc -a 3.6 Li | \ ase-run aims -s 0.3 -p \ kpts=1.5,xc=LDA,sc_accuracy_rho=5.e-2,relativistic=none,compute_analytical_stress=True,sc_accuracy_forces=5.e-1""") python-ase-3.9.1.4567/ase/test/emt_h3o2m.py0000664000175000017500000000406012553425527020375 0ustar jensjjensj00000000000000from math import radians, sin, cos from ase import Atom, Atoms from ase.neb import NEB from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.optimize import QuasiNewton, BFGS from ase.visualize import view # http://jcp.aip.org/resource/1/jcpsa6/v97/i10/p7507_s1 doo = 2.74 doht = 0.957 doh = 0.977 angle = radians(104.5) initial = Atoms('HOHOH', positions=[(- sin(angle)*doht, 0., cos(angle)*doht), (0., 0., 0.), (0., 0., doh), (0., 0., doo), (sin(angle)*doht, 0., doo - cos(angle)*doht)]) if 0: view(initial) final = Atoms('HOHOH', positions=[(- sin(angle)*doht, 0., cos(angle)*doht), (0., 0., 0.), (0., 0., doo - doh), (0., 0., doo), (sin(angle)*doht, 0., doo - cos(angle)*doht)]) if 0: view(final) # Make band: images = [initial.copy()] for i in range(3): images.append(initial.copy()) images.append(final.copy()) neb = NEB(images, climb=True) # Set constraints and calculator: constraint = FixAtoms(indices=[1, 3]) # fix OO for image in images: image.set_calculator(EMT()) image.set_constraint(constraint) for image in images: # O-H(shared) distance print(image.get_distance(1, 2), image.get_potential_energy()) # Relax initial and final states: if 1: # XXX: Warning: # One would have to optimize more tightly in order to get # symmetric anion from both images[0] and [1], but # if one optimizes tightly one gets rotated(H2O) ... OH- instead dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.01) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.01) # Interpolate positions between initial and final states: neb.interpolate() for image in images: print(image.get_distance(1, 2), image.get_potential_energy()) dyn = BFGS(neb, trajectory='emt_h3o2m.traj') dyn.run(fmax=0.05) for image in images: print(image.get_distance(1, 2), image.get_potential_energy()) python-ase-3.9.1.4567/ase/test/aff.py0000664000175000017500000000156612553425527017344 0ustar jensjjensj00000000000000from __future__ import print_function import numpy as np from ase.io.aff import affopen as open class A: def write(self, writer): writer.write(x=np.ones((2, 3))) @staticmethod def read(reader): a = A() a.x = reader.x return a w = open('a.aff', 'w') w.write(a=A(), y=9) w.write(s='abc') w.sync() w.write(s='abc2') w.sync() w.write(s='abc3', z=np.ones(7, int)) w.close() print(w.data) r = open('a.aff') print(r.y, r.s) print(A.read(r.a).x) print(r.a.x) print(r[1].s) print(r[2].s) print(r[2].z) w = open('a.aff', 'a') print(w.nitems, w.offsets) w.write(d={'h': [1, 'asdf']}) w.add_array('psi', (4, 3)) w.fill(np.ones((1, 3))) w.fill(np.ones((1, 3)) * 2) w.fill(np.ones((2, 3)) * 3) w.close() print(open('a.aff', 'r', 3).d) print(open('a.aff')[2].z) print(open('a.aff', index=3).proxy('psi')[0:3]) for d in open('a.aff'): print(d) python-ase-3.9.1.4567/ase/test/minimahop.py0000664000175000017500000000203512553425527020561 0ustar jensjjensj00000000000000from ase import Atoms, Atom from ase.lattice.surface import fcc110 from ase.optimize.minimahopping import MinimaHopping from ase.calculators.emt import EMT from ase.constraints import FixAtoms, Hookean # Make the Pt 110 slab. atoms = fcc110('Pt', (2, 2, 2), vacuum=7.) # Add the Cu2 adsorbate. adsorbate = Atoms([Atom('Cu', atoms[7].position + (0., 0., 2.5)), Atom('Cu', atoms[7].position + (0., 0., 5.0))]) atoms.extend(adsorbate) # Constrain the surface to be fixed and a Hookean constraint between # the adsorbate atoms. constraints = [FixAtoms(indices=[atom.index for atom in atoms if atom.symbol == 'Pt']), Hookean(a1=8, a2=9, rt=2.6, k=15.), Hookean(a1=8, a2=(0., 0., 1., -15.), k=15.)] atoms.set_constraint(constraints) # Set the calculator. calc = EMT() atoms.set_calculator(calc) # Instantiate and run the minima hopping algorithm. hop = MinimaHopping(atoms, Ediff0=2.5, T0=2000.) hop(totalsteps=3) hop(maxtemp=3000) python-ase-3.9.1.4567/ase/test/eos.py0000664000175000017500000001404712553425527017374 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- # test ASE3 eos vs ASE2' on EMT Al bulk import numpy as np from ase.test import NotAvailable try: import scipy except ImportError: raise NotAvailable('This needs scipy module.') from ase.lattice import bulk from ase.io.trajectory import Trajectory from ase.calculators.emt import EMT # old ASE2 conversion factor eVA3ToGPA = 160.21773 ref = { 'volumes': [29.205536, 30.581492, 32.000000, 33.461708, 34.967264], 'energies': [0.0190898, -0.0031172, -0.0096925, -0.0004014, 0.0235753], # name: (V0 A**3, E0 eV, B eV/A**3) # ASE2: ScientificPython 2.6.2/Numeric 24.2 'Taylor': (31.896496488942326, -0.0096090164907389405, 0.23802461480382878), 'Murnaghan': (31.866877784374836, -0.0096119194044206324, 0.24202636566649313), 'Birch': (31.866809942501359, -0.0096161509968013953, 0.24231157506701367), 'BirchMurnaghan': (31.867394584147391, -0.009609309015137282, 0.23891301754324207), 'PourierTarantola': (31.866473067615818, -0.009599545236557528, 0.24120474301680481), 'Vinet': (31.866741599224699, -0.0096110298949974356, 0.24196956466978184), 'AntonSchmidt': (31.745672779210317, 0.012772723347888704, 0.19905185689855259), # ASE3: scipy 0.7.0/numpy 1.3.0 'sjeos': (31.867118229937798, -0.0096410046694188622, 0.23984474782755572), # 'taylor': (31.867114798134253, -0.0096606904384420791, 0.24112293515031302), 'murnaghan': (31.866729811658402, -0.0096340233039666941, 0.23937322901028654), 'birch': (31.867567845123162, -0.0096525305272843597, 0.24062224387079953), 'birchmurnaghan': (31.866655489091499, -0.0096461024146103497, 0.24016191590912808), 'pouriertarantola': (31.866750629512403, -0.0096361387118443446, 0.23951298910150925), 'vinet': (31.866655146818957, -0.0096368465365208426, 0.23955684756879458), 'p3': (31.867115199307815, -0.0096606897797322233, 0.24112291100256208), } # original ASE2 methods eos_strl = [ 'Taylor', 'Murnaghan', 'Birch', 'BirchMurnaghan', 'PourierTarantola', 'Vinet', 'AntonSchmidt', ] # AntonSchmidt fails with ASE3! # RuntimeError: Optimal parameters not found: # Number of calls to function has reached maxfev = 1000. eos_strl3 = [m for m in eos_strl] eos_strl3.remove('AntonSchmidt') results = {} # prepare energies and volumes b = bulk('Al', 'fcc', a=4.0, orthorhombic=True) b.set_calculator(EMT()) cell = b.get_cell() volumes = [] energies = [] traj = Trajectory('eos.traj', 'w') for x in np.linspace(0.97, 1.03, 5): b.set_cell(cell * x, scale_atoms=True) volumes.append(b.get_volume()) energies.append(b.get_potential_energy()) traj.write(b) for n, (v, e) in enumerate(zip(volumes, energies)): vref = ref['volumes'][n] eref = ref['energies'][n] vabserr = abs((v - vref) / vref) vstrerr = str(n) + ' volume: ' + str(v) + ': ' + str(vref) + ': ' + str(vabserr) assert vabserr < 1.e-6, vstrerr eabserr = abs((e - eref) / eref) estrerr = str(n) + ' energy: ' + str(e) + ': ' + str(eref) + ': ' + str(eabserr) assert eabserr < 1.e-4, estrerr # ASE2 try: from ASE.Utilities.EquationOfState import EquationOfState as eos2 import sys from ase.utils import devnull for e in eos_strl: eos = eos2(e, volumes, energies) stdout_save = sys.stdout sys.stdout = devnull print(eos) results[e] = (eos.GetV0(), eos.GetEnergy(), eos.GetBulkModulus()/eVA3ToGPA) sys.stdout = stdout_save except (ImportError, TypeError, ValueError): # TypeError, ValueError may appear with weird numeric/numpy/scientificpython pass # ASE3 from ase.utils.eos import EquationOfState as eos3 for e in eos_strl3 + ['sjeos', 'p3']: eos = eos3(volumes, energies, eos=e.lower()) v0, e0, B = eos.fit() results[e.lower()] = (v0, e0, B) # test ASE2 vs ASE2 regression (if available) for e in eos_strl: for n, v2 in enumerate(ref[e]): if n in [0, 2]: # only test volume and bulk modulus try: v3 = results[e][n] abserr = abs((v3 - v2) / v2) #print e, abserr strerr = e + ' 2 vs 2: ' + str(v3) + ': ' + str(v2) + ': ' + str(abserr) assert abserr < 1.e-6, strerr except KeyError: pass # test ASE3 vs ASE3 regression for e in eos_strl3: for n, v2 in enumerate(ref[e.lower()]): if n in [0, 2]: # only test volume and bulk modulus v3 = results[e.lower()][n] abserr = abs((v3 - v2) / v2) #print e, abserr strerr = e + ' 3 vs 3: ' + str(v3) + ': ' + str(v2) + ': ' + str(abserr) assert abserr < 5.e-6, strerr # test ASE3 vs ASE2 reference for e in eos_strl3: for n, v2 in enumerate(ref[e]): if n in [0, 2]: # only test volume and bulk modulus v3 = results[e.lower()][n] abserr = abs((v3 - v2) / v2) #print e, abserr strerr = e + ' 3 vs 2: ' + str(v3) + ': ' + str(v2) + ': ' + str(abserr) if n == 0: # volume assert abserr < 1.e-3, strerr else: # ASE2/ScientificPython/Numeric vs ASE2 methods/scipy/numpy error ~1% for bulk modulus! assert abserr < 2.e-2, strerr # test ASE3: various eos between each other for e1 in eos_strl3: for e2 in eos_strl3: for n, v2 in enumerate(ref[e1.lower()]): if n in [0, 2]: # only test volume and bulk modulus v3 = ref[e2.lower()][n] abserr = abs((v3 - v2) / v2) #print e, abserr strerr = '3: '+ e1 + ' vs ' + e2 + ' ' + str(v3) + ' : ' + str(v2) + ': ' + str(abserr) if n == 0: # volume assert abserr < 5.e-5, strerr else: # different eos disagree by ~1% for bulk modulus! # The differences depend mostly on the sampling interval # and less on the number of sampling points. # Typical 5% of lattice constant is way too large for Al (~2% needed)! assert abserr < 1.e-2, strerr python-ase-3.9.1.4567/ase/test/maxwellboltzmann.py0000664000175000017500000000061512553425527022200 0ustar jensjjensj00000000000000from ase.md.velocitydistribution import MaxwellBoltzmannDistribution from ase.lattice.cubic import FaceCenteredCubic atoms = FaceCenteredCubic(size=(50,50,50), symbol="Cu", pbc=False) print("Number of atoms:", len(atoms)) MaxwellBoltzmannDistribution(atoms, 0.1) temp = atoms.get_kinetic_energy() / (1.5 * len(atoms)) print("Temperature", temp, " (should be 0.1)") assert abs(temp - 0.1) < 1e-3 python-ase-3.9.1.4567/ase/test/mopac/0000775000175000017500000000000012553427753017330 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/mopac/__init__.py0000664000175000017500000000000012553425527021424 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/mopac/mopac_cmdline.py0000664000175000017500000000056412553425527022476 0ustar jensjjensj00000000000000from ase.test import NotAvailable from ase.calculators.mopac import Mopac if Mopac().get_command() is None: raise NotAvailable('MOPAC required') from ase.tasks.main import run atoms, task = run("mopac molecule O2 O") atoms, task = run('mopac molecule O2 O -s') ae = 2 * task.data['O']['energy'] - task.data['O2']['energy'] print(ae) assert abs(ae - 12.658) < 1e-3 python-ase-3.9.1.4567/ase/test/niggli.py0000664000175000017500000002047512553425527020061 0ustar jensjjensj00000000000000#!/usr/bin/env python # Convert a selection of unit cells, both reasonable and unreasonable, # into their Niggli unit cell, and compare against the pre-computed values. # The tests and pre-computed values come from the program cctbx, in which # this algorithm was originally implemented. from ase import Atoms from ase.utils.geometry import niggli_reduce import numpy as np cells_in = np.array([ [[+1.38924439894498e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+3.59907875374346e-01, +1.38877811878372e+01, +0.00000000000000e+00], [+6.94622199472490e+00, +6.76853982134488e+00, +1.11326936851271e+01]], [[+1.00000000000000e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-5.00000000000000e+00, +8.66025403784439e+00, +0.00000000000000e+00], [+1.41421356237310e+01, +8.16496580927726e+00, +1.15470053837925e+01]], [[+1.00000000000000e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-1.00000000000000e+01, +1.73205080756888e+01, +0.00000000000000e+00], [+1.50000000000000e+01, -8.66025403784438e+00, +2.44948974278318e+01]], [[+1.08166538263920e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+5.40832691319598e+00, +1.27180973419769e+01, +0.00000000000000e+00], [+5.40832691319598e+00, +5.20911251255623e+00, +1.16023767751065e+01]], [[+1.01488915650922e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.51609252491968e+00, +1.25938440639213e+01, +0.00000000000000e+00], [-4.12196081365396e+00, -5.71298877345999e+00, +1.13741460481665e+01]], [[+1.97989898732233e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-1.62230498655085e+02, +1.64752132933454e+02, +0.00000000000000e+00], [-5.05076272276107e-01, -1.43302471019530e+01, +6.23631266175214e-01]], [[+1.03923048454133e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-3.84900179459751e+00, +1.26168611463068e+01, +0.00000000000000e+00], [-3.27165152540788e+00, -6.30843057315338e+00, +1.11130553854464e+01]], [[+1.60468065358812e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-5.92018105207268e-01, +1.33285225949130e+01, +0.00000000000000e+00], [-8.05612005796522e+01, -1.80304581562370e+02, +8.00942125147844e+00]], [[+1.04880884817015e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.79909503253615e+00, +1.29602734102598e+01, +0.00000000000000e+00], [-3.34506458393662e+00, -6.26040929795398e+00, +1.18582384168722e+01]], [[+1.00498756211209e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-3.83918515889354e+00, +1.26198517152830e+01, +0.00000000000000e+00], [-1.69985519994207e+00, -7.00161889241639e+00, +1.10493359612507e+01]], [[+1.00498756211209e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.47766735594495e+00, +1.26866266221366e+01, +0.00000000000000e+00], [-3.68163760377696e+00, -5.94997793843316e+00, +1.14910098375475e+01]], [[+1.13578166916005e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-3.36772471669551e+00, +1.32158401258701e+01, +0.00000000000000e+00], [-3.36772471669551e+00, -6.98718877407442e+00, +1.12177369940646e+01]], [[+1.18321595661992e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.71877792223422e+00, +1.29511827614560e+01, +0.00000000000000e+00], [-3.55669082198251e+00, -6.47559138072800e+00, +1.16368667031408e+01]], [[+6.90590144772860e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-8.02073428510396e+00, +4.80089958494375e+01, +0.00000000000000e+00], [+1.34099960000000e-08, +4.16233443900000e-07, +4.81947969343710e-03]], [[+8.08161863921814e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.03305037431393e+01, +7.02701915501634e+01, +0.00000000000000e+00], [+1.95267511987431e-01, +1.40678305273598e+02, +3.93001827573170e-03]], [[+1.27366000000000e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.95315299468855e+00, +2.88072764316797e+01, +0.00000000000000e+00], [-9.46867174719139e-01, -5.76708582259125e-01, +4.90035053895005e+00]], [[+1.27806000000000e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+1.17491405990366e+01, +4.91718158542779e+00, +0.00000000000000e+00], [-6.91158909142352e+00, -1.19373435268607e+00, +2.86097847514890e+01]], ]) cells_out = np.array([ [[+1.38924439894498e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+3.59907875374344e-01, +1.38877811878372e+01, +0.00000000000000e+00], [+6.94622199472490e+00, +6.76853982134488e+00, +1.11326936851271e+01]], [[+1.00000000000000e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+5.00000000000000e+00, +8.66025403784439e+00, +0.00000000000000e+00], [+8.57864376268997e-01, +4.95288228567129e-01, +1.15470053837925e+01]], [[+1.00000000000000e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+1.06057523872491e-15, +1.73205080756888e+01, +0.00000000000000e+00], [-5.00000000000000e+00, -8.66025403784442e+00, +2.44948974278318e+01]], [[+1.08166538263920e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+5.40832691319598e+00, +1.27180973419769e+01, +0.00000000000000e+00], [+5.40832691319598e+00, +5.20911251255623e+00, +1.16023767751065e+01]], [[+1.01488915650922e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.51609252491968e+00, +1.25938440639213e+01, +0.00000000000000e+00], [-4.12196081365396e+00, -5.71298877345999e+00, +1.13741460481665e+01]], [[+1.36381816969869e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+6.81909084849243e+00, +1.26293309403154e+01, +0.00000000000000e+00], [+6.81909084849065e+00, +4.47371284092803e+00, +1.18104146166409e+01]], [[+1.03923048454133e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-3.84900179459751e+00, +1.26168611463068e+01, +0.00000000000000e+00], [-3.27165152540788e+00, -6.30843057315338e+00, +1.11130553854464e+01]], [[+1.26095202129182e+01, +0.00000000000000e+00, +0.00000000000000e+00], [+6.30476010645935e+00, +1.17579760163048e+01, +0.00000000000000e+00], [+3.15238005323008e+00, +5.87898800815218e+00, +1.15542200082912e+01]], [[+1.04880884817015e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.79909503253615e+00, +1.29602734102598e+01, +0.00000000000000e+00], [-3.34506458393662e+00, -6.26040929795398e+00, +1.18582384168722e+01]], [[+1.00498756211209e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.51083526228529e+00, +1.23956591287645e+01, +0.00000000000000e+00], [-3.83918515889354e+00, -5.71984630990568e+00, +1.12491784369700e+01]], [[+1.00498756211209e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.47766735594495e+00, +1.26866266221366e+01, +0.00000000000000e+00], [-3.68163760377696e+00, -5.94997793843316e+00, +1.14910098375475e+01]], [[+1.13578166916005e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.62236725820948e+00, +1.28309672640153e+01, +0.00000000000000e+00], [-3.36772471669551e+00, -6.41548363200768e+00, +1.15542200082913e+01]], [[+1.18321595661992e+01, +0.00000000000000e+00, +0.00000000000000e+00], [-4.71877792223422e+00, +1.29511827614560e+01, +0.00000000000000e+00], [-3.55669082198251e+00, -6.47559138072800e+00, +1.16368667031408e+01]], [[+4.81947971142972e-03, +0.00000000000000e+00, +0.00000000000000e+00], [+4.12397039845618e-03, +4.86743859122682e+01, +0.00000000000000e+00], [+4.62732595971025e-03, +1.13797841621313e+01, +6.81149615940608e+01]], [[+1.43683914413843e-01, +0.00000000000000e+00, +0.00000000000000e+00], [+4.73841211849216e-02, +8.02075186538656e+00, +0.00000000000000e+00], [+9.29303317118020e-03, +8.28854375915883e-01, +1.93660401476964e+01]], [[+5.02420000000000e+00, +0.00000000000000e+00, +0.00000000000000e+00], [-2.40035596861745e+00, +1.25083680303996e+01, +0.00000000000000e+00], [-2.37319883118274e+00, -5.49894680458153e+00, +2.86098306766757e+01]], [[+5.02419976114664e+00, +0.00000000000000e+00, +0.00000000000000e+00], [-2.40036499209593e+00, +1.25083662987906e+01, +0.00000000000000e+00], [-2.37320481266200e+00, -5.49892622854049e+00, +2.86097847514890e+01]], ]) conf = Atoms(pbc=True) for i, cell in enumerate(cells_in): conf.set_cell(cell) niggli_reduce(conf) cell = conf.get_cell() diff = np.linalg.norm(cell - cells_out[i]) assert diff < 1e-5, \ 'Difference between unit cells is too large! ({0})'.format(diff) python-ase-3.9.1.4567/ase/test/h2.py0000664000175000017500000000036712553425527017117 0ustar jensjjensj00000000000000from ase import Atoms from ase.calculators.emt import EMT h2 = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT()) f1 = h2.calc.calculate_numerical_forces(h2, 0.0001) f2 = h2.get_forces() assert abs(f1 - f2).max() < 1e-6 python-ase-3.9.1.4567/ase/test/__init__.py0000664000175000017500000001472412553425527020347 0ustar jensjjensj00000000000000import os import sys import platform import unittest import subprocess from glob import glob import numpy as np from ase.parallel import paropen from ase.calculators.calculator import names as calc_names, get_calculator class NotAvailable(Exception): pass test_calculator_names = [] def require(calcname): if calcname not in test_calculator_names: raise NotAvailable class CustomTextTestRunner(unittest.TextTestRunner): def __init__(self, logname, descriptions=1, verbosity=1): self.f = paropen(logname, 'w') unittest.TextTestRunner.__init__(self, self.f, descriptions, verbosity) def run(self, test): stderr_old = sys.stderr try: sys.stderr = self.f testresult = unittest.TextTestRunner.run(self, test) finally: sys.stderr = stderr_old return testresult class ScriptTestCase(unittest.TestCase): def __init__(self, methodname='testfile', filename=None, display=True): unittest.TestCase.__init__(self, methodname) self.filename = filename self.display = display def testfile(self): try: with open(self.filename) as fd: exec(compile(fd.read(), self.filename, 'exec'), {'display': self.display}) except KeyboardInterrupt: raise RuntimeError('Keyboard interrupt') except ImportError as ex: module = ex.args[0].split()[-1].replace("'", '').split('.')[0] if module in ['scipy', 'cmr', 'Scientific', 'lxml']: sys.__stdout__.write('(skipped) ') else: raise except NotAvailable: sys.__stdout__.write('skipped ') def id(self): return self.filename def __str__(self): f = self.filename dir = os.path.basename(os.path.dirname(f)) file = os.path.basename(f) if f.find('test') + len('test') + 1 == f.find(file): return '%s (ScriptTestCase)' % file else: return '%s (ScriptTestCase)' % os.path.join(dir, file) def __repr__(self): return "ScriptTestCase(filename='%s')" % self.filename def test(verbosity=1, calculators=[], dir=None, display=True, stream=sys.stdout): test_calculator_names.extend(calculators) disable_calculators([name for name in calc_names if name not in calculators]) ts = unittest.TestSuite() if dir is None: # ase/test (__path__[0]) testdir = __path__[0] else: if os.path.isdir(dir): # absolute path testdir = dir else: # relative to ase/test (__path__[0]) testdir = os.path.join(__path__[0], dir) files = glob(testdir + '/*') sdirtests = [] # tests from subdirectories: only one level assumed tests = [] for f in files: if os.path.isdir(f): # add test subdirectories (like calculators) sdirtests.extend(glob(os.path.join(testdir, f) + '/*.py')) else: # add py files in testdir if f.endswith('.py'): tests.append(f) tests.sort() sdirtests.sort() tests.extend(sdirtests) # run test subdirectories at the end lasttest = None # is COCu111.py in the current set for test in tests: if test.endswith('vtk_data.py'): continue if test.endswith('__init__.py'): continue if test.endswith('COCu111.py'): lasttest = test continue ts.addTest(ScriptTestCase(filename=test, display=display)) if lasttest: ts.addTest(ScriptTestCase(filename=lasttest, display=display)) operating_system = platform.system() + ' ' + platform.machine() operating_system += ' ' + ' '.join(platform.dist()) python = platform.python_version() + ' ' + platform.python_compiler() python += ' ' + ' '.join(platform.architecture()) print('python %s on %s' % (python, operating_system)) from ase.utils import devnull sys.stdout = devnull ttr = unittest.TextTestRunner(verbosity=verbosity, stream=stream) results = ttr.run(ts) sys.stdout = sys.__stdout__ return results def disable_calculators(names): def __init__(self, *args, **kwargs): raise NotAvailable def __del__(self): pass for name in names: if name in ['emt', 'lj', 'eam', 'morse']: continue try: cls = get_calculator(name) except ImportError: pass else: cls.__init__ = __init__ cls.__del__ = __del__ def cli(command, calculator_name=None): if (calculator_name is not None and calculator_name not in test_calculator_names): return error = subprocess.call(' '.join(command.split('\n')), shell=True) assert error == 0 class World: """Class for testing parallelization with MPI""" def __init__(self, size): self.size = size self.data = {} def get_rank(self, rank): return CPU(self, rank) class must_raise: """Context manager for checking raising of exceptions.""" def __init__(self, exception): self.exception = exception def __enter__(self): pass def __exit__(self, exc_type, exc_value, tb): if exc_type is None: raise RuntimeError('Failed to fail: ' + str(self.exception)) return issubclass(exc_type, self.exception) class CPU: def __init__(self, world, rank): self.world = world self.rank = rank self.size = world.size def send(self, x, rank): while (self.rank, rank) in self.world.data: pass self.world.data[(self.rank, rank)] = x def receive(self, x, rank): while (rank, self.rank) not in self.world.data: pass x[:] = self.world.data.pop((rank, self.rank)) def sum(self, x): if not isinstance(x, np.ndarray): x = np.array([x]) self.sum(x) return x[0] if self.rank == 0: y = np.empty_like(x) for rank in range(1, self.size): self.receive(y, rank) x += y else: self.send(x, 0) self.broadcast(x, 0) def broadcast(self, x, root): if self.rank == root: for rank in range(self.size): if rank != root: self.send(x, rank) else: self.receive(x, root) python-ase-3.9.1.4567/ase/test/md.py0000664000175000017500000000110512553425527017175 0ustar jensjjensj00000000000000from ase import Atoms from ase.calculators.emt import EMT from ase.md import VelocityVerlet from ase.io import Trajectory a = 3.6 b = a / 2 fcc = Atoms('Cu', positions=[(0, 0, 0)], cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=1) fcc *= (2, 1, 1) fcc.set_calculator(EMT()) fcc.set_momenta([(0.9, 0.0, 0.0), (-0.9, 0, 0)]) md = VelocityVerlet(fcc, dt=0.1) def f(): print(fcc.get_potential_energy(), fcc.get_total_energy()) md.attach(f) md.attach(Trajectory('Cu2.traj', 'w', fcc).write, interval=3) md.run(steps=20) fcc2 = Trajectory('Cu2.traj', 'r')[-1] python-ase-3.9.1.4567/ase/test/CO2_Au111.py0000664000175000017500000000233412553425527020035 0ustar jensjjensj00000000000000from math import pi, cos, sin from ase import Atoms from ase.calculators.emt import EMT from ase.constraints import FixBondLengths from ase.optimize import BFGS from ase.lattice.surface import fcc111, add_adsorbate for wrap in [False, True]: zpos = cos(134.3 / 2.0 * pi / 180.0) * 1.197 xpos = sin(134.3 / 2.0 * pi / 180.0) * 1.19 co2 = Atoms('COO', positions=[(-xpos + 1.2, 0, -zpos), (-xpos + 1.2, -1.1, -zpos), (-xpos + 1.2, 1.1, -zpos)]) slab = fcc111('Au', size=(2, 2, 4), vacuum=2 * 5, orthogonal=True) slab.center() add_adsorbate(slab, co2, 1.5, 'bridge') slab.set_pbc((True, True, False)) d0 = co2.get_distance(-3, -2) d1 = co2.get_distance(-3, -1) calc = EMT() slab.set_calculator(calc) if wrap: # Remap into the cell so bond is actually wrapped: slab.set_scaled_positions(slab.get_scaled_positions() % 1.0) constraint = FixBondLengths([[-3, -2], [-3, -1]]) slab.set_constraint(constraint) dyn = BFGS(slab, trajectory='relax_%d.traj' % wrap) dyn.run(fmax=0.05) assert abs(slab.get_distance(-3, -2, mic=1) - d0) < 1e-9 assert abs(slab.get_distance(-3, -1, mic=1) - d1) < 1e-9 python-ase-3.9.1.4567/ase/test/nwchem/0000775000175000017500000000000012553427753017512 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/nwchem/__init__.py0000664000175000017500000000000012553425527021606 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/nwchem/nwchem_h3o2m.py0000664000175000017500000000371112553425527022354 0ustar jensjjensj00000000000000from math import radians, sin, cos from ase import Atom, Atoms from ase.neb import NEB from ase.constraints import FixAtoms from ase.calculators.nwchem import NWChem from ase.optimize import QuasiNewton, BFGS from ase.visualize import view # http://jcp.aip.org/resource/1/jcpsa6/v97/i10/p7507_s1 doo = 2.74 doht = 0.957 doh = 0.977 angle = radians(104.5) initial = Atoms('HOHOH', positions=[(- sin(angle)*doht, 0., cos(angle)*doht), (0., 0., 0.), (0., 0., doh), (0., 0., doo), (sin(angle)*doht, 0., doo - cos(angle)*doht)]) if 0: view(initial) final = Atoms('HOHOH', positions=[(- sin(angle)*doht, 0., cos(angle)*doht), (0., 0., 0.), (0., 0., doo - doh), (0., 0., doo), (sin(angle)*doht, 0., doo - cos(angle)*doht)]) if 0: view(final) # Make band: images = [initial.copy()] for i in range(3): images.append(initial.copy()) images.append(final.copy()) neb = NEB(images, climb=True) calculator = NWChem(task='gradient', geometry='nocenter noautosym noautoz', charge=-1) # Set constraints and calculator: constraint = FixAtoms(indices=[1, 3]) # fix OO for image in images: image.set_calculator(calculator) image.set_constraint(constraint) # Relax initial and final states: if 1: dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.10) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.10) # Interpolate positions between initial and final states: neb.interpolate() if 1: for image in images: print(image.get_distance(1, 2), image.get_potential_energy()) dyn = BFGS(neb, trajectory='nwchem_h3o2m.traj') dyn.run(fmax=0.10) # use better basis (e.g. aug-cc-pvdz) for NEB to converge for image in images: print(image.get_distance(1, 2), image.get_potential_energy()) python-ase-3.9.1.4567/ase/test/nwchem/nwchem_strong_levelshift.py0000664000175000017500000000157112553425527025167 0ustar jensjjensj00000000000000"""Check if ase issues a warning if level shift breaks symmetry.""" from warnings import catch_warnings, simplefilter from ase import Atoms from ase.calculators.nwchem import NWChem def main(): """The main routine for the prove of the warning.""" cr_atom = Atoms('Cr', positions=[(0, 0, 0)], pbc=False, magmoms=[5.0]) calculator = NWChem(task='energy', geometry='nocenter noautosym noautoz', convergence={'energy': 1e-3, 'density': 1e-2, 'gradient': 5e-2}, basis='Wachters+f', charge=1) cr_atom.set_calculator(calculator) with catch_warnings(record=True) as thrown_warning: simplefilter('always', RuntimeWarning) cr_atom.get_potential_energy() assert len(thrown_warning) == 1 assert 'levelshift' in str(thrown_warning[-1].message) if __name__ == '__main__': main() python-ase-3.9.1.4567/ase/test/nwchem/nwchem_spin_symmetry.py0000664000175000017500000000154112553425527024345 0ustar jensjjensj00000000000000"""Check if spin-symmetry is conserved""" from ase import Atoms from ase.calculators.nwchem import NWChem def main(): """Check is independence of alignment is conserved""" energies = [] cr_atom = Atoms('Cr', positions=[(0, 0, 0)], pbc=False) for orientation in range(2): imm = 6 * (-1) ** orientation cr_atom.set_initial_magnetic_moments([imm]) calculator = NWChem(task='energy', geometry='nocenter noautosym noautoz', convergence={'energy': 1e-3, 'density': 1e-2, 'gradient': 5e-2}, basis='m6-31g*', basispar='"ao basis" spherical', charge=0) cr_atom.set_calculator(calculator) energies.append(cr_atom.get_potential_energy()) assert abs(energies[0] - energies[1]) < 1e-9 if __name__ == '__main__': main() python-ase-3.9.1.4567/ase/test/nwchem/nwchem_cmdline.py0000664000175000017500000000130712553425527023036 0ustar jensjjensj00000000000000from ase.test import cli, require from ase.db import connect from ase.io.jsonio import read_json from ase.calculators.nwchem import NWChem require('nwchem') cli("""ase-build O | ase-run nwchem -d nwchem_cmdline.json && ase-build O2 | ase-run nwchem -d nwchem_cmdline.json""") c = connect('nwchem_cmdline.json') dct = read_json('nwchem_cmdline.json') for name in ['O2', 'O']: d = c.get([('name', '=', name)]) id = d.id e1 = d.energy e2 = c.get_atoms(id).get_potential_energy() e3 = NWChem.read_atoms(name).get_potential_energy() e4 = dct[id]['energy'] assert e1 == e2 == e3 == e4 print(e1) ae = 2 * c.get('name=O').energy - c.get('name=O2').energy assert abs(ae - 6.6053) < 1e-4 python-ase-3.9.1.4567/ase/test/nwchem/nwchem_broken_symmetry.py0000664000175000017500000000360612553425527024660 0ustar jensjjensj00000000000000"""Check if we can deal with spin-broken symmetries.""" from numpy import array from ase import Atoms from ase.calculators.nwchem import NWChem def main(): """Perform C_{\inf v} calculation on Cr_2.""" e_literature = -1.34 # PBE from # J. Chem. Phys. 112 , 5576 (2000) # http://dx.doi.org/10.1063/1.481183 names = [ 'Cr2_sp_up.mos', 'Cr2_sp_down.mos'] fragment_energies = array([.0] * 2) cr_atom = Atoms('Cr', positions=[(0, 0, 0)], pbc=False) for orientation in range(2): # create two fragments imm = 6 * (-1) ** orientation cr_atom.set_initial_magnetic_moments([imm]) calculator = NWChem(task='energy', xc='PBE', geometry='nocenter noautosym noautoz', convergence={'energy': 1e-3, 'density': 1e-2, 'gradient': 5e-2}, basis='"DZVP2 (DFT Orbital)"', vectors=u"input atomic output {}".format(names[orientation]), charge=0) cr_atom.set_calculator(calculator) fragment_energies[orientation] = cr_atom.get_potential_energy() cr_dimer = Atoms('Cr2', positions=[(0, 0, 0), (0, 0, 1.93)], pbc=False) cr_dimer.set_initial_magnetic_moments([0, 0]) calculator = NWChem(task='energy', xc='PBE', geometry='nocenter noautosym noautoz', convergence={'energy': 1e-3, 'density': 1e-2, 'gradient': 5e-2}, odft=True, basis='"DZVP2 (DFT Orbital)"', vectors=u"input fragment {} output Cr2_AF.mos".format( ' '.join(names)), charge=0) cr_dimer.set_calculator(calculator) e_dimer = cr_dimer.get_potential_energy() e_tot = e_dimer - fragment_energies.sum() assert abs(e_tot - e_literature) < 0.01 if __name__ == '__main__': main() python-ase-3.9.1.4567/ase/test/stress.py0000664000175000017500000000357212553425527020132 0ustar jensjjensj00000000000000from __future__ import division, print_function import numpy as np from ase.lattice import bulk from ase.calculators.lj import LennardJones from ase.constraints import UnitCellFilter from ase.optimize import MDMin vol0 = 4 * 0.91615977036 # theoretical minimum a0 = vol0**(1 / 3) a = bulk('X', 'fcc', a=a0) a.calc = LennardJones() a.set_cell(np.dot(a.cell, [[1.02, 0, 0.03], [0, 0.99, -0.02], [0.1, -0.01, 1.03]]), scale_atoms=True) a *= (1, 2, 3) a.rattle() sigma_vv = a.get_stress(voigt=False) print(sigma_vv) print(a.get_potential_energy() / len(a)) vol = a.get_volume() deps = 1e-5 cell = a.cell.copy() for v in range(3): x = np.eye(3) x[v, v] += deps a.set_cell(np.dot(cell, x), scale_atoms=True) ep = a.calc.get_potential_energy(a, force_consistent=True) x[v, v] -= 2 * deps a.set_cell(np.dot(cell, x), scale_atoms=True) em = a.calc.get_potential_energy(a, force_consistent=True) s = (ep - em) / 2 / deps / vol print(v, s, abs(s - sigma_vv[v, v])) assert abs(s - sigma_vv[v, v]) < 1e-7 for v1 in range(3): v2 = (v1 + 1) % 3 x = np.eye(3) x[v1, v2] = deps x[v2, v1] = deps a.set_cell(np.dot(cell, x), scale_atoms=True) ep = a.calc.get_potential_energy(a, force_consistent=True) x[v1, v2] = -deps x[v2, v1] = -deps a.set_cell(np.dot(cell, x), scale_atoms=True) em = a.calc.get_potential_energy(a, force_consistent=True) s = (ep - em) / deps / 4 / vol print(v1, v2, s, abs(s - sigma_vv[v1, v2])) assert abs(s - sigma_vv[v1, v2]) < 1e-7 opt = MDMin(UnitCellFilter(a), dt=0.01) opt.run(fmax=0.5) print(a.cell) for i in range(3): for j in range(3): x = np.dot(a.cell[i], a.cell[j]) y = (i + 1) * (j + 1) * a0**2 / 2 if i != j: y /= 2 print(i, j, x, (x - y) / x) assert abs((x - y) / x) < 0.01 python-ase-3.9.1.4567/ase/test/atoms_info_copy.py0000664000175000017500000000031312553425527021765 0ustar jensjjensj00000000000000from ase import Atoms at1 = Atoms('H2', positions=[[0., 0., 0.], [1., 0., 0.]]) at1.info['str'] = "str" at1.info['int'] = 42 at2 = Atoms(at1) assert at2.info == at1.info python-ase-3.9.1.4567/ase/test/castep/0000775000175000017500000000000012553427753017510 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/castep/__init__.py0000664000175000017500000000140112553425527021612 0ustar jensjjensj00000000000000def installed(): import os from ase.test import NotAvailable # check if CASTEP_COMMAND is set a environment variable if 'CASTEP_COMMAND' not in os.environ: print("WARNING: Environment variable CASTEP_COMMAND is not set") print("Will set CASTEP_COMMAND = castep for the sake of this test") print("Please change it if this does not run castep in your environment") os.environ['CASTEP_COMMAND'] = 'castep' if not (os.system('which %s > /dev/null 2>&1' % os.environ['CASTEP_COMMAND']) == 0): raise NotAvailable("""Could not find CASTEP. If you have it installed make sure, you set the CASTEP_COMMAND environment variable correctly""") return True python-ase-3.9.1.4567/ase/test/castep/castep_interface.py0000664000175000017500000000574012553425527023364 0ustar jensjjensj00000000000000"""Simple shallow test of the CASTEP interface""" import os import shutil import tempfile import traceback from ase.test.castep import installed assert installed() # check if we can import everything ase_castep_dir = "ase" try: castep_calc = __import__(ase_castep_dir + ".calculators.castep", globals(), locals(), ["Castep", "CastepParam", "create_castep_keywords"]) Castep = castep_calc.Castep CastepParam = castep_calc.CastepParam create_castep_keywords = castep_calc.create_castep_keywords except Exception as e: traceback.print_exc() print(e) assert False, 'Castep calculator module could not be loaded' try: __import__(ase_castep_dir + ".io.castep") except Exception as e: assert False, 'Castep io module could not be loaded' tmp_dir = tempfile.mkdtemp() cwd = os.getcwd() from ase.calculators.castep import Castep try: c = Castep(directory=tmp_dir, label='test_label') except Exception as e: traceback.print_exc() print(e) assert False, 'Could not instantiate castep calculator' try: c.xc_functional = 'PBE' except Exception as e: traceback.print_exc() print(e) assert False, 'Setting xc_functional failed' import ase.lattice.cubic lattice = ase.lattice.cubic.BodyCenteredCubic('Li' ) print('For the sake of evaluating this test, warnings') print('about auto-generating pseudo-potentials are') print('normal behavior and can be safely ignored') try: lattice.set_calculator(c) except Exception as e: traceback.print_exc() print(e) assert False, 'Setting the calculator %s failed' % c try: create_castep_keywords( castep_command=os.environ['CASTEP_COMMAND'], path=tmp_dir, fetch_only=20) except Exception as e: traceback.print_exc() print(e) assert False, "Cannot create castep_keywords, this usually means a bug"\ + " in the interface or the castep binary cannot be called" param_fn = os.path.join(tmp_dir, 'myParam.param') param = open(param_fn,'w') param.write('XC_FUNCTIONAL : PBE #comment\n') param.write('XC_FUNCTIONAL : PBE #comment\n') param.write('#comment\n') param.write('CUT_OFF_ENERGY : 450.\n') param.close() try: c.merge_param(param_fn) except Exception as e: traceback.print_exc() print(e) assert False,"Error in merge_param_filename, go figure" # check if the CastepOpt, CastepCell comparison mechanism works p1 = CastepParam() p2 = CastepParam() assert p1._options == p2._options, "Print two newly created CastepParams are not the same" p1._options['xc_functional'].value = 'PBE' p1.xc_functional = 'PBE' assert not p1._options == p2._options, "Changed one CastepParam, but the still look the same" assert c.calculation_required(lattice), 'Calculator does not fetch that a calculation is required' if not c.dryrun_ok(): print(c._error) assert False, "Dryrun_ok does not work, where it should" else: print("Dryrun is ok") c.prepare_input_files(lattice) os.chdir(cwd) shutil.rmtree(tmp_dir) print("Test finished without errors") python-ase-3.9.1.4567/ase/test/unitcellfilter.py0000664000175000017500000000166112553425527021631 0ustar jensjjensj00000000000000from math import sqrt from ase import Atoms from ase.optimize.lbfgs import LBFGS from ase.constraints import StrainFilter, UnitCellFilter from ase.io import Trajectory from ase.optimize.lbfgs import LBFGS from ase.optimize.mdmin import MDMin try: from asap3 import EMT except ImportError: pass else: a = 3.6 b = a / 2 cu = Atoms('Cu', cell=[(0,b,b),(b,0,b),(b,b,0)], pbc=1) * (6, 6, 6) cu.set_calculator(EMT()) f = UnitCellFilter(cu, [1, 1, 1, 0, 0, 0]) opt = LBFGS(f) t = Trajectory('Cu-fcc.traj', 'w', cu) opt.attach(t) opt.run(5.0) # HCP: from ase.lattice.surface import hcp0001 cu = hcp0001('Cu', (1, 1, 2), a=a / sqrt(2)) cu.cell[1,0] += 0.05 cu *= (6, 6, 3) cu.set_calculator(EMT()) print(cu.get_forces()) print(cu.get_stress()) f = UnitCellFilter(cu) opt = MDMin(f,dt=0.01) t = Trajectory('Cu-hcp.traj', 'w', cu) opt.attach(t) opt.run(0.2) python-ase-3.9.1.4567/ase/test/idpp.py0000664000175000017500000000072112553425527017534 0ustar jensjjensj00000000000000from ase.structure import molecule from ase.neb import NEB initial = molecule('C2H6') final = initial.copy() final.positions[2:5] = initial.positions[[3, 4, 2]] images = [initial] for i in range(5): images.append(initial.copy()) images.append(final) neb = NEB(images) d0 = images[3].get_distance(2, 3) neb.interpolate() d1 = images[3].get_distance(2, 3) neb.idpp_interpolate() d2 = images[3].get_distance(2, 3) print(d0, d1, d2) assert abs(d2 - 1.74) < 0.01 python-ase-3.9.1.4567/ase/test/atom.py0000664000175000017500000000106212553425527017537 0ustar jensjjensj00000000000000from ase import Atom, Atoms m = Atoms('H2') a = m[0] b = Atom('H') for c in [a, b]: assert c.x == 0 c.z = 24.0 assert c.position[2] == 24.0 assert c.symbol == 'H' c.number = 92 assert c.symbol == 'U' c.symbol = 'Fe' assert c.number == 26 c.tag = 42 assert c.tag == 42 c.momentum = (1,2,3) assert m[0].tag == 42 momenta = m.get_momenta() m = Atoms('LiH') for a in m: print(a.symbol) for a in m: if a.symbol == 'H': a.z = 0.75 assert m.get_distance(0, 1) == 0.75 a = m.pop() m += a del m[:1] print(m) python-ase-3.9.1.4567/ase/test/COCu111.py0000664000175000017500000000345212553425527017620 0ustar jensjjensj00000000000000from math import sqrt from ase import Atoms, Atom from ase.calculators.emt import EMT from ase.constraints import FixAtoms from ase.optimize import BFGS, QuasiNewton from ase.neb import NEB # Distance between Cu atoms on a (111) surface: a = 3.6 d = a / sqrt(2) fcc111 = Atoms(symbols='Cu', cell=[(d, 0, 0), (d / 2, d * sqrt(3) / 2, 0), (d / 2, d * sqrt(3) / 6, -a / sqrt(3))], pbc=True) slab = fcc111 * (2, 2, 4) slab.set_cell([2 * d, d * sqrt(3), 1]) slab.set_pbc((1, 1, 0)) slab.calc = 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 = 1.5 slab += Atom('C', (d / 2, -b / 2, h)) slab += Atom('O', (d / 2, +b / 2, h)) s = slab.copy() dyn = QuasiNewton(slab) dyn.run(fmax=0.05) # Make band: images = [slab] for i in range(6): image = slab.copy() # Set constraints and calculator: image.set_constraint(constraint) image.calc = EMT() images.append(image) # Displace last image: image[-2].position = image[-1].position image[-1].x = d image[-1].y = d / sqrt(3) dyn = QuasiNewton(images[-1]) dyn.run(fmax=0.05) neb = NEB(images, climb=not True) # Interpolate positions between initial and final states: neb.interpolate(method='idpp') for image in images: print(image.positions[-1], image.get_potential_energy()) dyn = BFGS(neb, maxstep=0.04, trajectory='mep.traj') dyn.run(fmax=0.05) for image in images: print(image.positions[-1], image.get_potential_energy()) if locals().get('display'): import os error = os.system('ase-gui mep.traj@-7:') assert error == 0 python-ase-3.9.1.4567/ase/test/hcp.py0000664000175000017500000000214512553425527017354 0ustar jensjjensj00000000000000try: import scipy except ImportError: from ase.test import NotAvailable raise NotAvailable('This test needs scipy module.') import numpy as np from ase.io import read, Trajectory from ase.lattice import bulk from ase.calculators.emt import EMT a0 = 3.52 / np.sqrt(2) c0 = np.sqrt(8 / 3.0) * a0 print('%.4f %.3f' % (a0, c0 / a0)) for i in range(3): traj = Trajectory('Ni.traj', 'w') eps = 0.01 for a in a0 * np.linspace(1 - eps, 1 + eps, 4): for c in c0 * np.linspace(1 - eps, 1 + eps, 4): ni = bulk('Ni', 'hcp', a=a, covera=c / a) ni.set_calculator(EMT()) ni.get_potential_energy() traj.write(ni) traj.close() configs = read('Ni.traj@:') energies = [config.get_potential_energy() for config in configs] ac = [(config.cell[0, 0], config.cell[2, 2]) for config in configs] from ase.optimize import polyfit p = polyfit(ac, energies, 2) from scipy.optimize import fmin_bfgs a0, c0 = fmin_bfgs(p, (a0, c0)) print('%.4f %.3f' % (a0, c0 / a0)) assert abs(a0 - 2.466) < 0.001 assert abs(c0 / a0 - 1.632) < 0.005 python-ase-3.9.1.4567/ase/test/pourbaix.py0000664000175000017500000000401512553425527020431 0ustar jensjjensj00000000000000from __future__ import print_function from ase.test import NotAvailable raise NotAvailable import numpy as np import ase.db from ase.phasediagram import bisect, Pourbaix, solvated if 0: N = 80 A = np.zeros((N, N), int) A[:] = -1 def f(x, y): dmin = 100 for i, (a, b) in enumerate([(0, 0), (0, 2), (1, 1)]): d = (x - a)**2 + (y - b)**2 if d < dmin: dmin = d imin = i return imin bisect(A, np.linspace(0, 2, N), np.linspace(0, 2, N), f) print(A) import matplotlib.pyplot as plt plt.imshow(A) plt.show() if 0: con = ase.db.connect('cubic_perovskites.db') references = [(row.count_atoms(), row.energy) for row in con.select('reference')] std = {} for count, energy in references: if len(count) == 1: symbol, n = list(count.items())[0] assert symbol not in std std[symbol] = energy / n std['O'] += 2.46 refs = [] for refcount, energy in references: for symbol, n in refcount.items(): energy -= n * std[symbol] if list(refcount) == ['O']: energy = 0.0 refs.append((refcount, energy)) if 1: refs = [#({'O': 1}, 0.0), ('O4Ti2', -17.511826939900217), ('Sr4O4', -20.474907588620653), ('Sr4', 0.0), ('Ti2', 0.0)] else: refs = [({'O': 1}, 0.0), ({'Zn': 1}, 0.0), ({'Zn': 2, 'O': 2}, -5.33991412178575), ({'Zn': 4, 'O': 8}, -7.594)] pb = Pourbaix(refs + solvated('SrTi'), Sr=1, Ti=1, O=3) #pb = Pourbaix(refs, Zn=1, O=1) print(pb.decompose(0, 9)) pH = np.linspace(-1, 15, 17) if 0: d, names = pb.diagram([0], pH) print(d) print('\n'.join(names)) U = np.linspace(-2, 2, 5) if 0: d, names = pb.diagram(U, [0]) for i, u in zip(d, U): print(u, names[i]) if 1: U = np.linspace(-3, 3, 200) pH = np.linspace(-1, 15, 300) d, names = pb.diagram(U, pH, plot=True) python-ase-3.9.1.4567/ase/test/build.py0000664000175000017500000000077512553425527017710 0ustar jensjjensj00000000000000import numpy as np from ase import Atoms, Atom a = Atoms([Atom('Cu')]) a.positions[:] += 1.0 print(a.get_positions(), a.positions) a=a+a a+=a a.append(Atom('C')) a += Atoms([]) a += Atom('H', magmom=1) print(a.get_initial_magnetic_moments()) print(a[0].number) print(a[[0,1]].get_atomic_numbers()) print(a[np.array([1,1,0,0,1], bool)].get_atomic_numbers()) print(a[::2].get_atomic_numbers()) print(a.get_chemical_symbols()) del a[2] print(a.get_chemical_symbols()) del a[-2:] print(a.get_chemical_symbols()) python-ase-3.9.1.4567/ase/test/distmom.py0000664000175000017500000000122512553425527020254 0ustar jensjjensj00000000000000from ase.dft import get_distribution_moment import numpy as np precision = 1E-8 x = np.linspace(-50., 50., 1000) y = np.exp(-x**2 / 2.) area, center, mom2 = get_distribution_moment(x, y, (0, 1, 2)) assert sum((abs(area - np.sqrt(2. * np.pi)), abs(center), abs(mom2 - 1.))) < precision x = np.linspace(-1., 1., 100000) for order in range(0, 9): y = x**order area = get_distribution_moment(x, y) assert abs(area - (1. - (-1.)**(order + 1)) / (order + 1.)) < precision x = np.linspace(-50., 50., 100) y = np.exp(-2. * (x - 7.)**2 / 10.) + np.exp(-2. * (x + 5.)**2 / 10.) center=get_distribution_moment(x, y, 1) assert abs(center - 1.) < precision python-ase-3.9.1.4567/ase/test/eam_test.py0000664000175000017500000000606112553425527020404 0ustar jensjjensj00000000000000import numpy as np from ase.calculators.eam import EAM from ase.lattice import bulk # test to generate an EAM potential file using a simplified # approximation to the Mishin potential Al99.eam.alloy data from scipy.interpolate import InterpolatedUnivariateSpline as spline cutoff = 6.28721 n = 21 rs = np.arange(0, n) * (cutoff / n) rhos = np.arange(0, 2, 2. / n) # generated from # mishin = EAM(potential='../potentials/Al99.eam.alloy') # m_density = mishin.electron_density[0](rs) # m_embedded = mishin.embedded_energy[0](rhos) # m_phi = mishin.phi[0,0](rs) m_density = np.array([2.78589606e-01, 2.02694937e-01, 1.45334053e-01, 1.06069912e-01, 8.42517168e-02, 7.65140344e-02, 7.76263116e-02, 8.23214224e-02, 8.53322309e-02, 8.13915861e-02, 6.59095390e-02, 4.28915711e-02, 2.27910928e-02, 1.13713167e-02, 6.05020311e-03, 3.65836583e-03, 2.60587564e-03, 2.06750708e-03, 1.48749693e-03, 7.40019174e-04, 6.21225205e-05]) m_embedded = np.array([1.04222211e-10, -1.04142633e+00, -1.60359806e+00, -1.89287637e+00, -2.09490167e+00, -2.26456628e+00, -2.40590322e+00, -2.52245359e+00, -2.61385603e+00, -2.67744693e+00, -2.71053295e+00, -2.71110418e+00, -2.69287013e+00, -2.68464527e+00, -2.69204083e+00, -2.68976209e+00, -2.66001244e+00, -2.60122024e+00, -2.51338548e+00, -2.39650817e+00, -2.25058831e+00]) m_phi = np.array([6.27032242e+01, 3.49638589e+01, 1.79007014e+01, 8.69001383e+00, 4.51545250e+00, 2.83260884e+00, 1.93216616e+00, 1.06795515e+00, 3.37740836e-01, 1.61087890e-02, -6.20816372e-02, -6.51314297e-02, -5.35210341e-02, -5.20950200e-02, -5.51709524e-02, -4.89093894e-02, -3.28051688e-02, -1.13738785e-02, 2.33833655e-03, 4.19132033e-03, 1.68600692e-04]) m_densityf = spline(rs, m_density) m_embeddedf = spline(rhos, m_embedded) m_phif = spline(rs, m_phi) a = 4.05 # Angstrom lattice spacing al = bulk('Al', 'fcc', a=a) mishin_approx = EAM(elements=['Al'], embedded_energy=np.array([m_embeddedf]), electron_density=np.array([m_densityf]), phi=np.array([[m_phif]]), cutoff=cutoff, form='alloy', # the following terms are only required to write out a file Z=[13], nr=n, nrho=n, dr=cutoff / n, drho=2. / n, lattice=['fcc'], mass=[26.982], a=[a]) al.set_calculator(mishin_approx) mishin_approx_energy = al.get_potential_energy() mishin_approx.write_potential('Al99-test.eam.alloy') mishin_check = EAM(potential='Al99-test.eam.alloy') al.set_calculator(mishin_check) mishin_check_energy = al.get_potential_energy() print('Cohesive Energy for Al = ', mishin_approx_energy, ' eV') error = (mishin_approx_energy - mishin_check_energy) / mishin_approx_energy print('read/write check error = ', error) assert abs(error) < 1e-4 python-ase-3.9.1.4567/ase/test/repeat_FixAtoms.py0000664000175000017500000000205212553425527021671 0ustar jensjjensj00000000000000from ase.structure import molecule from ase.constraints import FixAtoms N = 2 atoms = molecule('CO2') atoms.set_cell((15.,15.,15.)) print('indices method') atomsi = atoms.copy() atomsi.set_constraint(FixAtoms(indices=[0,])) atomsi = atomsi.repeat((N,1,1)) atomsiref = atoms.copy().repeat((N,1,1)) atomsiref.set_constraint(FixAtoms(indices=[0, N + 1])) lcatomsi = list(atomsi.constraints[0].index) lcatomsiref = list(atomsiref.constraints[0].index) assert lcatomsi == lcatomsiref print('mask method') atomsm = atoms.copy() atomsm.set_constraint(FixAtoms(mask=[True, False, False])) atomsm = atomsm.repeat((N,1,1)) atomsmref = atoms.copy().repeat((N,1,1)) atomsmref.set_constraint(FixAtoms(mask=[True, False, False] * N)) lcatomsm = list(atomsm.constraints[0].index) lcatomsmref = list(atomsmref.constraints[0].index) assert lcatomsm == lcatomsmref # http://stackoverflow.com/questions/3873361/finding-multiple-occurrences-of-a-string-within-a-string-in-python lcatomsm2i = [n for (n, e) in enumerate(lcatomsm) if e == True] assert lcatomsm2i == lcatomsi python-ase-3.9.1.4567/ase/test/set_momenta.py0000664000175000017500000000144512553425527021117 0ustar jensjjensj00000000000000"""Test that set_momenta behaves as expected when constraints are involved.""" import numpy as np from ase import Atoms, Atom from ase.constraints import Hookean, FixAtoms # FixAtoms check atoms = Atoms([Atom('H', (0., 0., 0.)), Atom('H', (2., 0., 0.))]) atoms.set_constraint(FixAtoms(indices=[0])) atoms.set_momenta(np.ones(atoms.get_momenta().shape)) desired = np.ones(atoms.get_momenta().shape) desired[0] = 0. actual = atoms.get_momenta() assert (actual == desired).all() # Hookean check atoms = Atoms([Atom('H', (0., 0., 0.)), Atom('H', (2., 0., 0.))]) atoms.set_constraint(Hookean(0, 1, rt=1., k=10.)) atoms.set_momenta(np.zeros(atoms.get_momenta().shape)) actual = atoms.get_momenta() desired = np.zeros(atoms.get_momenta().shape) assert (actual == desired).all() python-ase-3.9.1.4567/ase/test/turbomole/0000775000175000017500000000000012553427753020241 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/turbomole/__init__.py0000664000175000017500000000000012553425527022335 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/turbomole/turbomole_h3o2m.py0000664000175000017500000000512312553425527023631 0ustar jensjjensj00000000000000import os from subprocess import Popen, PIPE, STDOUT from math import radians, sin, cos from ase import Atom, Atoms from ase.neb import NEB from ase.constraints import FixAtoms from ase.optimize import QuasiNewton, BFGS from ase.visualize import view from ase.calculators.turbomole import Turbomole # Delete old coord, control, ... files, if exist for f in ['coord', 'basis', 'energy', 'gradients', 'alpha', 'beta', 'mos', 'forceapprox', 'statistics', 'dscf_problem', 'control']: if os.path.exists(f): os.remove(f) # http://jcp.aip.org/resource/1/jcpsa6/v97/i10/p7507_s1 doo = 2.74 doht = 0.957 doh = 0.977 angle = radians(104.5) initial = Atoms('HOHOH', positions=[(- sin(angle)*doht, 0., cos(angle)*doht), (0., 0., 0.), (0., 0., doh), (0., 0., doo), (sin(angle)*doht, 0., doo - cos(angle)*doht)]) if 0: view(initial) final = Atoms('HOHOH', positions=[(- sin(angle)*doht, 0., cos(angle)*doht), (0., 0., 0.), (0., 0., doo - doh), (0., 0., doo), (sin(angle)*doht, 0., doo - cos(angle)*doht)]) if 0: view(final) # Make band: images = [initial.copy()] for i in range(3): images.append(initial.copy()) images.append(final.copy()) neb = NEB(images, climb=True) # Set constraints and calculator: constraint = FixAtoms(indices=[1, 3]) # fix OO #BUG No.1: fixes atom 0 and 1 #constraint = FixAtoms(mask=[0,1,0,1,0]) # fix OO #Works without patch for image in images: image.set_calculator(Turbomole()) #BUG No.2: (Over-)writes coord file image.set_constraint(constraint) # Write all commands for the define command in a string define_str = '\n\na coord\n\n*\nno\nb all 3-21g hondo\n*\neht\n\n-1\nno\ns\n*\n\ndft\non\nfunc pwlda\n\n\nscf\niter\n300\n\n*' # Run define p = Popen('define', stdout=PIPE, stdin=PIPE, stderr=STDOUT) stdout = p.communicate(input=define_str) # Relax initial and final states: if 1: dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.10) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.10) # Interpolate positions between initial and final states: neb.interpolate() if 1: for image in images: print(image.get_distance(1, 2), image.get_potential_energy()) dyn = BFGS(neb, trajectory='turbomole_h3o2m.traj') dyn.run(fmax=0.10) for image in images: print(image.get_distance(1, 2), image.get_potential_energy()) python-ase-3.9.1.4567/ase/test/turbomole/turbomole_H2.py0000664000175000017500000000136012553425527023151 0ustar jensjjensj00000000000000import os from subprocess import Popen, PIPE, STDOUT from ase import Atoms from ase.calculators.turbomole import Turbomole # Delete old coord, control, ... files, if exist for f in ['coord', 'basis', 'energy', 'mos', 'statistics', 'control']: if os.path.exists(f): os.remove(f) atoms = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1.1)]) atoms.set_calculator(Turbomole()) # Writes a coord file as well # Write all commands for the define command in a string define_str = '\n\na coord\n*\nno\nb all sto-3g hondo\n*\neht\n\n\n\n*' # Run define p = Popen('define', stdout=PIPE, stdin=PIPE, stderr=STDOUT) stdout = p.communicate(input=define_str) # Run turbomole atoms.get_potential_energy() python-ase-3.9.1.4567/ase/test/emt2.py0000664000175000017500000000057412553425527017455 0ustar jensjjensj00000000000000from ase.calculators.emt import EMT from ase import Atoms from ase.structure import molecule a1 = Atoms('Au', calculator=EMT()) e1 = a1.get_potential_energy() a2 = molecule('C6H6', calculator=EMT()) e2 = a2.get_potential_energy() a1.translate((0, 0, 50)) a3 = a1 + a2 a3.calc = EMT() e3 = a3.get_potential_energy() print(e1, e2, e3, e3 - e1 - e2) assert abs(e3 - e1 - e2) < 1e-13 python-ase-3.9.1.4567/ase/test/dependency_backend_gtkagg.py0000664000175000017500000000315612553425527023716 0ustar jensjjensj00000000000000from __future__ import print_function import os import sys msg = "\nThe Agg rendering GTK matplotlib backend is missing or not installed properly.\n" msg += "See http://matplotlib.org/faq/usage_faq.html#what-is-a-backend.\n" msg += "Is the PYTHONPATH environment variable set correctly?\n" msg += "Please verify your installation by running on the command line:\n" msg += "python -c 'from matplotlib.backends import backend_gtkagg'\n" msg += "\n" msg += "This module is optional and required in order to use " msg += "ASE's simple GUI (ase-gui).\n" msg += "If you don't wish to use ase-gui ignore this error, otherwise\n" msg += "please install the matplotlib package containing the missing backend\n" msg += "using your distribution package manager, i.e.:\n" msg += "\n" msg += " Debian/Ubuntu: sudo apt-get python-matplotlib\n" msg += "\n" msg += " OpenSUSE: yast -i python-matplotlib-gtk\n" msg += "\n" msg += " Red Hat/Fedora: yum install python-matplotlib\n" msg += "\n" msg += "or perform manual installation, preferably as non-root user,\n" msg += "following http://matplotlib.sourceforge.net/users/installing.html\n" msg += "after installing the http://www.pygtk.org/downloads.html dependency first." if locals().get('display'): try: import matplotlib.backends as b f = os.path.join(os.path.dirname(b.__file__), '_gtkagg.so') open(f).close() from matplotlib.backends import backend_gtkagg except ImportError: print(msg, file=sys.stderr) raise except IOError: print(('\nThe backend file %s does not exist.\n' % f) + msg, file=sys.stderr) raise python-ase-3.9.1.4567/ase/test/dimer_method.py0000775000175000017500000000254612553425527021252 0ustar jensjjensj00000000000000from ase.lattice.surface import fcc100, add_adsorbate from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.dimer import DimerControl, MinModeAtoms, MinModeTranslate # Set up a small "slab" with an adatoms atoms = fcc100('Pt', size = (2, 2, 1), vacuum = 10.0) add_adsorbate(atoms, 'Pt', 1.611, 'hollow') # Freeze the "slab" mask = [atom.tag > 0 for atom in atoms] atoms.set_constraint(FixAtoms(mask = mask)) # Calculate using EMT atoms.set_calculator(EMT()) relaxed_energy = atoms.get_potential_energy() # Set up the dimer d_control = DimerControl(initial_eigenmode_method = 'displacement', \ displacement_method = 'vector', logfile = None, \ mask = [0, 0, 0, 0, 1]) d_atoms = MinModeAtoms(atoms, d_control) # Displace the atoms displacement_vector = [[0.0]*3]*5 displacement_vector[-1][1] = -0.1 d_atoms.displace(displacement_vector = displacement_vector) # Converge to a saddle point dim_rlx = MinModeTranslate(d_atoms, trajectory = 'dimer_method.traj', \ logfile = None) dim_rlx.run(fmax = 0.001) # Test the results tolerance = 1e-3 assert(d_atoms.get_barrier_energy() - 1.03733136918 < tolerance) assert(abs(d_atoms.get_curvature() + 0.900467048707) < tolerance) assert(d_atoms.get_eigenmode()[-1][1] < -0.99) assert(abs(d_atoms.get_positions()[-1][1]) < tolerance) python-ase-3.9.1.4567/ase/test/dihedralconstraint.py0000664000175000017500000000410612553425527022462 0ustar jensjjensj00000000000000import sys from ase.calculators.emt import EMT from ase.constraints import FixInternals from ase.optimize.bfgs import BFGS from ase.structure import molecule from ase.test import NotAvailable if sys.version_info[0] == 3: raise NotAvailable system = molecule('CH3CH2OH') system.center(vacuum=5.0) system.rattle(stdev=0.3) # Angles, Bonds, Dihedrals are built up with pairs of constraint # value and indices defining the constraint # Fix this dihedral angle to whatever it was from the start indices = [6, 0, 1, 2] dihedral1 = system.get_dihedral(indices) # Fix angle to whatever it was from the start indices2 = [6, 0, 1] angle1 = system.get_angle(indices2) #system.set_dihedral(indices, pi/20, mask=[0,1,1,1,1,1,0,0,0]) # Fix bond between atoms 1 and 2 to 1.4 target_bondlength = 1.4 indices_bondlength = [1, 2] constraint = FixInternals(bonds=[(target_bondlength, indices_bondlength)], angles=[(angle1, indices2)], dihedrals=[(dihedral1, indices)], epsilon=1e-10) print(constraint) calc = EMT() opt = BFGS(system, trajectory='opt.traj', logfile='opt.log') previous_angle = system.get_angle(indices2) previous_dihedral = system.get_dihedral(indices) print('angle before', previous_angle) print('dihedral before', previous_dihedral) print('bond length before', system.get_distance(*indices_bondlength)) print('(target bondlength %s)', target_bondlength) system.set_calculator(calc) system.set_constraint(constraint) print('-----Optimization-----') opt.run(fmax=0.01) new_angle = system.get_angle(indices2) new_dihedral = system.get_dihedral(indices) new_bondlength = system.get_distance(*indices_bondlength) print('angle after', new_angle) print('dihedral after', new_dihedral) print('bondlength after', new_bondlength) err1 = new_angle - previous_angle err2 = new_dihedral - previous_dihedral err3 = new_bondlength - target_bondlength print('error in angle', repr(err1)) print('error in dihedral', repr(err2)) print('error in bondlength', repr(err3)) assert err1 < 1e-12 assert err2 < 1e-12 assert err3 < 1e-12 python-ase-3.9.1.4567/ase/test/COCu111_2.py0000664000175000017500000000446012553425550020035 0ustar jensjjensj00000000000000from math import sqrt from ase import Atoms, Atom from ase.constraints import FixAtoms from ase.optimize import FIRE, QuasiNewton, BFGS from ase.neb import SingleCalculatorNEB from ase.calculators.emt import EMT Optimizer = BFGS # Distance between Cu atoms on a (111) surface: a = 3.6 d = a / sqrt(2) fcc111 = Atoms(symbols='Cu', cell=[(d, 0, 0), (d / 2, d * sqrt(3) / 2, 0), (d / 2, d * sqrt(3) / 6, -a / sqrt(3))], pbc=True) initial = fcc111 * (2, 2, 4) initial.set_cell([2 * d, d * sqrt(3), 1]) initial.set_pbc((1, 1, 0)) initial.set_calculator(EMT()) Z = initial.get_positions()[:, 2] indices = [i for i, z in enumerate(Z) if z < Z.mean()] constraint = FixAtoms(indices=indices) initial.set_constraint(constraint) print('Relax initial image') dyn = Optimizer(initial) dyn.run(fmax=0.05) Z = initial.get_positions()[:, 2] print(Z[0] - Z[1]) print(Z[1] - Z[2]) print(Z[2] - Z[3]) b = 1.2 h = 1.5 initial += Atom('C', (d / 2, -b / 2, h)) initial += Atom('O', (d / 2, +b / 2, h)) s = initial.copy() dyn = Optimizer(initial) dyn.run(fmax=0.05) #view(initial) print('Relax final image') final = initial.copy() final.set_calculator(EMT()) final.set_constraint(constraint) final[-2].position = final[-1].position final[-1].x = d final[-1].y = d / sqrt(3) dyn = Optimizer(final) dyn.run(fmax=0.1) #view(final) print('Create neb with 2 intermediate steps') neb = SingleCalculatorNEB([initial, final]) neb.refine(2) assert neb.n() == 4 print('Optimize neb using a single calculator') neb.set_calculators(EMT()) ##print('0001', id(neb.images[0]), id(neb.images[0].get_calculator().atoms)) dyn = Optimizer(neb, maxstep=0.04, trajectory='mep_2coarse.traj') dyn.run(fmax=0.1) #dyn.run(fmax=39.1) print('Optimize neb using a many calculators') neb = SingleCalculatorNEB([initial, final]) neb.refine(2) neb.set_calculators([EMT() for i in range(neb.n())]) dyn = Optimizer(neb, maxstep=0.04, trajectory='mep_2coarse.traj') dyn.run(fmax=0.1) #dyn.run(fmax=39.1) # read from the trajectory neb = SingleCalculatorNEB('mep_2coarse.traj@-4:') # refine in the important region neb.refine(2, 1, 3) neb.set_calculators(EMT()) print('Optimize refined neb using a single calculator') dyn = Optimizer(neb, maxstep=0.04, trajectory='mep_2fine.traj') dyn.run(fmax=0.1) assert len(neb.images) == 8 python-ase-3.9.1.4567/ase/test/dependency_gtk.py0000664000175000017500000000200612553425527021561 0ustar jensjjensj00000000000000from __future__ import print_function import sys msg = "\nThe gtk python module is missing or not installed properly.\n" msg += "Is the PYTHONPATH environment variable set correctly?\n" msg += "Please verify your installation by running on the command line:\n" msg += "python -c 'import gtk'\n" msg += "\n" msg += "This module is optional and required in order to use " msg += "ASE's simple GUI (ase-gui).\n" msg += "If you don't wish to use ase-gui ignore this error, otherwise\n" msg += "please install the package using " msg += "your distribution package manager, i.e.:\n" msg += "\n" msg += " Debian/Ubuntu: sudo apt-get python-gtk2\n" msg += "\n" msg += " OpenSUSE: yast -i python-gtk\n" msg += "\n" msg += " Red Hat/Fedora: yum install pygtk2\n" msg += "\n" msg += "or perform manual installation, preferably as non-root user,\n" msg += "following http://www.pygtk.org/downloads.html.\n" if locals().get('display'): try: import gtk except ImportError: print(msg, file=sys.stderr) raise python-ase-3.9.1.4567/ase/test/rotate.py0000664000175000017500000000120412553425527020073 0ustar jensjjensj00000000000000import numpy as np from ase.utils import rotate, irotate def test(xyz): a = rotate(xyz) ixyz = '%sx,%sy,%sz' % irotate(a) a2 = rotate(ixyz) print(xyz) print(ixyz) #print np.around(a-a2, 5) assert abs(a-a2).max() < 1e-10 test('10z') test('155x,43y,190z') test('55x,90y,190z') test('180x,-90y,45z') test('-180y') test('40z,50x') from math import sqrt from ase import Atoms, Atom norm = np.linalg.norm for eps in [1.e-6, 1.e-8]: struct = Atoms([Atom('H'), Atom('H',[0, sqrt(1-eps**2), eps])]) struct.rotate(struct[1].position, 'y') assert abs(norm(struct[1].position) - 1) < 1.e-12 python-ase-3.9.1.4567/ase/test/strain.py0000664000175000017500000000144012553425527020077 0ustar jensjjensj00000000000000from math import sqrt from ase import Atoms from ase.constraints import StrainFilter from ase.optimize.mdmin import MDMin from ase.io import Trajectory try: from asap3 import EMT except ImportError: pass else: a = 3.6 b = a / 2 cu = Atoms('Cu', cell=[(0,b,b),(b,0,b),(b,b,0)], pbc=1) * (6, 6, 6) cu.set_calculator(EMT()) f = StrainFilter(cu, [1, 1, 1, 0, 0, 0]) opt = MDMin(f, dt=0.01) t = Trajectory('Cu.traj', 'w', cu) opt.attach(t) opt.run(0.001) # HCP: from ase.lattice.surface import hcp0001 cu = hcp0001('Cu', (1, 1, 2), a=a / sqrt(2)) cu.cell[1,0] += 0.05 cu *= (6, 6, 3) cu.set_calculator(EMT()) f = StrainFilter(cu) opt = MDMin(f, dt=0.01) t = Trajectory('Cu.traj', 'w', cu) opt.attach(t) opt.run(0.01) python-ase-3.9.1.4567/ase/test/atoms_distance.py0000664000175000017500000000225012553425527021574 0ustar jensjjensj00000000000000from ase import Atoms # Setup a chain of H,O,C # H-O Dist = 2 # O-C Dist = 3 # C-H Dist = 5 with mic=False # C-H Dist = 4 with mic=True a = Atoms('HOC', positions=[(1, 1, 1), (3, 1, 1), (6, 1, 1)]) a.set_cell((9, 2, 2)) a.set_pbc((True, False, False)) # Calculate indiviually with mic=True assert a.get_distance(0, 1, mic=True) == 2 assert a.get_distance(1, 2, mic=True) == 3 assert a.get_distance(0, 2, mic=True) == 4 # Calculate indiviually with mic=False assert a.get_distance(0, 1, mic=False) == 2 assert a.get_distance(1, 2, mic=False) == 3 assert a.get_distance(0, 2, mic=False) == 5 # Calculate in groups with mic=True assert (a.get_distances(0, [1, 2], mic=True) == [2, 4]).all() # Calculate in groups with mic=False assert (a.get_distances(0, [1, 2], mic=False) == [2, 5]).all() # Calculate all with mic=True assert (a.get_all_distances(mic=True) == [[0, 2, 4], [2, 0, 3], [4, 3, 0]]).all() # Calculate all with mic=False assert (a.get_all_distances(mic=False) == [[0, 2, 5], [2, 0, 3], [5, 3, 0]]).all() python-ase-3.9.1.4567/ase/test/vacancy.py0000664000175000017500000000214412553425527020225 0ustar jensjjensj00000000000000from ase import Atoms from ase.optimize import QuasiNewton from ase.neb import NEB from ase.optimize.mdmin import MDMin try: from asap3 import EMT except ImportError: pass else: a = 3.6 b = a / 2 initial = Atoms('Cu4', positions=[(0, 0, 0), (0, b, b), (b, 0, b), (b, b, 0)], cell=(a, a, a), pbc=True) initial *= (4, 4, 4) del initial[0] images = [initial] + [initial.copy() for i in range(6)] images[-1].positions[0] = (0, 0, 0) for image in images: image.set_calculator(EMT()) #image.set_calculator(ASAP()) for image in [images[0], images[-1]]: QuasiNewton(image).run(fmax=0.01) neb = NEB(images) neb.interpolate() for a in images: print(a.positions[0], a.get_potential_energy()) dyn = MDMin(neb, dt=0.1, trajectory='mep1.traj') #dyn = QuasiNewton(neb) print(dyn.run(fmax=0.01, steps=25)) for a in images: print(a.positions[0], a.get_potential_energy()) python-ase-3.9.1.4567/ase/test/tasks/0000775000175000017500000000000012553427753017356 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/tasks/__init__.py0000664000175000017500000000000012553425527021452 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/tasks/dcdft.py0000664000175000017500000012731012553425527021015 0ustar jensjjensj00000000000000"""Collection of bulk systems. From here:: http://molmod.ugent.be/DeltaCodesDFT Data extracted to csv file with * Wien2K ref: pdftotext -layout -f 13 -l 14 SupplMat.pdf - | sed -n '/text file/,$p' \ | grep -E -v "text" | sed '/^$/d' | tr '\f' ' ' \ | sed 's/,WIEN2k//g' | sed 's/V0/formula,V0/g' | sed -e 's/^[ \t]*//' \ | sed -e 's/\s\+/,/g' """ import os import glob import pprint import urllib import tarfile import zipfile import numpy as np from numpy import array from ase import Atoms import ase.io from ase.tasks.io import read_json from ase.tasks.bulk import BulkTask from ase.utils.eos import EquationOfState from ase.test import NotAvailable try: import urllib2 except ImportError: raise NotAvailable class FullEquationOfState(EquationOfState): """Fit equation of state for bulk systems. Based on eosfit.py from http://molmod.ugent.be/DeltaCodesDFT """ def __init__(self, volumes, energies, eos='birch'): assert eos == 'birch', eos + ' eos not available.' self.v = np.array(volumes) self.e = np.array(energies) self.eos_string = 'birch' self.v0 = None def fit(self): """Calculate volume (v0), energy (e0), bulk modulus (B0), and bulk modulus pressure derivative (B1). Returns v0, e0, B0, B1, fit residuals. Notice that the ASE units for the bulk modulus is eV/Angstrom^3 - to get the value in GPa, do this:: v0, e0, B0, B1, R = eos.fit() print(B0 / kJ * 1.0e24, 'GPa') """ fitdata = np.polyfit(self.v**(-2./3.), self.e, 3, full=True) ssr = fitdata[1] sst = np.sum((self.e - np.average(self.e))**2.) residuals0 = ssr/sst deriv0 = np.poly1d(fitdata[0]) deriv1 = np.polyder(deriv0, 1) deriv2 = np.polyder(deriv1, 1) deriv3 = np.polyder(deriv2, 1) self.v0 = None for x in np.roots(deriv1): if x > 0 and deriv2(x) > 0: self.v0 = x**(-3./2.) break if self.v0 is None: raise ValueError('No minimum!') derivV2 = 4./9. * x**5. * deriv2(x) derivV3 = (-20./9. * x**(13./2.) * deriv2(x) - 8./27. * x**(15./2.) * deriv3(x)) bulk_modulus0 = derivV2 / x**(3./2.) bulk_deriv0 = -1 - x**(-3./2.) * derivV3 / derivV2 self.e0 = deriv0(x) self.B0 = bulk_modulus0 self.B1 = bulk_deriv0 return self.v0, self.e0, self.B0, self.B1, residuals0 class DeltaCodesDFTCollection: # https://molmod.ugent.be/sites/default/files/Delta_v3-0_0.zip wienref = """ formula,V0,B0,B1 H,17.3883,10.284,2.71 He,17.7708,0.847,7.71 Li,20.2191,13.839,3.34 Be,7.9099,122.903,3.04 B,7.2405,237.290,3.47 C,11.6366,208.991,3.58 N,28.8848,54.2195,3.7244 O,18.5590,51.378,3.89 F,19.1666,34.325,3.93 Ne,24.2492,1.406,14.44 Na,37.4686,7.472,3.77 Mg,22.9355,35.933,4.07 Al,16.4796,78.077,4.57 Si,20.4530,88.545,4.31 P,21.4709,68.208,4.35 S,17.1840,83.407,4.26 Cl,38.8889,19.081,4.34 Ar,52.3852,0.743,7.26 K,73.6793,3.574,4.59 Ca,42.1991,17.114,3.31 Sc,24.6196,54.393,3.42 Ti,17.3900,112.213,3.58 V,13.4520,181.674,3.75 Cr,11.7730,183.899,7.16 Mn,11.4473,118.632,-0.21 Fe,11.3436,197.652,5.80 Co,10.8599,217.295,4.37 Ni,10.8876,200.368,5.00 Cu,11.9511,141.335,4.86 Zn,15.1820,74.780,5.26 Ga,20.3069,49.223,5.38 Ge,23.9148,59.128,4.99 As,22.5890,68.285,4.22 Se,29.7437,47.070,4.44 Br,39.4470,22.415,4.87 Kr,65.6576,0.671,9.86 Rb,90.8087,2.787,5.80 Sr,54.5272,11.256,3.49 Y,32.8442,41.593,3.02 Zr,23.3850,93.684,3.21 Nb,18.1368,171.270,3.55 Mo,15.7862,258.928,4.33 Tc,14.4366,299.149,4.46 Ru,13.7619,312.502,4.95 Rh,14.0396,257.824,5.32 Pd,15.3101,168.629,5.56 Ag,17.8471,90.148,5.42 Cd,22.6287,46.403,6.92 In,27.4710,34.937,4.78 Sn,36.8166,36.030,4.64 Sb,31.7296,50.367,4.52 Te,34.9765,44.787,4.69 I,50.2333,18.654,5.05 Xe,86.6814,0.548,6.34 Cs,117.080,1.982,2.14 Ba,63.1401,8.677,3.77 Lu,29.0544,46.384,2.94 Hf,22.5325,107.004,3.50 Ta,18.2856,195.147,3.71 W,16.1394,301.622,4.28 Re,14.9580,362.850,4.52 Os,14.2802,397.259,4.84 Ir,14.5004,347.680,5.18 Pt,15.6420,248.711,5.46 Au,17.9745,139.109,5.76 Hg,29.5220,8.204,8.87 Tl,31.3902,26.865,5.49 Pb,32.0028,39.544,4.53 Bi,36.9047,42.630,4.70 Po,37.5869,45.458,4.93 Rn,92.6852,0.564,8.62 """ # http://molmod.ugent.be/sites/default/files/Delta_v1-1.zip atoms = { 'Ag': {'cell': array([[ 4.16424000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.54986159e-16, 4.16424000e+00, 0.00000000e+00], [ 2.54986159e-16, 2.54986159e-16, 4.16424000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.54986159e-16, 2.08212000e+00, 2.08212000e+00], [ 2.08212000e+00, 1.27493080e-16, 2.08212000e+00], [ 2.08212000e+00, 2.08212000e+00, 0.00000000e+00]]), 'symbols': ['Ag', 'Ag', 'Ag', 'Ag']}, 'Al': {'cell': array([[ 4.04021000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.47391512e-16, 4.04021000e+00, 0.00000000e+00], [ 2.47391512e-16, 2.47391512e-16, 4.04021000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.47391512e-16, 2.02010500e+00, 2.02010500e+00], [ 2.02010500e+00, 1.23695756e-16, 2.02010500e+00], [ 2.02010500e+00, 2.02010500e+00, 0.00000000e+00]]), 'symbols': ['Al', 'Al', 'Al', 'Al']}, 'Ar': {'cell': array([[ 5.95059000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.64368550e-16, 5.95059000e+00, 0.00000000e+00], [ 3.64368550e-16, 3.64368550e-16, 5.95059000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.64368550e-16, 2.97529500e+00, 2.97529500e+00], [ 2.97529500e+00, 1.82184275e-16, 2.97529500e+00], [ 2.97529500e+00, 2.97529500e+00, 0.00000000e+00]]), 'symbols': ['Ar', 'Ar', 'Ar', 'Ar']}, 'As': {'cell': array([[ 3.82055000e+00, 0.00000000e+00, 0.00000000e+00], [ -1.91027500e+00, 3.30869336e+00, 0.00000000e+00], [ 6.60674292e-16, 1.14432144e-15, 1.07896300e+01]]), 'magmoms': None, 'positions': array([[ 1.49688974e-16, 2.59268909e-16, 2.44460647e+00], [ 5.10985318e-16, 8.85052532e-16, 8.34502353e+00], [ 1.91029410e+00, 1.10288676e+00, 6.04111384e+00], [ 1.91029410e+00, 1.10288676e+00, 1.15190090e+00], [ -1.91027500e-05, 2.20580660e+00, 9.63772910e+00], [ -1.91027500e-05, 2.20580660e+00, 4.74851616e+00]]), 'symbols': ['As', 'As', 'As', 'As', 'As', 'As']}, 'Au': {'cell': array([[ 4.17410000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.55589910e-16, 4.17410000e+00, 0.00000000e+00], [ 2.55589910e-16, 2.55589910e-16, 4.17410000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.55589910e-16, 2.08705000e+00, 2.08705000e+00], [ 2.08705000e+00, 1.27794955e-16, 2.08705000e+00], [ 2.08705000e+00, 2.08705000e+00, 0.00000000e+00]]), 'symbols': ['Au', 'Au', 'Au', 'Au']}, 'B': {'cell': array([[ 4.90067 , 0. , 0. ], [-2.450335 , 4.24410472, 0. ], [ 2.45033259, -1.41470018, 4.18412387]]), 'magmoms': None, 'positions': array([[ 6.47799802e+00, -9.10670757e-01, 2.82281917e+00], [ -1.57733043e+00, 3.74007529e+00, 1.36130470e+00], [ 4.90064387e+00, 1.82138677e+00, 2.82281917e+00], [ 2.37195308e-05, 1.00801776e+00, 1.36130470e+00], [ 3.32328972e+00, -9.10670757e-01, 2.82281917e+00], [ 1.57737787e+00, 3.74007529e+00, 1.36130470e+00], [ 3.45323244e+00, 8.35678467e-01, 3.04353170e-01], [ 1.44743515e+00, 1.99372607e+00, 3.87977070e+00], [ 2.45035933e+00, 2.57270564e+00, 3.04353170e-01], [ 2.45030826e+00, 2.56698890e-01, 3.87977070e+00], [ 1.44748622e+00, 8.35678467e-01, 3.04353170e-01], [ 3.45318137e+00, 1.99372607e+00, 3.87977070e+00]]), 'symbols': ['B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']}, 'Ba': {'cell': array([[ 5.02792000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.07871307e-16, 5.02792000e+00, 0.00000000e+00], [ 3.07871307e-16, 3.07871307e-16, 5.02792000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 2.51396, 2.51396, 2.51396]]), 'symbols': ['Ba', 'Ba']}, 'Be': {'cell': array([[ 2.26276000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.13138000e+00, 1.95960764e+00, 0.00000000e+00], [ 2.18792948e-16, 1.26320167e-16, 3.57316000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.13136869, 0.65319602, 1.78658 ]]), 'symbols': ['Be', 'Be']}, 'Bi': {'cell': array([[ 4.58866000e+00, 0.00000000e+00, 0.00000000e+00], [ -2.29433000e+00, 3.97389613e+00, 0.00000000e+00], [ 7.45946449e-16, 1.29201715e-15, 1.21822300e+01]]), 'magmoms': None, 'positions': array([[ 1.74357523e-16, 3.01996088e-16, 2.84747444e+00], [ 5.71588926e-16, 9.90021061e-16, 9.33475556e+00], [ 2.29435294e+00, 1.32461880e+00, 6.90817717e+00], [ 2.29435294e+00, 1.32461880e+00, 1.21322829e+00], [ -2.29433000e-05, 2.64927733e+00, 1.09690017e+01], [ -2.29433000e-05, 2.64927733e+00, 5.27405283e+00]]), 'symbols': ['Bi', 'Bi', 'Bi', 'Bi', 'Bi', 'Bi']}, 'Br': {'cell': array([[ 8.22860000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.58848083e-16, 4.22731000e+00, 0.00000000e+00], [ 5.53125810e-16, 5.53125810e-16, 9.03323000e+00]]), 'magmoms': None, 'positions': array([[ 5.85581169e-16, 1.58836946e+00, 7.97489677e+00], [ 2.43923148e-16, 5.25285541e-01, 3.45828177e+00], [ 5.68050745e-16, 3.70202446e+00, 5.57494823e+00], [ 2.26392724e-16, 2.63894054e+00, 1.05833323e+00], [ 4.11430000e+00, 3.70202446e+00, 7.97489677e+00], [ 4.11430000e+00, 2.63894054e+00, 3.45828177e+00], [ 4.11430000e+00, 1.58836946e+00, 5.57494823e+00], [ 4.11430000e+00, 5.25285541e-01, 1.05833323e+00]]), 'symbols': ['Br', 'Br', 'Br', 'Br', 'Br', 'Br', 'Br', 'Br']}, 'C': {'cell': array([[ 2.46857000e+00, 0.00000000e+00, 0.00000000e+00], [ -1.23428500e+00, 2.13784433e+00, 0.00000000e+00], [ 5.41342259e-16, 9.37632296e-16, 8.84079000e+00]]), 'magmoms': None, 'positions': array([[ 1.35335565e-16, 2.34408074e-16, 2.21019750e+00], [ 4.06006694e-16, 7.03224222e-16, 6.63059250e+00], [ -1.23428500e-05, 1.42523668e+00, 2.21019750e+00], [ 1.23429734e+00, 7.12607651e-01, 6.63059250e+00]]), 'symbols': ['C', 'C', 'C', 'C']}, 'Ca': {'cell': array([[ 5.52507000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.38312965e-16, 5.52507000e+00, 0.00000000e+00], [ 3.38312965e-16, 3.38312965e-16, 5.52507000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.38312965e-16, 2.76253500e+00, 2.76253500e+00], [ 2.76253500e+00, 1.69156482e-16, 2.76253500e+00], [ 2.76253500e+00, 2.76253500e+00, 0.00000000e+00]]), 'symbols': ['Ca', 'Ca', 'Ca', 'Ca']}, 'Cd': {'cell': array([[ 3.03716000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.51858000e+00, 2.63025772e+00, 0.00000000e+00], [ 3.53347953e-16, 2.04005536e-16, 5.77061000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.51856481, 0.8767438 , 2.885305 ]]), 'symbols': ['Cd', 'Cd']}, 'Cl': {'cell': array([[ 7.77875000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.66324552e-16, 4.34941000e+00, 0.00000000e+00], [ 5.52777398e-16, 5.52777398e-16, 9.02754000e+00]]), 'magmoms': None, 'positions': array([[ 6.05538240e-16, 1.77812580e+00, 8.11106414e+00], [ 2.44554210e-16, 3.96579204e-01, 3.59729414e+00], [ 5.74547740e-16, 3.95283080e+00, 5.43024586e+00], [ 2.13563710e-16, 2.57128420e+00, 9.16475861e-01], [ 3.88937500e+00, 3.95283080e+00, 8.11106414e+00], [ 3.88937500e+00, 2.57128420e+00, 3.59729414e+00], [ 3.88937500e+00, 1.77812580e+00, 5.43024586e+00], [ 3.88937500e+00, 3.96579204e-01, 9.16475861e-01]]), 'symbols': ['Cl', 'Cl', 'Cl', 'Cl', 'Cl', 'Cl', 'Cl', 'Cl']}, 'Co': {'cell': array([[ 2.49680000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.24840000e+00, 2.16229223e+00, 0.00000000e+00], [ 2.46815928e-16, 1.42499243e-16, 4.03081000e+00]]), 'magmoms': [1.2, 1.2], 'positions': array([[ 0. , 0. , 0. ], [ 1.24838752, 0.72075687, 2.015405 ]]), 'symbols': ['Co', 'Co']}, 'Cr': {'cell': array([[ 2.87100000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.75798048e-16, 2.87100000e+00, 0.00000000e+00], [ 1.75798048e-16, 1.75798048e-16, 2.87100000e+00]]), 'magmoms': [1.5, -1.5], 'positions': array([[ 0. , 0. , 0. ], [ 1.4355, 1.4355, 1.4355]]), 'symbols': ['Cr', 'Cr']}, 'Cs': {'cell': array([[ 6.16153000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.77284900e-16, 6.16153000e+00, 0.00000000e+00], [ 3.77284900e-16, 3.77284900e-16, 6.16153000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 3.080765, 3.080765, 3.080765]]), 'symbols': ['Cs', 'Cs']}, 'Cu': {'cell': array([[ 3.63689000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.22695285e-16, 3.63689000e+00, 0.00000000e+00], [ 2.22695285e-16, 2.22695285e-16, 3.63689000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.22695285e-16, 1.81844500e+00, 1.81844500e+00], [ 1.81844500e+00, 1.11347642e-16, 1.81844500e+00], [ 1.81844500e+00, 1.81844500e+00, 0.00000000e+00]]), 'symbols': ['Cu', 'Cu', 'Cu', 'Cu']}, 'F': {'cell': array([[ 6.16310000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.25644234e-16, 3.68505000e+00, 0.00000000e+00], [ -8.17043395e-01, 4.74089763e-16, 6.87706484e+00]]), 'magmoms': None, 'positions': array([[ 1.49468221, 1.21717201, 0.64733811], [ 3.8513744 , 2.46787799, 6.22972672], [ 4.2598961 , 1.21717202, 2.79119431], [ 1.08616051, 2.46787799, 4.08587053], [ 4.57623221, 3.05969702, 0.64733811], [ 0.7698244 , 0.62535299, 6.22972672], [ 1.1783461 , 3.05969702, 2.79119431], [ 4.16771051, 0.62535299, 4.08587053]]), 'symbols': ['F', 'F', 'F', 'F', 'F', 'F', 'F', 'F']}, 'Fe': {'cell': array([[ 2.83351000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.73502448e-16, 2.83351000e+00, 0.00000000e+00], [ 1.73502448e-16, 1.73502448e-16, 2.83351000e+00]]), 'magmoms': [2.3, 2.3], 'positions': array([[ 0. , 0. , 0. ], [ 1.416755, 1.416755, 1.416755]]), 'symbols': ['Fe', 'Fe']}, 'Ga': {'cell': array([[ 4.56689000e+00, 0.00000000e+00, 0.00000000e+00], [ 4.74752701e-16, 7.75330000e+00, 0.00000000e+00], [ 2.81655293e-16, 2.81655293e-16, 4.59978000e+00]]), 'magmoms': None, 'positions': array([[ 9.71312273e-17, 1.21277119e+00, 3.73502136e-01], [ 6.59276767e-16, 6.54052881e+00, 4.22627786e+00], [ 3.26813589e-16, 2.66387881e+00, 2.67339214e+00], [ 4.29594405e-16, 5.08942119e+00, 1.92638786e+00], [ 2.28344500e+00, 5.08942119e+00, 3.73502136e-01], [ 2.28344500e+00, 2.66387881e+00, 4.22627786e+00], [ 2.28344500e+00, 6.54052881e+00, 2.67339214e+00], [ 2.28344500e+00, 1.21277119e+00, 1.92638786e+00]]), 'symbols': ['Ga', 'Ga', 'Ga', 'Ga', 'Ga', 'Ga', 'Ga', 'Ga']}, 'Ge': {'cell': array([[ 4.07419 , 0. , 0. ], [ 2.037095 , 3.52835204, 0. ], [ 2.037095 , 1.17611735, 3.32656221]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 2.037095 , 1.17611735, 0.83164055]]), 'symbols': ['Ge', 'Ge']}, 'H': {'cell': array([[ 4.00759000e+00, 0.00000000e+00, 0.00000000e+00], [ -2.00379500e+00, 3.47067475e+00, 0.00000000e+00], [ 3.06349683e-16, 5.30613216e-16, 5.00307000e+00]]), 'magmoms': None, 'positions': array([[ -2.00379500e-05, 2.31379473e+00, 8.75437189e-01], [ 2.00381504e+00, 1.15688001e+00, 4.12763281e+00], [ 2.00381504e+00, 1.15688001e+00, 3.37697219e+00], [ -2.00379500e-05, 2.31379473e+00, 1.62609781e+00]]), 'symbols': ['H', 'H', 'H', 'H']}, 'He': {'cell': array([[ 2.92661000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.46330500e+00, 2.53451861e+00, 0.00000000e+00], [ 2.92637313e-16, 1.68954231e-16, 4.77913000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.46329037, 0.84483109, 2.389565 ]]), 'symbols': ['He', 'He']}, 'Hf': {'cell': array([[ 3.20273000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.60136500e+00, 2.77364554e+00, 0.00000000e+00], [ 3.10137516e-16, 1.79057978e-16, 5.06493000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.60134899, 0.92453927, 2.532465 ]]), 'symbols': ['Hf', 'Hf']}, 'Hg': {'cell': array([[ 4.10305000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.51239352e-16, 4.10305000e+00, 0.00000000e+00], [ 2.17271324e-16, 2.17271324e-16, 3.54831000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 2.051525, 2.051525, 1.774155]]), 'symbols': ['Hg', 'Hg']}, 'I': {'cell': array([[ 8.57701000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.78865547e-16, 4.55422000e+00, 0.00000000e+00], [ 6.23578516e-16, 6.23578516e-16, 1.01838100e+01]]), 'magmoms': None, 'positions': array([[ 6.49392323e-16, 1.65819150e+00, 8.94718995e+00], [ 2.73965947e-16, 6.18918498e-01, 3.85528495e+00], [ 6.28478117e-16, 3.93530150e+00, 6.32852505e+00], [ 2.53051741e-16, 2.89602850e+00, 1.23662005e+00], [ 4.28850500e+00, 3.93530150e+00, 8.94718995e+00], [ 4.28850500e+00, 2.89602850e+00, 3.85528495e+00], [ 4.28850500e+00, 1.65819150e+00, 6.32852505e+00], [ 4.28850500e+00, 6.18918498e-01, 1.23662005e+00]]), 'symbols': ['I', 'I', 'I', 'I', 'I', 'I', 'I', 'I']}, 'In': {'cell': array([[ 3.29841000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.01969362e-16, 3.29841000e+00, 0.00000000e+00], [ 3.09992395e-16, 3.09992395e-16, 5.06256000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.649205, 1.649205, 2.53128 ]]), 'symbols': ['In', 'In']}, 'Ir': {'cell': array([[ 3.87675000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.37382474e-16, 3.87675000e+00, 0.00000000e+00], [ 2.37382474e-16, 2.37382474e-16, 3.87675000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.37382474e-16, 1.93837500e+00, 1.93837500e+00], [ 1.93837500e+00, 1.18691237e-16, 1.93837500e+00], [ 1.93837500e+00, 1.93837500e+00, 0.00000000e+00]]), 'symbols': ['Ir', 'Ir', 'Ir', 'Ir']}, 'K': {'cell': array([[ 5.28589000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.23667413e-16, 5.28589000e+00, 0.00000000e+00], [ 3.23667413e-16, 3.23667413e-16, 5.28589000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 2.642945, 2.642945, 2.642945]]), 'symbols': ['K', 'K']}, 'Kr': {'cell': array([[ 6.42930000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.93681083e-16, 6.42930000e+00, 0.00000000e+00], [ 3.93681083e-16, 3.93681083e-16, 6.42930000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.93681083e-16, 3.21465000e+00, 3.21465000e+00], [ 3.21465000e+00, 1.96840542e-16, 3.21465000e+00], [ 3.21465000e+00, 3.21465000e+00, 0.00000000e+00]]), 'symbols': ['Kr', 'Kr', 'Kr', 'Kr']}, 'Li': {'cell': array([[ 7.64004 , 0. , 0. ], [ 7.02117921, 3.01218421, 0. ], [ 7.02117921, 1.44251886, 2.64431335]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 4.81826258, 0.98992412, 0.58761931], [ 16.86413584, 3.46477895, 2.05669403]]), 'symbols': ['Li', 'Li', 'Li']}, 'Lu': {'cell': array([[ 3.52388000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.76194000e+00, 3.05176960e+00, 0.00000000e+00], [ 3.35568531e-16, 1.93740582e-16, 5.48025000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.76192238, 1.01724636, 2.740125 ]]), 'symbols': ['Lu', 'Lu']}, 'Mg': {'cell': array([[ 3.19405000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.59702500e+00, 2.76612844e+00, 0.00000000e+00], [ 3.16692438e-16, 1.82842464e-16, 5.17198000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.59700903, 0.92203359, 2.58599 ]]), 'symbols': ['Mg', 'Mg']}, 'Mn': {'cell': array([[ 3.59552000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.20162103e-16, 3.59552000e+00, 0.00000000e+00], [ 2.20162103e-16, 2.20162103e-16, 3.59552000e+00]]), 'magmoms': [2.0, 1.9, -2.0, -1.9], 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.20162103e-16, 1.79776000e+00, 1.79776000e+00], [ 1.79776000e+00, 1.10081051e-16, 1.79776000e+00], [ 1.79776000e+00, 1.79776000e+00, 0.00000000e+00]]), 'symbols': ['Mn', 'Mn', 'Mn', 'Mn']}, 'Mo': {'cell': array([[ 3.16930000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.94063655e-16, 3.16930000e+00, 0.00000000e+00], [ 1.94063655e-16, 1.94063655e-16, 3.16930000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.58465, 1.58465, 1.58465]]), 'symbols': ['Mo', 'Mo']}, 'N': {'cell': array([[ 6.19019000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.79039818e-16, 6.19019000e+00, 0.00000000e+00], [ 3.79039818e-16, 3.79039818e-16, 6.19019000e+00]]), 'magmoms': None, 'positions': array([[ 0.32120896, 0.32120896, 0.32120896], [ 5.86898104, 5.86898104, 5.86898104], [ 2.77388604, 5.86898104, 3.41630396], [ 3.41630396, 0.32120896, 2.77388604], [ 5.86898104, 3.41630396, 2.77388604], [ 0.32120896, 2.77388604, 3.41630396], [ 3.41630396, 2.77388604, 5.86898104], [ 2.77388604, 3.41630396, 0.32120896]]), 'symbols': ['N', 'N', 'N', 'N', 'N', 'N', 'N', 'N']}, 'Na': {'cell': array([[ 9.41813 , 0. , 0. ], [ 8.67443415, 3.66815551, 0. ], [ 8.67443415, 1.75868789, 3.21906535]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 5.94816236, 1.20595314, 0.7153407 ], [ 20.81883594, 4.22089025, 2.50372465]]), 'symbols': ['Na', 'Na', 'Na']}, 'Nb': {'cell': array([[ 3.32239000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.03437714e-16, 3.32239000e+00, 0.00000000e+00], [ 2.03437714e-16, 2.03437714e-16, 3.32239000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.661195, 1.661195, 1.661195]]), 'symbols': ['Nb', 'Nb']}, 'Ne': {'cell': array([[ 4.62262000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.83053839e-16, 4.62262000e+00, 0.00000000e+00], [ 2.83053839e-16, 2.83053839e-16, 4.62262000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.83053839e-16, 2.31131000e+00, 2.31131000e+00], [ 2.31131000e+00, 1.41526920e-16, 2.31131000e+00], [ 2.31131000e+00, 2.31131000e+00, 0.00000000e+00]]), 'symbols': ['Ne', 'Ne', 'Ne', 'Ne']}, 'Ni': {'cell': array([[ 3.52414000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.15791339e-16, 3.52414000e+00, 0.00000000e+00], [ 2.15791339e-16, 2.15791339e-16, 3.52414000e+00]]), 'magmoms': [0.6, 0.6, 0.6, 0.6], 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.15791339e-16, 1.76207000e+00, 1.76207000e+00], [ 1.76207000e+00, 1.07895669e-16, 1.76207000e+00], [ 1.76207000e+00, 1.76207000e+00, 0.00000000e+00]]), 'symbols': ['Ni', 'Ni', 'Ni', 'Ni']}, 'O': {'cell': array([[ 4.27163000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.61879696e-16, 4.27682000e+00, 0.00000000e+00], [ 1.80666882e+00, 1.69295858e-16, 4.19933056e+00]]), 'magmoms': [1.5, 1.5, -1.5, -1.5], 'positions': array([[ 4.27100416e+00, 2.48306235e-17, 6.15915813e-01], [ 1.80729466e+00, 1.44465234e-16, 3.58341475e+00], [ 2.13518916e+00, 2.13841000e+00, 6.15915813e-01], [ 3.94310966e+00, 2.13841000e+00, 3.58341475e+00]]), 'symbols': ['O', 'O', 'O', 'O']}, 'Os': {'cell': array([[ 2.75895000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.37947500e+00, 2.38932079e+00, 0.00000000e+00], [ 2.66785631e-16, 1.54028756e-16, 4.35694000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.37946121, 0.7964323 , 2.17847 ]]), 'symbols': ['Os', 'Os']}, 'P': {'cell': array([[ 3.30466000e+00, 0.00000000e+00, 0.00000000e+00], [ 6.92962717e-16, 1.13169400e+01, 0.00000000e+00], [ 2.80032023e-16, 2.80032023e-16, 4.57327000e+00]]), 'magmoms': None, 'positions': array([[ 8.92565136e-17, 1.05892608e+00, 3.98743411e-01], [ 8.83738227e-16, 1.02580139e+01, 4.17452659e+00], [ 4.46072841e-16, 4.59954392e+00, 2.68537841e+00], [ 5.26921900e-16, 6.71739608e+00, 1.88789159e+00], [ 1.65233000e+00, 6.71739608e+00, 3.98743411e-01], [ 1.65233000e+00, 4.59954392e+00, 4.17452659e+00], [ 1.65233000e+00, 1.02580139e+01, 2.68537841e+00], [ 1.65233000e+00, 1.05892608e+00, 1.88789159e+00]]), 'symbols': ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P']}, 'Pb': {'cell': array([[ 5.04386000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.08847350e-16, 5.04386000e+00, 0.00000000e+00], [ 3.08847350e-16, 3.08847350e-16, 5.04386000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.08847350e-16, 2.52193000e+00, 2.52193000e+00], [ 2.52193000e+00, 1.54423675e-16, 2.52193000e+00], [ 2.52193000e+00, 2.52193000e+00, 0.00000000e+00]]), 'symbols': ['Pb', 'Pb', 'Pb', 'Pb']}, 'Pd': {'cell': array([[ 3.95315000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.42060625e-16, 3.95315000e+00, 0.00000000e+00], [ 2.42060625e-16, 2.42060625e-16, 3.95315000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.42060625e-16, 1.97657500e+00, 1.97657500e+00], [ 1.97657500e+00, 1.21030312e-16, 1.97657500e+00], [ 1.97657500e+00, 1.97657500e+00, 0.00000000e+00]]), 'symbols': ['Pd', 'Pd', 'Pd', 'Pd']}, 'Po': {'cell': array([[ 3.34818000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.05016896e-16, 3.34818000e+00, 0.00000000e+00], [ 2.05016896e-16, 2.05016896e-16, 3.34818000e+00]]), 'magmoms': None, 'positions': array([[ 0., 0., 0.]]), 'symbols': ['Po']}, 'Pt': {'cell': array([[ 3.97675000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.43505708e-16, 3.97675000e+00, 0.00000000e+00], [ 2.43505708e-16, 2.43505708e-16, 3.97675000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.43505708e-16, 1.98837500e+00, 1.98837500e+00], [ 1.98837500e+00, 1.21752854e-16, 1.98837500e+00], [ 1.98837500e+00, 1.98837500e+00, 0.00000000e+00]]), 'symbols': ['Pt', 'Pt', 'Pt', 'Pt']}, 'Rb': {'cell': array([[ 5.67197000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.47307995e-16, 5.67197000e+00, 0.00000000e+00], [ 3.47307995e-16, 3.47307995e-16, 5.67197000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 2.835985, 2.835985, 2.835985]]), 'symbols': ['Rb', 'Rb']}, 'Re': {'cell': array([[ 2.77447000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.38723500e+00, 2.40276150e+00, 0.00000000e+00], [ 2.74316597e-16, 1.58376761e-16, 4.47993000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.38722113, 0.80091249, 2.239965 ]]), 'symbols': ['Re', 'Re']}, 'Rh': {'cell': array([[ 3.84210000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.35260773e-16, 3.84210000e+00, 0.00000000e+00], [ 2.35260773e-16, 2.35260773e-16, 3.84210000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.35260773e-16, 1.92105000e+00, 1.92105000e+00], [ 1.92105000e+00, 1.17630387e-16, 1.92105000e+00], [ 1.92105000e+00, 1.92105000e+00, 0.00000000e+00]]), 'symbols': ['Rh', 'Rh', 'Rh', 'Rh']}, 'Rn': {'cell': array([[ 7.19417000e+00, 0.00000000e+00, 0.00000000e+00], [ 4.40515863e-16, 7.19417000e+00, 0.00000000e+00], [ 4.40515863e-16, 4.40515863e-16, 7.19417000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 4.40515863e-16, 3.59708500e+00, 3.59708500e+00], [ 3.59708500e+00, 2.20257932e-16, 3.59708500e+00], [ 3.59708500e+00, 3.59708500e+00, 0.00000000e+00]]), 'symbols': ['Rn', 'Rn', 'Rn', 'Rn']}, 'Ru': {'cell': array([[ 2.72661000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.36330500e+00, 2.36131353e+00, 0.00000000e+00], [ 2.63329678e-16, 1.52033460e-16, 4.30050000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.36329137, 0.78709664, 2.15025 ]]), 'symbols': ['Ru', 'Ru']}, 'S': {'cell': array([[ 2.58153 , 0. , 0. ], [-0.06556819, 2.58069718, 0. ], [-0.06556819, -0.06725525, 2.57982067]]), 'magmoms': None, 'positions': array([[ 0., 0., 0.]]), 'symbols': ['S']}, 'Sb': {'cell': array([[ 4.38047000e+00, 0.00000000e+00, 0.00000000e+00], [ -2.19023500e+00, 3.79359830e+00, 0.00000000e+00], [ 7.02827247e-16, 1.21733250e-15, 1.14780400e+01]]), 'magmoms': None, 'positions': array([[ 1.63983653e-16, 2.84028019e-16, 2.67805629e+00], [ 5.38843594e-16, 9.33304482e-16, 8.79998371e+00], [ 2.19025690e+00, 1.26452012e+00, 6.50414615e+00], [ 2.19025690e+00, 1.26452012e+00, 1.14791878e+00], [ -2.19023500e-05, 2.52907818e+00, 1.03301212e+01], [ -2.19023500e-05, 2.52907818e+00, 4.97389385e+00]]), 'symbols': ['Sb', 'Sb', 'Sb', 'Sb', 'Sb', 'Sb']}, 'Sc': {'cell': array([[ 3.32145000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.66072500e+00, 2.87646008e+00, 0.00000000e+00], [ 3.16076440e-16, 1.82486818e-16, 5.16192000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.66070839, 0.95881044, 2.58096 ]]), 'symbols': ['Sc', 'Sc']}, 'Se': {'cell': array([[ 4.52464000e+00, 0.00000000e+00, 0.00000000e+00], [ -2.26232000e+00, 3.91845318e+00, 0.00000000e+00], [ 3.09209846e-16, 5.35567163e-16, 5.04978000e+00]]), 'magmoms': None, 'positions': array([[ 9.91031899e-01, 1.78520602e-16, 1.68324317e+00], [ -4.95515950e-01, 8.58258801e-01, 3.36653683e+00], [ 1.76680405e+00, 3.06019438e+00, 0.00000000e+00]]), 'symbols': ['Se', 'Se', 'Se']}, 'Si': {'cell': array([[ 3.86709 , 0. , 0. ], [ 1.933545 , 3.34899818, 0. ], [ 1.933545 , 1.11633273, 3.15746576]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.933545 , 1.11633273, 0.78936644]]), 'symbols': ['Si', 'Si']}, 'Sn': {'cell': array([[ 4.70647 , 0. , 0. ], [ 2.353235 , 4.07592258, 0. ], [ 2.353235 , 1.35864086, 3.84281666]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 2.353235 , 1.35864086, 0.96070417]]), 'symbols': ['Sn', 'Sn']}, 'Sr': {'cell': array([[ 6.01969000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.68599705e-16, 6.01969000e+00, 0.00000000e+00], [ 3.68599705e-16, 3.68599705e-16, 6.01969000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 3.68599705e-16, 3.00984500e+00, 3.00984500e+00], [ 3.00984500e+00, 1.84299852e-16, 3.00984500e+00], [ 3.00984500e+00, 3.00984500e+00, 0.00000000e+00]]), 'symbols': ['Sr', 'Sr', 'Sr', 'Sr']}, 'Ta': {'cell': array([[ 3.32169000e+00, 0.00000000e+00, 0.00000000e+00], [ 2.03394851e-16, 3.32169000e+00, 0.00000000e+00], [ 2.03394851e-16, 2.03394851e-16, 3.32169000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.660845, 1.660845, 1.660845]]), 'symbols': ['Ta', 'Ta']}, 'Tc': {'cell': array([[ 2.76187000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.38093500e+00, 2.39184958e+00, 0.00000000e+00], [ 2.70588772e-16, 1.56224500e-16, 4.41905000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.38092119, 0.79727522, 2.209525 ]]), 'symbols': ['Tc', 'Tc']}, 'Te': {'cell': array([[ 4.50788000e+00, 0.00000000e+00, 0.00000000e+00], [ -2.25394000e+00, 3.90393860e+00, 0.00000000e+00], [ 3.65156610e-16, 6.32469801e-16, 5.96346000e+00]]), 'magmoms': None, 'positions': array([[ 1.21559492e+00, 2.10821159e-16, 1.98780012e+00], [ -6.07797460e-01, 1.05273608e+00, 3.97565988e+00], [ 1.64614254e+00, 2.85120252e+00, 0.00000000e+00]]), 'symbols': ['Te', 'Te', 'Te']}, 'Ti': {'cell': array([[ 2.93664000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.46832000e+00, 2.54320484e+00, 0.00000000e+00], [ 2.84848559e-16, 1.64457392e-16, 4.65193000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.46830532, 0.84772647, 2.325965 ]]), 'symbols': ['Ti', 'Ti']}, 'Tl': {'cell': array([[ 3.59255000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.79627500e+00, 3.11123956e+00, 0.00000000e+00], [ 3.45469800e-16, 1.99457082e-16, 5.64195000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.79625704, 1.03706948, 2.820975 ]]), 'symbols': ['Tl', 'Tl']}, 'V': {'cell': array([[ 2.99894000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.83632114e-16, 2.99894000e+00, 0.00000000e+00], [ 1.83632114e-16, 1.83632114e-16, 2.99894000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.49947, 1.49947, 1.49947]]), 'symbols': ['V', 'V']}, 'W': {'cell': array([[ 3.18968000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.95311570e-16, 3.18968000e+00, 0.00000000e+00], [ 1.95311570e-16, 1.95311570e-16, 3.18968000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.59484, 1.59484, 1.59484]]), 'symbols': ['W', 'W']}, 'Xe': {'cell': array([[ 7.05482000e+00, 0.00000000e+00, 0.00000000e+00], [ 4.31983137e-16, 7.05482000e+00, 0.00000000e+00], [ 4.31983137e-16, 4.31983137e-16, 7.05482000e+00]]), 'magmoms': None, 'positions': array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00], [ 4.31983137e-16, 3.52741000e+00, 3.52741000e+00], [ 3.52741000e+00, 2.15991568e-16, 3.52741000e+00], [ 3.52741000e+00, 3.52741000e+00, 0.00000000e+00]]), 'symbols': ['Xe', 'Xe', 'Xe', 'Xe']}, 'Y': {'cell': array([[ 3.66051000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.83025500e+00, 3.17009465e+00, 0.00000000e+00], [ 3.47431685e-16, 2.00589777e-16, 5.67399000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.8302367 , 1.05668765, 2.836995 ]]), 'symbols': ['Y', 'Y']}, 'Zn': {'cell': array([[ 2.66169000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.33084500e+00, 2.30509116e+00, 0.00000000e+00], [ 3.06404792e-16, 1.76902889e-16, 5.00397000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.33083169, 0.76835604, 2.501985 ]]), 'symbols': ['Zn', 'Zn']}, 'Zr': {'cell': array([[ 3.23603000e+00, 0.00000000e+00, 0.00000000e+00], [ 1.61801500e+00, 2.80248419e+00, 0.00000000e+00], [ 3.17767065e-16, 1.83462901e-16, 5.18953000e+00]]), 'magmoms': None, 'positions': array([[ 0. , 0. , 0. ], [ 1.61799882, 0.93415205, 2.594765 ]]), 'symbols': ['Zr', 'Zr']}} names = [r.split(',')[0] for r in wienref.split()][1:] ref = {} for name in names: for l in wienref.split(): if l.split(',')[0] == name: ref[name] = [float(v) for v in l.split(',')[1:]] data = {} for name in names: d = atoms[name] a = Atoms(symbols=d['symbols'], positions=d['positions'], cell=d['cell'], magmoms=d['magmoms']) a.set_pbc((1, 1, 1)) data[name] = a def __getitem__(self, name): # must return a copy return self.data[name].copy() def keys(self): return self.names class DeltaCodesDFTTask(BulkTask): def __init__(self, **kwargs): BulkTask.__init__(self, collection=DeltaCodesDFTCollection(), **kwargs) self.summary_keys = ['energy', 'fitted energy', 'volume', 'volume error [%]', 'B', 'B error [%]'] def analyse(self, atomsfile=None): try: BulkTask.analyse(self) except ValueError: # allow fit outside of range pass for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) # full equation of state # use relaxed volume if present if 'relaxed volume' in data: volume = data['relaxed volume'] else: volume = atoms.get_volume() volumes = data['strains']**3 * volume energies = data['energies'] eos = FullEquationOfState(volumes, energies) try: v, e, B0, B1, R = eos.fit() except ValueError: pass else: data['dcdft fitted energy'] = e / len(atoms) data['dcdft volume'] = v / len(atoms) data['dcdft B0'] = B0 data['dcdft B1'] = B1 data['dcdft R'] = R if atomsfile: # MDTMP: TODO atomdata = read_json(atomsfile) for name, data in self.data.items(): atoms = self.create_system(name) e = -data['energy'] for atom in atoms: e += atomdata[atom.symbol]['energy'] e /= len(atoms) data['cohesive energy'] = e if self.collection.xc == 'PBE': eref = self.collection.data[name][7] else: eref = self.collection.data[name][9] data['cohesive energy error [%]'] = (e / eref - 1) * 100 self.summary_keys += ['cohesive energy', 'cohesive energy error [%]'] if __name__ == '__main__': # download and create the project databases src = 'https://molmod.ugent.be/sites/default/files/Delta_v3-0.zip' name = os.path.basename(src) dir = 'Delta' if not os.path.exists(dir): os.makedirs(dir) os.chdir(dir) try: resp = urllib.request.urlopen(src) urllib.urlretrieve(src, filename=name) z = zipfile.ZipFile(name) try: # new in 2.6 z.extractall() except AttributeError: # http://stackoverflow.com/questions/7806563/how-to-unzip-a-zip-file-with-python-2-4 for f in z.namelist(): fd = open(f, "w") fd.write(z.read(f)) fd.close() t = tarfile.open('CIFs.tar.gz', 'r:gz') t.extractall() # extract structures data = {} for f in glob.glob('*.cif'): a = ase.io.read(f) s = os.path.splitext(f)[0] # Fe, Co, Ni M = {'Fe': 2.3, 'Co': 1.2, 'Ni': 0.6}.get(s) if M is not None: magmoms = [M] * len(a) else: magmoms = None # antiferromagnetic Cr, O if s in ['Cr', 'O']: magmoms = [1.5 for i in range(len(a) / 2)] magmoms += [-1.5 for i in range(len(a) / 2)] # ferrimagnetic Mn elif s in ['Mn']: magmoms = [2.0, 1.9, -2.0, -1.9] d = {'symbols': a.get_chemical_symbols(), 'positions': a.get_positions(), 'cell': a.get_cell(), 'magmoms': magmoms} data[s] = d pprint.pprint(data) # AttributeError if unzip not found except (urllib2.HTTPError, AttributeError): pass os.chdir('..') # run with emt from ase.calculators.emt import parameters from ase.tasks.main import run task = DeltaCodesDFTTask(calcfactory='emt', fit=(13, 0.06)) task.run(parameters.keys()) python-ase-3.9.1.4567/ase/test/tasks/mmbjmp.py0000664000175000017500000001010012553425527021177 0ustar jensjjensj00000000000000"""Collection of Heusler systems. From this paper: Markus Meinert Modified Becke-Johnson potential investigation of half-metallic Heusler compounds Phys. Rev. B 79, 085104 (2009) XXX http://arxiv.org/pdf/1210.7738v1.pdf """ # Data extracted with: # pdftotext -layout -f 2 -l 2 1210.7738v1.pdf - | "eaxp|mmBJ|Eg" \ # | tr -d '\n' | sed -E 's/[ \t]+/ /g' \ # | sed -n 's/NV/compound NV/p' \ # | sed -n 's/Eg.*PBE/EgPBE/p' | sed -n 's/ mBJ.*Eg/ EgmBJ/p' \ # | sed -e 's/^[ \t]*//' | sed -e 's/\s\+/,/g' # # pdftotext -layout -f 2 -l 2 1210.7738v1.pdf - | grep -E "[0-9][0-9]*" \ # | sed -n '/Co2 YZ Heusler compounds/,$p' \ # | sed -n '/become half-metals in mBJLDA/q;p' \ # | cut -c 62- | grep -v Heusler | sed '/^$/d' | sed -e 's/^[ \t]*//' \ # | sed -n 's/2 /2/p' | sed 's/\xe2\x80\x94/-/g' | sed -e 's/\s\+/,/g' from ase.atoms import string2symbols from ase.lattice.spacegroup import crystal class HeuslerMeinertCollection: data1 = """ #compound,NV,aexp,mexp,mPBE,EgPBE,mmBJ,EgmBJ,c Co2TiAl,25,5.85,0.74,1.00,0.40,1.00,1.11,1.12 Co2TiSn,26,6.08,1.96,2.00,0.47,2.00,1.16,1.17 Co2VAl,26,5.72,1.95,2.00,0.36*,2.00,0.65,1.13 Co2ZrSn,26,6.25,1.81,2.00,0.50,2.00,1.50,1.16 Co2CrGa,27,5.81,3.01,3.04,0.39*,3.00,1.06,1.18 Co2MnAl,28,5.75,4.04,4.03,0.61*,4.04,1.29*,1.14 Co2MnSi,29,5.65,4.97,5.00,0.81,5.00,1.42,1.15 Co2MnGe,29,5.75,4.93,5.00,0.57,5.00,1.49,1.19 Co2MnSn,29,5.98,5.08,5.03,0.39*,5.04,1.36*,1.19 Co2FeAl,29,5.73,4.96,4.99,0.06*,5.00,0.75,1.14 Co2FeGa,29,5.74,5.04,5.02,0.02*,5.00,0.80,1.20 Co2FeSi,30,5.64,5.97,5.47,0.11*,5.79,0.82*,1.16 Co2FeGe,30,5.74,5.90,5.63,0.09*,5.98,0.90*,1.20 Mn2VAl,22,5.92,1.94,2.00,0.28,2.00,0.48,1.09 Mn2VGa,22,5.91,1.88,1.99,0.02*,2.00,0.27,1.15 Fe2VAl,24,5.76,0.00,-,-,-,0.31,1.12 Fe2VGa,24,5.78,0.00,-,-,-,0.39,1.17 Fe2TiSn,24,6.09,0.00,-,-,-,0.69,1.16 Ru2MnSb,28,6.20,4.40,4.03,0.28*,4.06,0.44*,1.19 Ni2MnSn,31,6.05,4.05,4.03,-,4.17,-,1.19 Cu2MnAl,32,5.95,3.60,3.51,-,3.50,-,1.13 Cu2MnSn,33,6.17,4.11,3.86,-,3.91,-,1.19 Cr2CoGa,24,5.80,0.35,0.08,0.19*,0.03,0.66*,1.17 Mn2CoAl,26,5.84,1.95,2.00,0.43,2.00,0.68,1.12 Mn2CoGe,27,5.80,2.99,3.00,0.36,3.00,0.76,1.18 Fe2CoSi,29,5.65,4.99,4.96,-,5.00,0.57,1.16 """ data_ref = {} for l in data1.split(): if 'compound' not in l: l1 = l.split(',') row = [] for v in l1[1:]: if '*' in v: # gaps which are above or below the Fermi energy row.append(float(v[:-1])) elif v == '-': row.append(float(0.0)) else: row.append(float(v)) data_ref[l1[0]] = row data = data_ref.copy() names = [d.split(',')[0] for d in data1.split()][1:] labels = data1.split()[0].split(',') def __getitem__(self, name): d = self.data[name] # the index of label in labels less one # (compound is already as key in d) a = d[self.labels.index('aexp') - 1] if name in ['Cr2CoGa', 'Mn2CoAl', 'Mn2CoGe', 'Fe2CoSi']: # http://en.wikipedia.org/wiki/Space_group sg = 216 else: sg = 225 symbols = string2symbols(name) symbols.pop(0) b = crystal(symbols=symbols, basis=[(1. / 4, 1. / 4, 1. / 4), (0., 0., 0.), (1. / 2, 1. / 2, 1. / 2)], spacegroup=sg, cellpar=[a, a, a, 90, 90, 90], primitive_cell=True) # set average moments on all atoms (add + 2.0) magmom = d[self.labels.index('mexp') - 1] + 2.0 m = [magmom / len(b)] * len(b) # break spin symmetry between atoms no. 1 and 2 m[1] = m[1] + m[2] m[2] = - m[2] b.set_initial_magnetic_moments(m) if 0: from ase.visualize import view view(b) return b def keys(self): return self.names if __name__ == '__main__': HeuslerMeinertCollection()['Co2TiAl'] python-ase-3.9.1.4567/ase/test/tasks/gbrv.py0000664000175000017500000004727112553425527020700 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- import numpy as np u"""Collection of bulk systems. From this paper: Kevin F. Garrity , Joseph W. Bennett, Karin M. Rabe, David Vanderbilt Pseudopotentials for high-throughput DFT calculations Computational Materials Science 81 (2014) 446-452 http://dx.doi.org/10.1016/j.commatsci.2013.08.053 Data extracted to csv files with: * Table I:: pdftotext -layout -f 2 -l 2 mmc1.pdf - | tail -n +7| sed 's/\s\+/,/g' | sed 's/-/np.nan/g' | sed 's/−/np.nan/g' | sed 's/f,cc/fcc/g' | sed -E 's/^,fcc/e,fcc/' * Table II: pdftotext -layout -f 3 -l 3 mmc1.pdf - | tail -n +8| sed 's/\s\+/,/g' | sed 's/-/np.nan/g' | sed 's/−/np.nan/g' * Table III: pdftotext -layout -f 4 -l 4 mmc1.pdf - | tail -n +8| sed 's/\s\+/,/g' | sed 's/-/np.nan/g' | sed 's/−/np.nan/g' * Table IV/V/VI: pdftotext -layout -f 5 -l 5 mmc1.pdf - | tail -n +9| sed 's/\s\+/,/g' | sed 's/-/np.nan/g' | sed 's/−/np.nan/g' pdftotext -layout -f 6 -l 6 mmc1.pdf - | tail -n +5| sed 's/\s\+/,/g' | sed 's/-/np.nan/g' | sed 's/−/np.nan/g' pdftotext -layout -f 7 -l 7 mmc1.pdf - | tail -n +5| sed 's/\s\+/,/g' | sed 's/-/np.nan/g' | sed 's/−/np.nan/g' Note: they used cubic stuctures, 8x8x8 k-points and 0.002 Rydberg Fermi–Dirac smearing. The calculations of magnetic moments were on the non-spin-polarized structures (Table 2. from the article is available as csv download). """ import ase.units as units from ase import Atoms from ase.lattice.spacegroup import crystal from ase.lattice import bulk def perovskite(symbols, a): # perovskite ABX3 # http://cst-www.nrl.navy.mil/lattice/struk/e2_1.html u = 0.01 scaled_positions = [(0.00 , 0.00 , 0.00), (0.50+u, 0.50-u, 0.50+u), (0.00 , 0.50-u, 0.50+u), (0.50-u, 0.00 , 0.50+u), (0.50-u, 0.50+u, 0.00)] atoms = Atoms(symbols, cell=(a, a, a), pbc=True) atoms.set_scaled_positions(scaled_positions) return atoms.copy() def halfheusler(symbols, a): # See page 21 of http://d-nb.info/1021065781/34 # The inequivalent “stuffing atom” (Wycoff position 4c) third. b = crystal(symbols=symbols, basis=[(0., 0., 0.), (1./2, 1./2, 1./2), (1./4, 1./4, 1./4)], spacegroup=216, cellpar=[a, a, a, 90, 90, 90], primitive_cell=False) return b.copy() class GBRVBulkCollection: data = {} data['names'] = {} T1 = """ Element,aAE,aGBRV,aVASP,aPSLIB,aAE,aGBRV,aVASP,aPSLIB e,fcc,fcc,fcc,fcc,bcc,bcc,bcc,bcc H,2.283,2.284,2.283,2.284,1.806,1.807,1.807,1.806 Li,4.335,4.332,4.336,4.359,3.427,3.425,3.429,3.454 Be,3.166,3.175,3.170,3.160,2.506,2.514,2.508,2.501 B,2.872,2.873,2.872,2.871,2.323,2.325,2.323,2.322 C,3.103,3.103,3.104,3.103,2.366,2.366,2.367,2.365 O,3.178,3.175,3.172,3.172,2.511,2.511,2.508,2.508 N,np.nan,3.123,3.117,3.117,np.nan,2.456,2.449,2.449 F,3.447,3.430,3.433,3.433,2.730,2.714,2.717,2.720 Na,5.294,5.294,5.292,5.294,4.199,4.196,4.205,4.195 Mg,4.526,4.527,4.530,4.521,3.581,3.582,3.582,3.577 Al,4.043,4.043,4.044,4.040,3.242,3.242,3.242,3.239 Si,3.857,3.853,3.859,3.852,3.080,3.076,3.078,3.075 P,np.nan,3.917,3.893,3.889,np.nan,3.060,3.043,3.041 S,3.994,3.992,3.993,3.988,3.182,3.178,3.180,3.175 Cl,4.409,4.396,4.395,4.392,3.501,3.491,3.492,3.488 K,6.684,6.668,6.670,6.667,5.294,5.279,5.285,5.281 Ca,5.532,5.523,5.529,5.514,4.400,4.392,4.396,4.386 Sc,4.622,4.621,4.624,4.623,3.680,3.679,3.683,3.681 Ti,4.114,4.114,4.110,4.105,3.259,3.258,3.255,3.249 V,3.822,3.820,3.823,3.824,3.006,3.003,3.005,3.006 Cr,3.630,3.629,3.625,3.634,2.851,2.849,2.848,2.861 Mn,3.503,3.502,3.501,3.508,2.784,2.784,2.783,2.788 Fe,3.449,3.451,3.447,3.457,2.762,2.762,2.758,2.770 Co,3.457,3.455,3.457,3.463,2.762,2.761,2.761,2.766 Ni,3.515,3.511,3.516,3.517,2.793,2.790,2.794,2.795 Cu,3.638,3.639,3.641,3.654,2.885,2.886,2.885,2.896 Zn,3.936,3.936,3.939,3.931,3.128,3.128,3.130,3.127 Ga,4.240,4.244,4.242,4.247,3.364,3.366,3.364,3.369 Ge,4.283,4.282,4.283,4.283,3.397,3.396,3.397,3.396 As,4.272,4.276,4.273,4.272,3.383,3.386,3.385,3.383 Se,4.337,4.332,4.335,4.341,3.460,3.456,3.459,3.463 Br,4.732,4.726,4.726,4.731,3.765,3.762,3.762,3.765 Rb,7.183,7.155,7.160,7.155,5.680,5.659,5.665,5.659 Sr,6.030,6.022,6.022,6.020,4.756,4.750,4.749,4.748 Y,5.062,5.057,5.055,5.060,4.044,4.040,4.040,4.042 Zr,4.522,4.520,4.521,4.527,3.569,3.566,3.568,3.572 Nb,4.217,4.214,4.215,4.217,3.309,3.306,3.307,3.308 Mo,4.007,4.002,4.008,4.005,3.166,3.160,3.164,3.162 Tc,3.875,3.872,3.876,3.874,3.082,3.080,3.085,3.082 Ru,3.809,3.806,3.808,3.809,3.058,3.054,3.056,3.057 Rh,3.836,3.836,3.834,3.842,3.071,3.069,3.069,3.075 Pd,3.951,3.951,3.951,3.956,3.137,3.136,3.135,3.141 Ag,4.158,4.161,4.165,4.167,3.299,3.299,3.303,3.304 Cd,4.511,4.512,4.515,4.491,3.628,3.629,3.632,3.612 In,4.795,4.800,4.797,4.793,3.827,3.831,3.826,3.825 Sn,4.824,4.826,4.824,4.830,3.823,3.825,3.823,3.829 Sb,4.805,4.808,4.802,4.782,3.807,3.809,3.805,3.787 Te,4.840,4.840,4.837,4.854,3.867,3.865,3.865,3.877 I,5.201,5.195,5.198,5.192,4.149,4.149,4.151,4.144 Cs,7.821,7.789,7.794,7.808,6.172,6.147,6.145,6.161 Ba,6.347,6.338,6.345,6.344,5.023,5.018,5.023,5.023 La,5.267,5.277,5.290,5.387,4.235,4.239,4.248,4.297 Hf,4.488,4.491,4.483,4.483,3.551,3.554,3.549,3.548 Ta,4.235,4.232,4.235,4.227,3.333,3.331,3.332,3.327 W,4.041,4.042,4.042,4.046,3.188,3.187,3.187,3.190 Re,3.917,3.915,3.919,3.919,3.118,3.115,3.120,3.119 Os,3.858,3.855,3.861,3.861,3.096,3.091,3.099,3.103 Ir,3.881,3.875,3.877,3.888,3.113,3.107,3.110,3.118 Pt,3.970,3.964,3.970,3.984,3.166,3.160,3.165,3.176 Au,4.168,4.163,4.166,4.180,3.306,3.302,3.304,3.316 Hg,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan,np.nan Tl,4.996,5.004,4.997,4.962,3.977,3.980,3.975,3.974 Pb,5.045,5.039,5.044,5.044,4.008,4.003,4.007,4.007 Bi,5.038,5.035,5.035,5.041,3.984,3.981,3.982,3.979 """ data['fcc'] = {} for line in T1.split(): if 'fcc' not in line and 'Element' not in line: l = line.split(',') try: data['fcc'].update( {l[0]: float(l[T1.split()[1].split(',').index('fcc')])} ) except ValueError: pass if 0: # original set data['names']['fcc'] = [l.split(',')[0] for l in T1.split()[2:] if l.split(',')[1] != 'np.nan'] else: # add missing elements: N, P, Hg - FHI-AIMS tight data['fcc'].update({'N': 3.12}) data['fcc'].update({'P': 3.88}) data['fcc'].update({'Hg': 5.07}) data['names']['fcc'] = [l.split(',')[0] for l in T1.split()[2:]] data['bcc'] = {} for line in T1.split(): if 'bcc' not in line and 'Element' not in line: l = line.split(',') try: data['bcc'].update( {l[0]: float(l[T1.split()[1].split(',').index('bcc')])} ) except ValueError: pass if 0: # original set data['names']['bcc'] = [l.split(',')[0] for l in T1.split()[2:] if l.split(',')[1] != 'np.nan'] else: # add missing elements: N, P, Hg - FHI-AIMS tight data['bcc'].update({'N': 2.44}) data['bcc'].update({'P': 3.06}) data['bcc'].update({'Hg': 3.86}) data['names']['bcc'] = [l.split(',')[0] for l in T1.split()[2:]] T2 = """ Element,aAE,aGBRV,aVASP,aPSLIB LiCl,5.161,5.151,5.150,5.160 NaCl,5.714,5.701,5.701,5.696 KCl,6.391,6.382,6.391,6.384 RbCl,6.710,6.698,6.705,6.701 CsCl,7.088,7.072,7.085,7.088 BeO,3.650,3.653,3.654,3.638 MgO,4.259,4.259,4.261,4.250 CaO,4.839,4.834,4.842,4.828 SrO,5.204,5.198,5.208,5.201 BaO,5.590,5.597,5.617,5.603 ScN,4.516,4.514,4.519,4.516 YN,4.911,4.908,4.906,4.915 LaN,5.314,5.314,5.328,5.349 TiO,4.288,4.288,4.288,4.283 VO,4.192,4.190,4.191,4.192 CrO,4.139,4.139,4.134,4.142 MnO,4.108,4.110,4.103,4.110 FeO,4.096,4.103,4.092,4.103 CoO,4.106,4.108,4.102,4.108 NiO,4.166,4.170,4.167,4.169 CuO,4.248,4.250,4.246,4.260 ZnO,4.332,4.338,4.340,4.330 ZrO,4.608,4.605,4.607,4.621 NbO,4.476,4.474,4.471,4.475 MoO,4.419,4.417,4.419,4.417 TcO,4.398,4.396,4.394,4.394 RuO,4.411,4.408,4.405,4.408 RhO,4.450,4.455,4.449,4.455 PdO,4.544,4.550,4.541,4.547 AgO,4.677,4.680,4.675,4.684 CdO,4.774,4.783,4.785,4.762 HfO,4.611,4.596,4.584,4.574 TaO,4.506,4.503,4.504,4.483 WO,4.466,4.470,4.467,4.466 ReO,4.455,4.459,np.nan,4.461 OsO,4.487,4.487,4.497,4.492 IrO,4.542,4.540,4.545,4.548 PtO,4.624,4.621,4.622,4.637 AuO,4.759,4.754,4.752,4.769 HgO,4.929,4.933,4.938,4.913 BN,3.506,3.506,3.505,3.504 AlN,4.073,4.079,4.070,4.068 GaN,4.269,4.275,4.274,4.285 InN,4.708,4.713,4.711,4.714 TlN,4.957,4.963,4.963,4.968 CO,3.977,3.982,3.974,3.972 SiO,4.616,4.617,4.615,4.612 GeO,4.773,4.775,4.773,4.772 SnO,5.120,5.122,5.119,5.125 PbO,5.269,5.263,5.266,5.268 AlN,4.073,4.079,4.070,4.068 AlP,5.075,5.077,5.072,5.068 AlAs,5.303,5.307,5.298,5.301 AlSb,5.774,5.761,5.765,5.752 AlBi,5.987,5.976,5.977,5.976 SrS,6.063,6.057,6.065,6.060 SrSe,6.301,6.297,6.304,6.300 SrTe,6.724,6.720,6.726,6.728 LiF,4.076,4.074,4.067,4.081 LiBr,5.521,5.512,5.511,5.524 LiI,6.038,6.020,6.021,6.030 NaF,4.711,4.717,4.708,4.705 NaBr,6.049,6.040,6.040,6.037 NaI,6.540,6.534,6.537,6.529 """ data['rocksalt'] = {} for line in T2.split(): if 'Element' not in line: l = line.split(',') data['rocksalt'].update( {l[0]: float(l[T2.split()[0].split(',').index('aAE')])} ) data['names']['rocksalt'] = [l.split(',')[0] for l in T2.split()[1:]] T3 = """ Element,aAE,aGBRV,aVASP,aPSLIB SrLiF3,3.884,3.881,3.884,3.884 NaNbO3,3.981,3.981,3.976,3.980 KMgF3,4.059,4.057,4.062,4.052 CsMgF3,4.258,4.255,4.261,4.255 MgTiO3,3.839,3.840,3.839,3.839 CaTiO3,3.886,3.887,3.888,3.886 SrTiO3,3.941,3.942,3.943,3.942 BaTiO3,4.024,4.031,4.035,4.030 BiScO3,4.074,4.074,4.079,4.076 BiYO3,4.335,4.334,4.331,4.343 SrVO3,3.862,3.863,3.866,3.867 SrCrO3,3.820,3.821,3.819,3.826 SrMnO3,3.799,3.800,3.798,3.808 SrFeO3,3.801,3.802,3.802,3.812 SrCoO3,3.811,3.810,3.812,3.823 SrNiO3,3.843,3.842,3.849,3.853 KNiF3,4.039,4.036,4.036,4.042 KCuF3,4.085,4.084,4.084,4.095 KZnF3,4.132,4.133,4.139,4.130 SrZrO3,4.176,4.175,4.177,4.187 SrNbO3,4.067,4.066,4.064,4.066 SrMoO3,4.002,4.001,4.003,4.002 SrTcO3,3.967,3.968,3.966,3.968 SrRuO3,3.959,3.959,3.956,3.962 SrRhO3,3.982,3.987,3.981,3.991 KPdF3,4.312,4.314,4.309,4.315 SrAgF3,4.536,4.535,4.535,4.537 KCdF3,4.463,4.471,4.477,4.458 LaAlO3,3.816,3.819,3.822,3.829 SrHfO3,4.155,4.148,4.146,4.133 SrTaO3,4.066,4.067,4.067,4.050 SrWO3,4.014,4.020,4.019,4.013 SrReO3,3.986,3.989,3.997,3.994 SrOsO3,3.982,3.983,3.992,3.988 SrIrO3,3.994,3.996,4.006,4.018 SrPtO3,4.040,4.039,4.039,4.079 BiAuO3,4.151,4.152,4.147,4.171 KHgF3,4.594,4.602,4.608,4.587 TlCTi3,4.263,4.261,4.260,4.259 LaBRh3,4.288,4.283,4.287,4.306 BiAlO3,3.797,3.800,3.795,3.795 BiInO3,4.170,4.175,4.178,4.179 SrSiO3,3.695,3.695,3.698,3.694 SrGeO3,3.855,3.860,3.860,3.865 SnTiO3,3.949,3.950,3.949,3.950 PbTiO3,3.971,3.970,3.971,3.971 PNCa3,4.725,4.721,4.728,4.714 AsNCa3,4.769,4.766,4.772,4.759 SbNCa3,4.872,4.868,4.875,4.862 SrTiS3,4.786,4.781,4.785,4.781 SrTiSe3,5.030,5.029,5.033,5.034 BaZrTe3,5.681,5.679,5.684,5.691 KMgCl3,5.028,5.024,5.026,5.018 CsPbBr3,5.994,5.999,6.003,6.009 CsPbI3,6.383,6.393,6.396,6.397 """ data['perovskite'] = {} for line in T3.split(): if 'Element' not in line: l = line.split(',') data['perovskite'].update( {l[0]: float(l[T3.split()[0].split(',').index('aAE')])} ) data['names']['perovskite'] = [l.split(',')[0] for l in T3.split()[1:]] T456 = """ Element,aAE,aGBRV,aVASP,aPSLIB AgAlGe,6.224,6.220,6.223,6.221 AgAlSn,6.595,6.594,6.596,6.600 AgCaBi,7.161,7.155,7.163,7.153 AgYSi,6.501,6.496,6.499,6.502 AlBeB,4.963,4.966,4.964,4.958 AlLiGe,6.022,6.015,6.014,6.017 AlLiSi,5.931,5.933,5.936,5.938 AuLiSb,6.449,6.440,6.431,6.450 BaZnTi,6.946,6.955,6.982,6.967 BeScB,5.321,5.317,5.324,5.318 BiMgCu,6.444,6.438,6.440,6.444 BiScNi,6.271,6.261,6.265,6.267 BiYNi,6.502,6.494,6.495,6.501 BiYPd,6.736,6.731,6.734,6.738 BiZrCo,6.235,6.225,6.226,6.236 BiZrNi,6.300,6.288,6.291,6.299 CaZnSn,6.923,6.923,6.928,6.924 CaZnZr,6.834,6.823,6.834,6.829 CdPLi,5.969,5.955,5.952,5.945 CoMnSb,5.835,5.833,5.824,5.851 CoNbSn,6.186,6.176,6.175,6.186 CoSnMo,6.107,6.096,6.099,6.105 CoSnNb,6.222,6.211,6.211,6.218 CoSnTc,6.034,6.023,6.024,6.032 CoSnTi,6.121,6.115,6.115,6.118 CoZrSb,6.328,6.320,6.319,6.333 CrSbNi,5.803,5.805,5.800,5.814 CsZnBi,8.016,8.002,8.018,8.043 CuAlGe,5.920,5.912,5.910,5.916 CuAlSn,6.332,6.327,6.325,6.337 CuMgAs,6.057,6.057,6.052,6.057 CuMgSn,6.436,6.432,6.433,6.439 CuScSn,6.461,6.456,6.459,6.467 CuYSi,6.310,6.302,6.302,6.312 CuYSn,6.732,6.729,6.728,6.741 FeSnTi,6.118,6.115,6.111,6.119 InLiGe,6.398,6.397,6.394,6.397 IrMnSn,6.044,6.033,6.032,6.050 KZnBi,7.428,7.418,7.426,7.432 LiAlSn,6.459,6.454,6.453,6.459 LiAuS,6.015,5.994,5.993,6.008 LiBaP,7.139,7.148,7.164,7.158 LiCaP,6.497,6.492,6.498,6.491 LiCGa,5.088,5.091,5.091,5.100 LiCuS,5.578,5.576,5.574,5.594 LiCuSe,5.863,5.859,5.858,5.880 LiCuTe,6.273,6.273,6.261,6.294 LiLaGe,6.930,6.927,6.934,6.960 LiMgN,5.005,5.008,5.008,5.011 LiSiGa,5.881,5.882,5.881,5.887 LiSnIn,6.799,6.799,6.796,6.801 LiSrP,6.817,6.813,6.819,6.818 LiYSn,7.009,7.006,7.005,7.014 LiZnN,4.923,4.929,4.929,4.928 MgPLi,5.775,5.776,5.776,5.776 MgSbCu,6.259,6.257,6.257,6.256 MgSbNi,6.099,6.094,6.094,6.093 MgSbPd,6.354,6.351,6.349,6.351 MgSbPt,6.364,6.359,6.357,6.362 MgSnCu,6.247,6.248,6.248,6.257 MgSrGe,7.069,7.067,7.072,7.064 MgSrSi,7.012,7.009,7.016,7.008 MgSrSn,7.427,7.424,7.428,7.422 MgZnHf,6.579,6.576,6.573,6.572 MnPdTe,6.059,6.075,6.036,6.068 MnPtGa,5.744,5.743,5.744,5.756 MnPtSb,6.064,6.053,6.048,6.076 MnRhSb,6.001,5.991,5.982,6.010 MnSbCo,5.720,5.724,5.718,5.737 MnSbCu,5.853,5.857,5.850,5.868 MnSbIr,6.033,6.022,6.017,6.035 MnSbNi,5.758,5.760,5.755,5.771 MnSbOs,6.017,6.004,6.003,6.015 MnSbPt,6.106,6.096,6.090,6.112 MnSbRe,6.045,6.036,6.033,6.040 MnSbRh,5.996,5.988,5.980,5.998 MnSbTa,6.246,6.239,6.237,6.233 MnSbW,6.116,6.107,6.104,6.110 MnSnPt,6.093,6.081,6.082,6.098 NaAgO,5.708,5.711,5.709,5.706 NaAlGe,6.387,6.384,6.386,6.380 NaBGe,5.750,5.754,5.754,5.748 NaMgN,5.446,5.452,5.450,5.439 NaYGe,6.897,6.897,6.899,6.899 NaYSn,7.286,7.282,7.284,np.nan NaZnBi,6.951,6.948,6.954,6.995 NaZnP,6.150,6.148,6.149,6.143 NaZnSb,6.765,6.765,6.764,6.764 NbRhSn,6.295,6.289,6.289,6.301 NbSbFe,5.972,5.963,5.956,5.970 NbSbRh,6.220,6.215,6.213,6.220 NbSbRu,6.197,6.191,6.189,np.nan NiHfSn,6.341,6.334,6.329,6.332 NiSbMn,5.817,5.818,5.813,5.824 NiSbTi,6.177,6.169,6.167,6.160 NiSnTi,6.167,6.162,6.162,6.162 NiSnZr,6.467,6.459,6.462,6.467 NiTiSn,6.146,6.141,6.142,6.145 PbYAu,6.856,6.845,6.849,6.857 PdHfSn,6.483,6.477,6.474,6.481 PdSbMn,6.002,5.994,5.987,5.999 PdTiGe,5.980,5.971,5.973,5.972 PdZrSn,6.507,6.503,6.506,6.514 PtHfSn,6.449,6.442,6.439,6.448 PtSbMn,5.998,5.989,5.985,6.001 PtSnMn,5.996,5.990,5.990,6.007 PtSnSc,6.494,6.487,6.493,6.496 PZnLi,5.637,5.642,5.639,5.645 RbZnBi,7.694,7.683,7.689,7.697 RhSbMn,5.922,5.912,5.906,5.919 RhTiGa,5.917,5.907,5.910,5.910 SbCdAg,6.688,6.693,6.693,6.679 SbCdAu,6.684,6.685,6.682,6.676 SbCuCd,6.566,6.570,6.567,6.554 SbHgAg,6.735,6.738,6.738,6.725 SbScNi,6.127,6.119,6.122,6.123 SbScPd,6.385,6.381,6.383,6.384 SbScPt,6.399,6.393,6.396,6.398 SbTaCo,5.983,5.971,5.970,5.970 SbTaRu,6.196,6.189,6.188,np.nan SbTiCo,5.896,5.897,5.894,5.902 SbTiFe,5.943,5.936,5.929,5.942 SbTiNi,5.965,5.956,5.953,5.957 SbTiRu,6.165,6.159,6.157,np.nan SbVCo,5.810,5.811,5.809,5.821 SbVFe,5.795,5.798,5.792,5.809 SbVNi,5.867,5.868,5.866,5.874 SbVRu,6.053,6.044,6.042,np.nan SbYNi,6.371,6.365,6.364,6.368 SbYPt,6.623,6.620,6.620,6.626 SbZrRu,6.347,6.343,6.342,np.nan SbZrTc,6.402,6.398,6.399,6.403 ScSnAu,6.518,6.512,6.515,6.521 SnTiNi,5.959,5.953,5.953,5.958 SnTiPt,6.239,6.231,6.236,6.239 SrAlGa,6.875,6.870,6.876,6.872 SrCdSi,6.966,6.966,6.974,6.961 TlLiGe,6.564,6.563,6.559,6.561 """ data['halfheusler'] = {} for line in T456.split(): if 'Element' not in line: l = line.split(',') data['halfheusler'].update( {l[0]: float(l[T456.split()[0].split(',').index('aAE')])} ) data['names']['halfheusler'] = [l.split(',')[0] for l in T456.split()[1:]] magnetic_moments = """ Compound,μAE,μGBRV,μVASP,μPSLIB TiO,0.08,0.08,0.04,0.07 VO,1.55,1.54,1.44,1.55 CrO,2.91,2.98,2.97,2.90 MnO,3.83,3.90,3.84,3.82 FeO,3.83,3.85,3.83,3.83 CoO,2.59,2.78,2.69,2.59 NiO,1.82,1.75,1.01,1.83 MoO,0.42,0.43,0.42,0.42 TcO,2.02,2.01,2.01,2.02 RuO,1.44,1.43,1.45,1.44 RhO,0.36,0.36,0.37,0.36 ReO,0.11,0.11,0.09,0.11 OsO,1.79,1.79,1.79,1.79 IrO,0.79,0.80,0.79,0.79 """ data['magnetic_moments'] = {} for line in magnetic_moments.split(): if 'Compound' not in line: l = line.split(',') data['magnetic_moments'].update( {l[0]: float(l[magnetic_moments.split(',').index('μAE')])} ) data['names']['magnetic_moments'] = [l.split(',')[0] for l in magnetic_moments.split()[1:]] def __init__(self, category='fcc'): assert category in ['fcc', 'bcc', 'rocksalt', 'perovskite', 'halfheusler', 'magnetic_moments'] self.category = category self.names = self.data['names'][category] self.d = self.data[category] def __getitem__(self, name): a = self.d[name] c = self.category if c in ['fcc', 'bcc', 'rocksalt']: b = bulk(name, crystalstructure=c, a=a, cubic=True) elif c == 'perovskite': b = perovskite(name, a) elif c == 'halfheusler': b = halfheusler(name, a) elif c == 'magnetic_moments': b = bulk(name, crystalstructure='rocksalt', a=self.data['rocksalt'][name], cubic=True) b.set_initial_magnetic_moments([a * 4 / len(b) for i in range(len(b))]) return b def keys(self): return self.names if __name__ == '__main__': from ase.calculators.emt import EMT from ase.test.tasks.gbrv import GBRVBulkCollection from ase.units import kJ from ase.utils.eos import EquationOfState c = GBRVBulkCollection(category='fcc') volumes = [] energies = [] for name in ['Ag']: b = c[name] cell = b.get_cell() for x in np.linspace(0.95, 1.05, 5): b.set_cell(cell * x, scale_atoms=True) b.set_calculator(EMT()) volumes.append(b.get_volume()) energies.append(b.get_potential_energy()) eos = EquationOfState(volumes, energies) v0, e0, B = eos.fit() print(B / kJ * 1.0e24, 'GPa') python-ase-3.9.1.4567/ase/test/tasks/htb.py0000664000175000017500000004477712553425527020525 0ustar jensjjensj00000000000000"""Collection of bulk systems. From this paper: Philipp Haas, Fabien Tran, Peter Blaha Calculation of the lattice constant of solids with semilocal functionals Phys. Rev. B 79, 085104 (2009) dx.doi.org/10.1103/PhysRevB.79.085104 Data extracted to csv files with: * lattice constant:: pdftotext -layout -f 3 -l 4 e085104.pdf - | sed -n '/Solid/,$p' \ | sed -n '/me /q;p' | grep -E -v "085104|TRAN|TABLE" \ | sed '/^$/d' | sed -e 1b -e '/^Solid/d' \ | sed 's/Expt./Expt1. Expt2./' | sed 's/Solid/Solid Str/' \ | sed -e 's/\s\+/,/g' * erratum:: pdftotext -layout e209902.pdf - | sed -n '/Solid/,$p' | sed -n '/me /q;p' \ | sed '/^$/d' \ | sed 's/Expt./Expt1. Expt2./' | sed 's/Solid/Solid Str/' \ | sed -e 's/\s\+/,/g' """ import ase.units as units from ase.lattice import bulk from ase.tasks.io import read_json from ase.tasks.bulk import BulkTask from ase.utils.eos import EquationOfState strukturbericht = {'A1': 'fcc', 'A2': 'bcc', 'A4': 'diamond', 'B1': 'rocksalt', 'B2': 'cesiumchloride', 'B3': 'zincblende', 'C1': 'fluorite'} class HaasTranBlahaBulkCollection: # e085104.pdf, lattice constant data1 = """ Solid,Str,LDA,SOGGA,PBEsol,WC,AM05,TPSS,PBE,Expt1.,Expt2. Li,A2,3.363,3.435,3.433,3.449,3.456,3.455,3.435,3.451,3.477 Na,A2,4.047,4.175,4.170,4.199,4.209,4.237,4.196,4.209,4.225 K,A2,5.045,5.231,5.213,5.256,5.293,5.352,5.282,5.212,5.225 Rb,A2,5.374,5.605,5.579,5.609,5.692,5.749,5.670,5.577,5.585 Ca,A1,5.333,5.469,5.456,5.458,5.491,5.533,5.530,5.556,5.565 Sr,A1,5.786,5.930,5.917,5.914,5.975,6.018,6.027,6.040,6.048 Ba,A2,4.754,4.881,4.881,4.870,4.963,4.991,5.030,5.002,5.007 V,A2,2.932,2.959,2.963,2.965,2.961,2.979,3.001,3.024,3.028 Nb,A2,3.250,3.268,3.274,3.280,3.271,3.297,3.312,3.294,3.296 Ta,A2,3.257,3.280,3.285,3.290,3.281,3.300,3.323,3.299,3.301 Mo,A2,3.116,3.126,3.133,3.139,3.128,3.151,3.164,3.141,3.144 W,A2,3.143,3.155,3.162,3.167,3.156,3.173,3.191,3.160,3.162 Fe,A2,2.754,2.783,2.790,2.793,2.787,2.804,2.833,2.853,2.861 Rh,A1,3.759,3.772,3.785,3.795,3.777,3.807,3.834,3.793,3.798 Ir,A1,3.828,3.834,3.847,3.857,3.837,3.867,3.887,3.831,3.835 Ni,A1,3.423,3.453,3.463,3.468,3.461,3.478,3.518,3.508,3.516 Pd,A1,3.848,3.867,3.882,3.892,3.878,3.909,3.948,3.876,3.881 Pt,A1,3.909,3.917,3.932,3.944,3.923,3.958,3.985,3.913,3.916 Cu,A1,3.522,3.557,3.570,3.573,3.568,3.585,3.632,3.596,3.603 Ag,A1,4.007,4.038,4.058,4.065,4.059,4.093,4.152,4.062,4.069 Au,A1,4.047,4.061,4.081,4.092,4.074,4.115,4.154,4.062,4.065 Al,A1,3.983,4.008,4.018,4.023,4.008,4.015,4.041,4.019,4.032 C,A4,3.536,3.552,3.557,3.558,3.553,3.573,3.575,3.544,3.567 Si,A4,5.407,5.425,5.438,5.437,5.439,5.466,5.475,5.415,5.430 Ge,A4,5.632,5.662,5.684,5.686,5.688,5.734,5.769,5.639,5.652 Sn,A4,6.481,6.521,6.547,6.548,6.566,6.621,6.661,6.474,6.482 Pb,A1,4.874,4.899,4.931,4.936,4.945,4.997,5.048,4.912,4.916 Th,A1,4.920,4.928,4.959,4.977,4.954,5.032,5.056,5.071,5.074 LiF,B1,3.919,4.008,4.013,4.017,4.046,4.047,4.071,3.960,4.010 LiCl,B1,4.986,5.062,5.081,5.087,5.142,5.151,5.167,5.072,5.106 NaF,B1,4.507,4.637,4.635,4.652,4.682,4.702,4.709,4.576,4.609 NaCl,B1,5.484,5.608,5.619,5.637,5.696,5.715,5.714,5.565,5.595 MgO,B1,4.169,4.217,4.222,4.223,4.228,4.244,4.261,4.186,4.207 MgS,B1,5.139,5.174,5.190,5.195,5.197,5.237,5.238,5.182,5.202 CaO,B1,4.719,4.771,4.778,4.777,4.790,4.819,4.841,4.787,4.803 TiC,B1,4.266,4.294,4.302,4.303,4.297,4.336,4.339,4.317,4.330 TiN,B1,4.178,4.202,4.210,4.214,4.206,4.241,4.254,4.228,4.239 ZrC,B1,4.647,4.664,4.675,4.680,4.670,4.711,4.715,4.688,4.696 ZrN,B1,4.532,4.549,4.560,4.565,4.555,4.590,4.602,4.574,4.585 HfC,B1,4.578,4.602,4.613,4.618,4.606,4.646,4.660,4.627,4.638 HfN,B1,4.482,4.506,4.515,4.520,4.510,4.543,4.560,4.512,4.520 VC,B1,4.095,4.114,4.123,4.129,4.116,4.151,4.162,4.148,4.160 VN,B1,4.050,4.071,4.081,4.087,4.075,4.112,4.125,4.126,4.141 NbC,B1,4.432,4.446,4.457,4.462,4.448,4.487,4.491,4.462,4.470 NbN,B1,4.361,4.374,4.385,4.392,4.378,4.419,4.426,4.383,4.392 FeAl,B2,2.812,2.837,2.840,2.843,2.839,2.850,2.869,2.882,2.889 CoAl,B2,2.795,2.820,2.824,2.826,2.822,2.833,2.853,2.855,2.861 NiAl,B2,2.834,2.859,2.864,2.866,2.862,2.873,2.894,2.882,2.887 BN,B3,3.585,3.605,3.610,3.610,3.607,3.628,3.629,3.585,3.607 BP,B3,4.496,4.514,4.525,4.526,4.522,4.553,4.553,4.520,4.538 BAs,B3,4.740,4.761,4.775,4.778,4.772,4.808,4.816,4.760,4.777 AlP,B3,5.440,5.464,5.476,5.474,5.479,5.504,5.513,5.445,5.460 AlAs,B3,5.636,5.668,5.681,5.680,5.687,5.713,5.734,5.646,5.658 GaN,B3,4.463,4.492,4.502,4.504,4.501,4.536,4.551,4.520,4.531 GaP,B3,5.401,5.429,5.447,5.448,5.451,5.498,5.514,5.435,5.448 GaAs,B3,5.616,5.650,5.670,5.672,5.678,5.724,5.757,5.637,5.648 InP,B3,5.839,5.869,5.890,5.890,5.898,5.958,5.968,5.856,5.866 InAs,B3,6.038,6.076,6.098,6.100,6.111,6.167,6.195,6.044,6.054 SiC,B3,4.333,4.354,4.360,4.360,4.357,4.371,4.384,4.340,4.358 CeO2,C1,5.371,5.396,5.410,5.415,5.414,5.454,5.475,5.393,5.401 """ data_ref = {} for l in data1.split(): if 'Solid' not in l: l1 = l.split(',') data_ref[l1[0]] = [l1[1]] data_ref[l1[0]].extend([float(v) for v in l1[2:]]) # e209902.pdf, lattice constant data2 = """ Solid,Str,LDA,SOGGA,PBEsol,WC,AM05,TPSS,PBE,Expt1.,Expt2. Rb,A2,5.372,5.592,5.570,5.608,5.676,5.749,5.668,5.577,5.585 Pd,A1,3.840,3.859,3.875,3.884,3.870,3.905,3.942,3.876,3.881 Ge,A4,5.625,5.656,5.678,5.681,5.683,5.724,5.763,5.639,5.652 Sn,A4,6.473,6.513,6.540,6.541,6.557,6.615,6.655,6.474,6.482 LiF,B1,3.911,4.003,4.006,4.012,4.038,4.039,4.068,3.960,4.010 LiCl,B1,4.965,5.042,5.063,5.069,5.118,5.115,5.150,5.072,5.106 NaCl,B1,5.465,5.594,5.605,5.623,5.682,5.704,5.700,5.565,5.595 MgS,B1,5.132,5.169,5.184,5.189,5.191,5.224,5.231,5.182,5.202 HfN,B1,4.472,4.497,4.506,4.511,4.501,4.541,4.550,4.512,4.520 AlAs,B3,5.630,5.663,5.676,5.676,5.680,5.706,5.729,5.646,5.658 GaAs,B3,5.607,5.642,5.662,5.664,5.670,5.715,5.747,5.637,5.648 InP,B3,5.825,5.862,5.880,5.882,5.886,5.951,5.961,5.856,5.866 InAs,B3,6.027,6.065,6.088,6.091,6.102,6.161,6.187,6.044,6.054 CeO2,C1,5.356,5.379,5.394,5.399,5.397,5.439,5.459,5.393,5.401 """ for l in data2.split(): if 'Solid' not in l: l1 = l.split(',') data_ref[l1[0]] = [l1[1]] data_ref[l1[0]].extend([float(v) for v in l1[2:]]) # F. Tran, private communication, lattice constant data3 = """ Solid,Str,LDA,SOGGA,PBEsol,WC,AM05,TPSS,PBE,Expt2. Li,A2,3.363,3.435,3.433,3.449,3.456,3.455,3.435,3.451 Na,A2,4.047,4.175,4.170,4.199,4.209,4.237,4.196,4.209 K,A2,5.045,5.231,5.213,5.256,5.293,5.352,5.282,5.212 Rb,A2,5.372,5.592,5.570,5.608,5.676,5.749,5.668,5.577 Ca,A1,5.333,5.469,5.456,5.458,5.491,5.533,5.530,5.556 Sr,A1,5.786,5.930,5.917,5.914,5.975,6.018,6.027,6.040 Ba,A2,4.754,4.881,4.881,4.870,4.963,4.991,5.030,5.002 V,A2,2.932,2.959,2.963,2.965,2.961,2.979,3.001,3.024 Nb,A2,3.250,3.268,3.274,3.280,3.271,3.297,3.312,3.294 Ta,A2,3.257,3.280,3.285,3.290,3.281,3.300,3.323,3.299 Mo,A2,3.116,3.126,3.133,3.139,3.128,3.151,3.164,3.141 W,A2,3.143,3.155,3.162,3.167,3.156,3.173,3.191,3.160 Fe,A2,2.754,2.783,2.790,2.793,2.787,2.804,2.833,2.853 Rh,A1,3.759,3.772,3.785,3.795,3.777,3.807,3.834,3.793 Ir,A1,3.828,3.834,3.847,3.857,3.837,3.867,3.887,3.831 Ni,A1,3.423,3.453,3.463,3.468,3.461,3.478,3.518,3.508 Pd,A1,3.840,3.859,3.875,3.884,3.870,3.905,3.942,3.876 Pt,A1,3.909,3.917,3.932,3.944,3.923,3.958,3.985,3.913 Cu,A1,3.522,3.557,3.570,3.573,3.568,3.585,3.632,3.596 Ag,A1,4.007,4.038,4.058,4.065,4.059,4.093,4.152,4.062 Au,A1,4.047,4.061,4.081,4.092,4.074,4.115,4.154,4.062 Al,A1,3.983,4.008,4.018,4.023,4.008,4.015,4.041,4.019 C,A4,3.536,3.552,3.557,3.558,3.553,3.573,3.575,3.544 Si,A4,5.407,5.425,5.438,5.437,5.439,5.466,5.475,5.415 Ge,A4,5.625,5.656,5.678,5.681,5.683,5.724,5.763,5.639 Sn,A4,6.473,6.513,6.540,6.541,6.557,6.615,6.655,6.474 Pb,A1,4.874,4.899,4.931,4.936,4.945,4.997,5.048,4.912 Th,A1,4.920,4.928,4.959,4.977,4.954,5.032,5.056,5.071 LiF,B1,3.911,4.003,4.006,4.012,4.038,4.039,4.068,3.960 LiCl,B1,4.965,5.042,5.063,5.069,5.118,5.115,5.150,5.072 NaF,B1,4.507,4.637,4.635,4.652,4.682,4.702,4.709,4.576 NaCl,B1,5.465,5.594,5.605,5.623,5.682,5.704,5.700,5.565 MgO,B1,4.169,4.217,4.222,4.223,4.228,4.244,4.261,4.186 MgS,B1,5.132,5.169,5.184,5.189,5.191,5.224,5.231,5.182 CaO,B1,4.719,4.771,4.778,4.777,4.790,4.819,4.841,4.787 TiC,B1,4.266,4.294,4.302,4.303,4.297,4.336,4.339,4.317 TiN,B1,4.178,4.202,4.210,4.214,4.206,4.241,4.254,4.228 ZrC,B1,4.647,4.664,4.675,4.680,4.670,4.711,4.715,4.688 ZrN,B1,4.532,4.549,4.560,4.565,4.555,4.590,4.602,4.574 HfC,B1,4.578,4.602,4.613,4.618,4.606,4.646,4.660,4.627 HfN,B1,4.472,4.497,4.506,4.511,4.501,4.541,4.550,4.512 VC,B1,4.095,4.114,4.123,4.129,4.116,4.151,4.162,4.148 VN,B1,4.050,4.071,4.081,4.087,4.075,4.112,4.125,4.126 NbC,B1,4.432,4.446,4.457,4.462,4.448,4.487,4.491,4.462 NbN,B1,4.361,4.374,4.385,4.392,4.378,4.419,4.426,4.383 FeAl,B2,2.812,2.837,2.840,2.843,2.839,2.850,2.869,2.882 CoAl,B2,2.795,2.820,2.824,2.826,2.822,2.833,2.853,2.855 NiAl,B2,2.834,2.859,2.864,2.866,2.862,2.873,2.894,2.882 BN,B3,3.585,3.605,3.610,3.610,3.607,3.628,3.629,3.585 BP,B3,4.496,4.514,4.525,4.526,4.522,4.553,4.553,4.520 BAs,B3,4.740,4.761,4.775,4.778,4.772,4.808,4.816,4.760 AlP,B3,5.440,5.464,5.476,5.474,5.479,5.504,5.513,5.445 AlAs,B3,5.630,5.663,5.676,5.676,5.680,5.706,5.729,5.646 GaN,B3,4.463,4.492,4.502,4.504,4.501,4.536,4.551,4.520 GaP,B3,5.401,5.429,5.447,5.448,5.451,5.498,5.514,5.435 GaAs,B3,5.607,5.642,5.662,5.664,5.670,5.715,5.747,5.637 InP,B3,5.825,5.862,5.880,5.882,5.886,5.951,5.961,5.856 InAs,B3,6.027,6.065,6.088,6.091,6.102,6.161,6.187,6.044 SiC,B3,4.333,4.354,4.360,4.360,4.357,4.371,4.384,4.340 CeO2,C1,5.356,5.379,5.394,5.399,5.397,5.439,5.459,5.393 """ data_priv = {} for l in data3.split(): if 'Solid' not in l: l1 = l.split(',') data_priv[l1[0]] = [l1[1]] data_priv[l1[0]].extend([float(v) for v in l1[2:]]) # F. Tran, private communication, bulk modulus data4 = """ Solid,Str,LDA,SOGGA,PBEsol,WC,AM05,TPSS,PBE,Expt2. Li,A2,15.2,13.7,13.7,13.4,13.2,13.5,14.0,13.0 Na,A2,9.41,7.91,7.88,7.32,7.50,7.37,7.85,7.50 K,A2,4.50,3.69,3.73,3.49,3.45,3.34,3.61,3.70 Rb,A2,3.59,2.82,2.88,2.71,2.59,2.53,2.77,3.10 Ca,A1,18.7,17.8,18.0,17.4,17.6,17.4,17.3,18.4 Sr,A1,14.4,12.2,12.5,12.2,11.8,11.5,11.4,12.3 Ba,A2,10.6,9.0,9.3,9.2,8.5,8.2,8.2,9.3 V,A2,213,203,201,198,199,196,183,162 Nb,A2,193,186,184,183,183,180,171,170 Ta,A2,219,210,208,207,208,206,195,194 Mo,A2,294,288,282,279,284,277,260,272 W,A2,336,329,322,320,325,319,303,296 Fe,A2,254,233,226,227,224,220,194,168 Rh,A1,320,309,298,292,300,284,259,269 Ir,A1,395,392,377,368,383,360,336,355 Ni,A1,259,239,232,231,231,221,200,186 Pd,A1,231,218,208,207,207,194,170,195 Pt,A1,301,296,282,276,285,265,242,277 Cu,A1,191,177,170,168,168,165,141,142 Ag,A1,140,127,120,119,116,109,91,109 Au,A1,200,192,180,177,179,165,144,167 Al,A1,84.3,86.6,83.0,80.6,86.3,87.2,79.2,79.4 C,A4,469,458,452,451,453,431,434,443 Si,A4,96.4,96.4,93.8,94.0,93.2,90.5,88.7,99.2 Ge,A4,72.7,71.1,68.1,67.8,66.5,62.5,59.5,75.8 Sn,A4,45.7,44.0,42.3,42.4,40.3,38.1,36.3,53.0 Pb,A1,50.5,47.5,44.6,45.2,41.7,40.0,35.6,43.0 Th,A1,66.9,64.1,62.7,63.0,61.7,60.0,58.0,54.3 LiF,B1,88.2,73.4,72.8,72.4,66.1,66.8,67.5,69.8 LiCl,B1,42.0,36.6,35.9,35.7,31.4,33.0,32.2,35.4 NaF,B1,61.7,48.5,48.5,45.4,44.3,42.8,44.5,51.4 NaCl,B1,32.7,26.2,26.1,24.7,22.4,23.2,23.7,26.6 MgO,B1,174,158,158,158,154,154,149,165 MgS,B1,84.0,80.3,78.7,78.2,76.7,76.2,74.4,78.9 CaO,B1,129,116,115,116,111,109,105,114 TiC,B1,283,275,270,267,270,255,248,233 TiN,B1,322,307,302,300,301,289,277,277 ZrC,B1,248,241,237,236,236,226,222,230 ZrN,B1,286,276,271,270,271,262,250,215 HfC,B1,257,247,240,238,244,223,218,200 HfN,B1,309,295,290,289,290,279,265,306 VC,B1,349,338,331,328,333,314,307,303 VN,B1,365,352,343,340,344,326,312,233 NbC,B1,335,330,324,319,325,306,301,315 NbN,B1,353,344,335,333,338,323,309,292 FeAl,B2,208,197,194,193,194,191,180,136 CoAl,B2,207,196,193,192,193,191,179,162 NiAl,B2,185,176,173,171,173,171,159,156 BN,B3,405,391,387,387,387,374,373,373 BP,B3,176,173,170,170,169,162,162,152 BAs,B3,148,145,141,141,140,133,132,138 AlP,B3,89.9,88.8,87.1,87.1,85.8,85.9,82.6,86.0 AlAs,B3,75.5,73.8,72.4,72.5,70.8,70.5,67.0,74.0 GaN,B3,204,194,190,190,189,179,173,190 GaP,B3,90.6,87.9,85.2,85.5,83.4,78.6,77.0,87.4 GaAs,B3,74.7,72.1,69.5,69.5,67.5,64.1,61.0,75.6 InP,B3,72.0,69.5,67.4,67.4,65.3,60.7,59.9,71.0 InAs,B3,60.7,58.1,56.0,56.6,53.8,50.7,48.8,58.0 SiC,B3,230,225,222,221,222,217,212,225 CeO2,C1,209,198,195,195,190,189,176,220 """ data_B_priv = {} for l in data4.split(): if 'Solid' not in l: l1 = l.split(',') data_B_priv[l1[0]] = [l1[1]] data_B_priv[l1[0]].extend([float(v) for v in l1[2:]]) if 1: # use private communication data data = data_priv.copy() B = data_B_priv.copy() names = [d.split(',')[0] for d in data3.split()][1:] labels = data3.split()[0].split(',') else: # use private published data (no bulk modulus) data = data_ref.copy() B = None names = [d.split(',')[0] for d in data1.split()][1:] labels = data1.split()[0].split(',') def __init__(self, xc='PBE'): self.xc = xc def __getitem__(self, name): d = self.data[name] # the index of functional in labels less one # (solid is already as key in d) a = d[self.labels.index(self.xc) - 1] cs = strukturbericht[d[0]] b = bulk(name, crystalstructure=cs, a=a) M = {'Fe': 2.3, 'Co': 1.2, 'Ni': 0.6}.get(name) if M is not None: b.set_initial_magnetic_moments([M] * len(b)) return b def keys(self): return self.names class HaasTranBlahaBulkTask(BulkTask): def __init__(self, xc='PBE', **kwargs): BulkTask.__init__(self, collection=HaasTranBlahaBulkCollection(xc), **kwargs) self.summary_keys = ['energy', 'fitted energy', 'crystal structure', 'strukturbericht', 'lattice constant', 'lattice constant error [%]', 'volume', 'volume error [%]', 'B', 'B error [%]'] def analyse(self, atomsfile=None): try: BulkTask.analyse(self) except ValueError: # allow fit outside of range pass for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) # use relaxed volume if present if 'relaxed volume' in data: volume = data['relaxed volume'] else: volume = atoms.get_volume() volumes = data['strains']**3 * volume energies = data['energies'] # allow selection of eos type independent of data if self.eos is not None: eos = EquationOfState(volumes, energies, self.eos) else: eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except ValueError: pass else: data['fitted energy'] = e data['volume'] = v data['B'] = B # with respect tot the reference volume data['volume error [%]'] = (data['volume'] / atoms.get_volume() - 1) * 100 if self.collection.B: i = self.collection.labels.index(self.collection.xc) - 1 B = self.collection.B[name][i] * units.kJ * 1e-24 data['B error [%]'] = (data['B'] / B - 1) * 100 else: data['B error [%]'] = None data['strukturbericht'] = self.collection.data[name][0] data['crystal structure'] = strukturbericht[data['strukturbericht']] # calculate lattice constant from volume cs = data['crystal structure'] if cs == 'bcc': a0 = (volume*2)**(1/3.) a = (data['volume']*2)**(1/3.) elif cs == 'cesiumchloride': a0 = (volume)**(1/3.) a = (data['volume'])**(1/3.) elif cs in ['fcc', 'diamond', 'zincblende', 'rocksalt', 'fluorite']: a0 = (volume*4)**(1/3.) a = (data['volume']*4)**(1/3.) i = self.collection.labels.index(self.collection.xc) - 1 a0_ref = self.collection.data[name][i] if 'relaxed volume' not in data: # no volume relaxation performed - volume equals the reference one assert abs(a0 - a0_ref) < 1.e-4 data['lattice constant'] = a data['lattice constant error [%]'] = (a - a0_ref) / a0_ref * 100 if atomsfile: # MDTMP: TODO atomdata = read_json(atomsfile) for name, data in self.data.items(): atoms = self.create_system(name) e = -data['energy'] for atom in atoms: e += atomdata[atom.symbol]['energy'] e /= len(atoms) data['cohesive energy'] = e if self.collection.xc == 'PBE': eref = self.collection.data[name][7] else: eref = self.collection.data[name][9] data['cohesive energy error [%]'] = (e / eref - 1) * 100 self.summary_keys += ['cohesive energy', 'cohesive energy error [%]'] if __name__ == '__main__': # run with emt from ase.tasks.main import run run(calcname='emt', task=HaasTranBlahaBulkTask(fit=(5, 0.02))) python-ase-3.9.1.4567/ase/test/tasks/analyse.py0000664000175000017500000003502012553425527021361 0ustar jensjjensj00000000000000import csv import heapq import numpy as np from ase.tasks.io import read_json ann_fontsize = 'small' label_fontsize = 12 def most_common_value(values, precision=None): import heapq # find the most common value if precision is not None: vs = [round(v, precision) for v in values] else: vs = values[:] if len(vs) > 0: nlargest = heapq.nlargest(1, [vs.count(e) for e in vs])[0] index = [vs.count(e) for e in vs].index(nlargest) v = vs[index] else: v = None return v def get_differences(reference, values, precision=None): # diffrences with respect to the reference value within precision values = values[:] for n, v in enumerate(values): if v is not None: de = v - reference if precision is not None: if abs(de) < 1. / precision: # value within precision values[n] = 0.0 else: values[n] = round(de, precision) else: values[n] = de return values def get_key_summary_list(key, name, runs, data, precision=3, relative=False): # if relative, then first entry is a common value, other entries relative # if not relative, then first entry is average value, other entries verbatim nruns = len(runs) d = data.copy() l = [name] values = [d[r][key] for r in runs if r in d and key in d[r] and d[r][key] is not None] if relative: # find the most common value e = most_common_value(values, precision) else: e = np.mean(values) if e is None: l.extend(['None' for i in range(nruns + 1)]) else: # print the found common value with the precision l.append(("%." + "%df" % (precision + 0)) % e) es = [d[r].get(key, None) for r in runs if r in d] if relative: des = get_differences(e, es) # and the corresponding differences for n, de in enumerate(des): if de is not None: if abs(de) < 1. / precision: # value within precision des[n] = '-' else: des[n] = ("%." + "%df" % precision) % de else: des[n] = 'None' l.extend(des) else: des = es[:] for n, de in enumerate(es): if de is not None: des[n] = str(de) else: des[n] = 'None' l.extend(des) return l def get_key_stats(data, key, nnlargest): keys = [] values = [] stats = {'absaverage': None, 'average': None, 'std': None, 'max': None, 'N': None, 'nlargest': []} for k, v in data.iteritems(): if key in v: if v.get(key) is not None: keys.append(k) values.append(v[key]) if len(keys) > 0: stats['absaverage'] = np.average(abs(np.array(values))) stats['average'] = np.average(np.array(values)) stats['std'] = np.std(np.array(values)) stats['max'] = np.max(np.array(values)) stats['N'] = len(values) nlargest = heapq.nlargest(nnlargest, np.abs(np.array(values))) # already found elements must be removed in order to avoid repetition k = keys[:] v = values[:] nl = [] for i in nlargest: ind = v.index(i) nl.append((k[ind], i)) v.pop(ind) k.pop(ind) stats['nlargest'] = nl return stats def plot_single(xdata, ydata, std, title, xlabel, ylabel, label, color, alpha, miny, maxy, num=1, ): import matplotlib matplotlib.rc('text', usetex=False) import pylab import matplotlib.font_manager # all goes to figure num pylab.figure(num=num, figsize=(9.5, 9)) pylab.gca().set_position([0.10, 0.20, 0.85, 0.60]) # let the plot have fixed y-axis scale ywindow = maxy - miny pylab.bar(xdata, ydata, 0.9, yerr=std, label=label, color=color, alpha=alpha) pylab.gca().set_ylim(miny, maxy) t = pylab.title(title) # http://old.nabble.com/More-space-between-title-and-secondary-x-axis-td31722298.html t.set_y(1.05) pylab.xlabel(xlabel) pylab.ylabel(ylabel) prop = matplotlib.font_manager.FontProperties(size=12) leg = pylab.legend(loc='upper right', fancybox=True, prop=prop) leg.get_frame().set_alpha(0.5) def plot(runs, data, labels, # labels coresponding to runs key, # the main quantity to plot failkey, # the key that informs about failure/success in run nnlargest, plot_label, plot_xlabel, plot_ylabel, miny, maxy, tag=None, tunit='min'): # horror function d = data.copy() # collect stats for each run stats = {'average': [], 'std': [], 'sdom': [], 'nlargest': [], 'time': [], 'converged': []} for n, r in enumerate(runs): s = get_key_stats(d[r], key, nnlargest) assert s['average'] is not None, r + ': no key ' + "'" + key + "'" + ' in results?' stats['average'].append(s['average']) stats['std'].append(s['std']) stats['sdom'].append(s['std']/np.sqrt(s['N'])) stats['nlargest'].append(s['nlargest']) # total run time t = [d[r][k]['time'] for k in d[r].keys() if 'time' in d[r][k]] if tunit == 'sec': stats['time'].append(sum(t)) # sec elif tunit == 'min': stats['time'].append(sum(t) / 60) # min elif tunit == 'h': stats['time'].append(sum(t) / 3600) # hours # number of converged systems c = [d[r][k][failkey] for k in d[r].keys() if failkey in d[r][k]] stats['converged'].append(len([s for s in c if s is not None])) import matplotlib #matplotlib.use('Agg') matplotlib.rc('text', usetex=False) from matplotlib import pylab, ticker num=1 scale = [i for i in range(len(runs))] # plot skeleton plot_single( scale, stats['average'], stats['sdom'], plot_label, plot_xlabel, plot_ylabel, 'Average (avg)', 'blue', 0.5, miny, maxy, num=1, ) zero = [0.0 for v in scale] pylab.plot(scale, zero, 'k-', label='_nolegend_') ay1=pylab.gca() ay1.xaxis.set_ticks([n + 0.5 for n in scale]) ay1.xaxis.set_ticklabels(labels) ay1.yaxis.set_minor_locator(matplotlib.ticker.AutoMinorLocator()) for label in ay1.get_xticklabels() + ay1.get_yticklabels(): label.set_fontsize(label_fontsize) # rotate labels http://old.nabble.com/Rotate-x-axes-%28xticks%29-text.-td3141258.html for label in ay1.get_xticklabels(): label.set_rotation(75) # plot stats for n, r in enumerate(runs): label = '' for n1, v in enumerate(['average', 'std', 'time']): l = { 'average': '\navg\n', 'absaverage': '\nabs\n', 'std': '\nstd\n', 'time': '\nt [%s]\n' % tunit, }[v] value = { 'average': stats['average'][n], #'absaverage': stats['absaverage'][n], 'std': stats['std'][n], 'time': stats['time'][n], }[v] label += l + ' ' + str(round(value, 1)) + '\n' label += '\nconv.\n' + ' ' + str(int(stats['converged'][n])) + '\n' pylab.annotate(label, xy=(n + 0.0, 0.0), xytext=(n + 0.2, miny / 2 - 0.5), arrowprops=None, horizontalalignment='left', verticalalignment='center', fontsize=ann_fontsize, ) # plot compounds with largest errors for n, l in enumerate(stats['nlargest']): l.reverse() for n1, (c, e) in enumerate(l): name = c + '\n' label = name + ' ' + str(int(e)) xytext=(n + 0.3, maxy / 2 + maxy / 10 * n1) if e > maxy: # labels exceeding y-scale xy = xytext else: xy=(n + 0.05, e) pylab.annotate(label, xy=xy, xytext=xytext, arrowprops=dict(width=0.05, headwidth=5.0, facecolor='black', shrink=1.00), horizontalalignment='left', verticalalignment='center', fontsize=ann_fontsize, ) # axis limits after the last plot! pylab.ylim(miny, maxy) kname = key.replace(' ', '_') if tag is not None: plotname = '%s_%s.png' % (tag, kname) else: plotname = '%s.png' % kname pylab.savefig(plotname, bbox_inches='tight') class AnalyseOptimizersTask: def __init__(self, taskname, runs, labels=None, tag=None, steps=100, precision=3, tunit='min'): """Analyse optimizers runs. """ self.taskname = taskname self.runs = runs if labels is None: # run labels for plotting self.labels = self.runs.split(',') else: self.labels = labels self.tag = tag self.steps = steps # only for purpose of limit plot y-axis self.precision = precision assert tunit in ['sec', 'min', 'h'] self.tunit = tunit self.key_summary = 'relaxed energy' self.key_plot = 'optimizer force calls' self.plot_label = 'Summary of optimizers' self.plot_xlabel = 'optimizer' self.plot_ylabel = self.key_plot def read_run(self, taskname, tag, run): if tag is not None: tag += '_%s' % run else: tag = run return read_json(taskname + '-' + tag + '.json') def get_data(self, taskname, tag, runs): d = {} for r in runs: d[r] = self.read_run(taskname, tag, r) return d def analyse(self): runs = self.runs.split(',') # dict of systems for each run datarun = self.get_data(self.taskname, self.tag, runs) # the number of systems (based on results from json) nsystems = max([len(datarun[n]) for n in datarun.keys()]) # dict of runs for each system datasys = {} for k, v in datarun.iteritems(): for k1, v1 in v.iteritems(): if k1 not in datasys: datasys[k1] = {k: v1} else: datasys[k1].update({k: v1}) # csv summary of self.key_plot key_name = self.key_plot.replace(' ', '_') row = ['formula', self.key_plot] row.extend([r for r in range(len(runs))]) rows = [row] for name, data in datasys.items(): if not data: continue row = get_key_summary_list(self.key_plot, name, runs, data, precision=self.precision, relative=False) row = [r.replace('None', 'N/A') for r in row] # only failed or non-common runs for k in row[2:]: if k == 'N/A' or k != '-': rows.append(row) break if len(rows) > 0: # always create csv file if self.tag is not None: csvwriter = csv.writer( open('%s_%s.csv' % (self.tag, key_name), 'wb')) else: csvwriter = csv.writer(open('%s.csv' % key_name, 'wb')) for r in rows: csvwriter.writerow(r) # csv summary of self.key_summary summary_name = self.key_summary.replace(' ', '_') row = ['formula', self.key_summary] row.extend([r for r in range(len(runs))]) rows = [row] for name, data in datasys.items(): if not data: continue row = get_key_summary_list(self.key_summary, name, runs, data, precision=self.precision, relative=True) row = [r.replace('None', 'N/A') for r in row] # only failed or non-common runs for k in row[2:]: if k == 'N/A' or k != '-': rows.append(row) break if len(rows) > 0: # always create csv file if self.tag is not None: csvwriter = csv.writer( open('%s_%s.csv' % (self.tag, summary_name), 'wb')) else: csvwriter = csv.writer(open('%s.csv' % summary_name, 'wb')) for r in rows: csvwriter.writerow(r) # plot maxy = self.steps - 5 miny = - ((maxy + 5) / 2 + 5) # plot only runs with data plotruns = runs[:] labels = self.labels[:] for n, r in enumerate(runs): nd = [1 for k in datarun[r] if datarun[r][k]] if len(nd) == 0: print('skipped plotting empty data', r) # no data for this run i = plotruns.index(r) plotruns.pop(i) labels.pop(i) continue plot(plotruns, datarun, labels, self.key_plot, # the main quantity to plot self.key_summary, 4, self.plot_label + ': ' + str(nsystems) + ' systems', self.plot_xlabel, self.plot_ylabel, miny, maxy, tag=self.tag, tunit=self.tunit) class AnalyseSCFTask(AnalyseOptimizersTask): def __init__(self, taskname, runs, labels=None, tag=None, steps=100, precision=3, tunit='min'): """Analyse SCF runs. """ AnalyseOptimizersTask.__init__(self, taskname, runs, labels, tag, steps, precision, tunit) self.key_summary = 'energy' self.key_plot = 'calculator steps' self.plot_label = 'Summary of runs' self.plot_xlabel = 'run' self.plot_ylabel = self.key_plot python-ase-3.9.1.4567/ase/test/emt1.py0000664000175000017500000000115612553425527017451 0ustar jensjjensj00000000000000from ase import Atoms from ase.calculators.emt import EMT from ase.constraints import FixBondLength from ase.io import Trajectory from ase.optimize import BFGS a = 3.6 b = a / 2 cu = Atoms('Cu2Ag', positions=[(0, 0, 0), (b, b, 0), (a, a, b)], calculator=EMT()) e0 = cu.get_potential_energy() print(e0) d0 = cu.get_distance(0, 1) cu.set_constraint(FixBondLength(0, 1)) t = Trajectory('cu2ag.traj', 'w', cu) qn = BFGS(cu) qn.attach(t.write) def f(): print(cu.get_distance(0,1)) qn.attach(f) qn.run(fmax=0.01) assert abs(cu.get_distance(0, 1) - d0) < 1e-14 python-ase-3.9.1.4567/ase/test/ag.py0000664000175000017500000000066312553425527017174 0ustar jensjjensj00000000000000import os import sys from ase import Atoms from ase.io import write write('x.json', Atoms('X')) # Make sure ase-gui can run in terminal mode without $DISPLAY and gtk: sys.argv = ['ase-gui', '--terminal', 'x.json'] display = os.environ.pop('DISPLAY', None) error = False try: from ase.gui.ag import main main() assert 'gtk' not in sys.modules finally: if display is not None: os.environ['DISPLAY'] = display python-ase-3.9.1.4567/ase/test/center.py0000664000175000017500000000464712553425527020073 0ustar jensjjensj00000000000000"Test that atoms.center() works when adding vacuum ()" import numpy as np from math import pi, sqrt, cos from ase import data from ase.lattice.cubic import FaceCenteredCubic def checkang(a, b, phi): "Check the angle between two vectors." cosphi = np.dot(a,b) / sqrt(np.dot(a,a) * np.dot(b,b)) assert np.abs(cosphi - cos(phi)) < 1e-10 symb = "Cu" Z = data.atomic_numbers[symb] a0 = data.reference_states[Z]['a'] # (100) oriented block atoms = FaceCenteredCubic(size=(5,5,5), symbol="Cu", pbc=(1,1,0)) assert len(atoms) == 5*5*5*4 c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/2) checkang(c[1], c[2], pi/2) assert np.abs(5 * a0 - c[2,2]) < 1e-10 # Add vacuum in one direction vac = 10.0 atoms.center(axis=2, vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/2) checkang(c[1], c[2], pi/2) assert np.abs(4.5 * a0 + 2* vac - c[2,2]) < 1e-10 # Add vacuum in all directions vac = 4.0 atoms.center(vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/2) checkang(c[1], c[2], pi/2) assert np.abs(4.5 * a0 + 2* vac - c[0,0]) < 1e-10 assert np.abs(4.5 * a0 + 2* vac - c[1,1]) < 1e-10 assert np.abs(4.5 * a0 + 2* vac - c[2,2]) < 1e-10 # Now a general unit cell atoms = FaceCenteredCubic(size=(5,5,5), directions=[[1,0,0], [0,1,0], [1,0,1]], symbol="Cu", pbc=(1,1,0)) assert len(atoms) == 5*5*5*2 c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/4) checkang(c[1], c[2], pi/2) assert np.abs(2.5 * a0 - c[2,2]) < 1e-10 # Add vacuum in one direction vac = 10.0 atoms.center(axis=2, vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/4) checkang(c[1], c[2], pi/2) assert np.abs(2 * a0 + 2* vac - c[2,2]) < 1e-10 # Recenter without specifying vacuum atoms.center() c = atoms.get_cell() checkang(c[0], c[1], pi/2) checkang(c[0], c[2], pi/4) checkang(c[1], c[2], pi/2) assert np.abs(2 * a0 + 2* vac - c[2,2]) < 1e-10 a2 = atoms.copy() # Add vacuum in all directions vac = 4.0 atoms.center(vacuum=vac) c = atoms.get_cell() checkang(c[0], c[1], pi / 2) checkang(c[0], c[2], pi / 4) checkang(c[1], c[2], pi / 2) assert np.abs(4.5 * a0 + 2 * vac - c[1, 1]) < 1e-10 assert np.abs(2 * a0 + 2 * vac - c[2, 2]) < 1e-10 # One axis at the time: for i in range(3): a2.center(vacuum=vac, axis=i) assert abs(atoms.positions - a2.positions).max() < 1e-12 assert abs(atoms.cell - a2.cell).max() < 1e-12 python-ase-3.9.1.4567/ase/test/replay.py0000664000175000017500000000164012553425527020075 0ustar jensjjensj00000000000000from math import sqrt from ase import Atoms, Atom from ase.constraints import FixAtoms from ase.calculators.emt import EMT from ase.optimize import QuasiNewton from ase.io import read from ase.visualize import view # Distance between Cu atoms on a (100) surface: d = 3.6 / sqrt(2) a = Atoms('Cu', positions=[(0, 0, 0)], cell=(d, d, 1.0), pbc=(True, True, False)) a *= (2, 2, 1) # 2x2 (100) surface-cell # Approximate height of Ag atom on Cu(100) surfece: h0 = 2.0 a += Atom('Ag', (d / 2, d / 2, h0)) if 0: view(a) constraint = FixAtoms(range(len(a) - 1)) a.set_calculator(EMT()) a.set_constraint(constraint) dyn1 = QuasiNewton(a, trajectory='AgCu1.traj', logfile='AgCu1.log') dyn1.run(fmax=0.1) a = read('AgCu1.traj') a.set_calculator(EMT()) print(a.constraints) dyn2 = QuasiNewton(a, trajectory='AgCu2.traj', logfile='AgCu2.log') dyn2.replay_trajectory('AgCu1.traj') dyn2.run(fmax=0.01) python-ase-3.9.1.4567/ase/test/dependency_backend_gdk.py0000664000175000017500000000313312553425527023212 0ustar jensjjensj00000000000000from __future__ import print_function import os import sys msg = "\nThe GDK rendering GTK matplotlib backend is missing or not installed properly.\n" msg += "See http://matplotlib.org/faq/usage_faq.html#what-is-a-backend.\n" msg += "Is the PYTHONPATH environment variable set correctly?\n" msg += "Please verify your installation by running on the command line:\n" msg += "python -c 'from matplotlib.backends import backend_gdk'\n" msg += "\n" msg += "This module is optional and required in order to use " msg += "ASE's simple GUI (ase-gui).\n" msg += "If you don't wish to use ase-gui ignore this error, otherwise\n" msg += "please install the matplotlib package containing the missing backend\n" msg += "using your distribution package manager, i.e.:\n" msg += "\n" msg += " Debian/Ubuntu: sudo apt-get python-matplotlib\n" msg += "\n" msg += " OpenSUSE: yast -i python-matplotlib\n" msg += "\n" msg += " Red Hat/Fedora: yum install python-matplotlib\n" msg += "\n" msg += "or perform manual installation, preferably as non-root user,\n" msg += "following http://matplotlib.sourceforge.net/users/installing.html\n" msg += "after installing the http://www.pygtk.org/downloads.html dependency first." if locals().get('display'): try: import matplotlib.backends as b f = os.path.join(os.path.dirname(b.__file__), '_backend_gdk.so') open(f).close() from matplotlib.backends import backend_gdk except ImportError: print(msg, file=sys.stderr) raise except IOError: print(("\nThe backend file %s does not exist.\n" % f) + msg, file=sys.stderr) raise python-ase-3.9.1.4567/ase/test/bader.py0000664000175000017500000000151612553425527017660 0ustar jensjjensj00000000000000from __future__ import print_function import os from ase.structure import molecule from ase.io.bader import attach_charges fname = 'ACF.dat' f = open(fname, 'w') print(""" # X Y Z CHARGE MIN DIST ---------------------------------------------------------------- 1 7.0865 8.5038 9.0672 9.0852 1.3250 2 7.0865 9.9461 7.9403 0.4574 0.3159 3 7.0865 7.0615 7.9403 0.4574 0.3159 ---------------------------------------------------------------- NUMBER OF ELECTRONS: 9.99999 """, file=f) f.close() atoms = molecule('H2O') atoms.set_cell([7.5, 9, 9]) atoms.center() attach_charges(atoms) attach_charges(atoms, fname) os.remove(fname) for atom in atoms: print('Atom', atom.symbol, 'Bader charge', atom.charge) python-ase-3.9.1.4567/ase/test/bulk.py0000664000175000017500000000034612553425527017540 0ustar jensjjensj00000000000000from ase.lattice import bulk a1 = bulk('ZnS', 'wurtzite', a=3.0, u=0.23) * (1, 2, 1) a2 = bulk('ZnS', 'wurtzite', a=3.0, u=0.23, orthorhombic=True) a1.cell = a2.cell a1.wrap() assert abs(a1.positions - a2.positions).max() < 1e-14 python-ase-3.9.1.4567/ase/test/db.py0000664000175000017500000000234012553425527017164 0ustar jensjjensj00000000000000import sys from ase.test import cli, NotAvailable from ase.db import connect if sys.platform == 'win32': raise NotAvailable('Fails on Windows!') cmd = """ ase-build H | ase-run emt -d y.json && ase-build H2O | ase-run emt -d y.json && ase-build O2 | ase-run emt -d y.json && ase-build H2 | ase-run emt -f 0.02 -d y.json && ase-build O2 | ase-run emt -f 0.02 -d y.json && ase-build -x fcc Cu | ase-run emt -E 5 -d y.json && ase-db y.json -v natoms=1,Cu=1 --delete --yes && ase-db y.json -v "H>0" -k hydro=1,abc=42,foo=bar && ase-db y.json -v "H>0" --delete-keys foo""" for name in ['y.json', 'y.db']: cli(cmd.replace('y.json', name)) con = connect(name) assert len(list(con.select())) == 5 assert len(list(con.select('hydro'))) == 3 assert con.get_atoms(H=1)[0].magmom == 1 assert len(list(con.select('foo'))) == 0 assert len(list(con.select(abc=42))) == 3 assert len(list(con.select('abc'))) == 3 assert len(list(con.select('abc,foo'))) == 0 assert len(list(con.select('abc,hydro'))) == 3 assert len(list(con.select(foo='bar'))) == 0 assert len(list(con.select(formula='H2'))) == 1 assert len(list(con.select(formula='H2O'))) == 1 id = con.reserve(abc=7) assert con[id].abc == 7 python-ase-3.9.1.4567/ase/test/dimer.py0000664000175000017500000000105212553425527017676 0ustar jensjjensj00000000000000from ase import Atom, Atoms from ase.calculators.lj import LennardJones from ase.constraints import FixBondLength dimer = Atoms([Atom('X', (0, 0, 0)), Atom('X', (0, 0, 1))], calculator=LennardJones(), constraint=FixBondLength(0, 1)) print(dimer.get_forces()) print(dimer.positions) dimer.positions[:] += 0.1 print(dimer.positions) dimer.positions[:, 2] += 5.1 print(dimer.positions) dimer.positions[:] = [(1,2,3),(4,5,6)] print(dimer.positions) dimer.set_positions([(1,2,3),(4,5,6.2)]) print(dimer.positions) python-ase-3.9.1.4567/ase/test/cmr/0000775000175000017500000000000012553427753017012 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/cmr/ase_rw.py0000664000175000017500000000225212553425527020642 0ustar jensjjensj00000000000000import os import warnings # cmr calls all available methods in ase.atoms detected by the module inspect. # Therefore also deprecated methods are called - and we choose to silence those warnings. warnings.filterwarnings('ignore', 'ase.atoms.*deprecated',) from ase.test import NotAvailable # if CMR_SETTINGS_FILE is missing, cmr raises simply # Exception("CMR is not configured properly. Please create the settings file with cmr --create-settings.") try: import cmr except (Exception, ImportError): raise NotAvailable('CMR is required') from ase.calculators.emt import EMT from ase.io import read, write from ase.structure import molecule cmr_params = {"db_keywords":["O", "ase"], # keyword "molecule":"O2"} #field m1 = molecule('O2') m1.set_calculator(EMT()) e1 = m1.get_potential_energy() write("O2.cmr", m1, cmr_params = cmr_params) reread = read("O2.cmr") e2 = reread.get_potential_energy() assert abs(e1 - e2) < 1.e-6, str(e1) + ' ' + str(e2) db_read = cmr.read("O2.cmr") assert "O" in db_read["db_keywords"] assert "ase" in db_read["db_keywords"] assert db_read["molecule"] == "O2" # clean filename = "O2.cmr" if os.path.exists(filename): os.unlink(filename) python-ase-3.9.1.4567/ase/test/cmr/__init__.py0000664000175000017500000000000012553425527021106 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/cmr/reactions.py0000664000175000017500000000122712553425527021352 0ustar jensjjensj00000000000000# Define the list of reactions here: # [('N2', -1), ('N', 2), ('reaction_energy', None), ('reaction_id', 1)] denotes: # reaction_energy = -1 * N2 + 2 *N # reaction_id is an integer or string to identify the reaction reactions = [ [('N2', -1), ('N', 2), ('reaction_id', 1)], [('H2O', -1), ('H2', 1), ('O2', 0.5), ('reaction_id', 'H2O decomposition')], [('H2O', -1), ('H', 2), ('O', 1), ('reaction_id', 3)], ] # reference reaction energies reference = { # 'reaction_id' : reaction energy reactions[0][-1][1]: 9.93722251591, reactions[1][-1][1]: -0.496408928568, reactions[2][-1][1]: 9.14067431054, } python-ase-3.9.1.4567/ase/test/cmr/rw.py0000664000175000017500000000250612553425527020014 0ustar jensjjensj00000000000000import os import warnings # cmr calls all available methods in ase.atoms detected by the module inspect. # Therefore also deprecated methods are called - and we choose to silence those warnings. warnings.filterwarnings('ignore', 'ase.atoms.*deprecated',) import numpy as np def array_almost_equal(a1, a2, tol=np.finfo(type(1.0)).eps): """Replacement for old numpy.testing.utils.array_almost_equal.""" return (np.abs(a1 - a2) < tol).all() from ase.test import NotAvailable # if CMR_SETTINGS_FILE is missing, cmr raises simply # Exception("CMR is not configured properly. Please create the settings file with cmr --create-settings.") try: import cmr except (Exception, ImportError): raise NotAvailable('CMR is required') from ase.calculators.emt import EMT from ase.io import read, write from ase.structure import molecule m1 = molecule('O2') m1.center(2.0) write("O2.cmr", images=m1) m1.set_calculator(EMT()) e1 = m1.get_potential_energy() f1 = m1.get_forces() m2 = read("O2.cmr") m2.set_calculator(EMT()) e2 = m2.get_potential_energy() f2 = m1.get_forces() # assume atoms definitions are the same if energy/forces are the same: can we do better? assert abs(e1-e2) < 1.e-6, str(e1) + ' ' + str(e2) assert array_almost_equal(f1, f2, tol=1.e-6) # clean filename = "O2.cmr" if os.path.exists(filename): os.unlink(filename) python-ase-3.9.1.4567/ase/test/cmr/reactions_xsimple.py0000664000175000017500000000433112553425527023112 0ustar jensjjensj00000000000000import os import warnings # cmr calls all available methods in ase.atoms detected by the module inspect. # Therefore also deprecated methods are called - and we choose to silence those warnings. warnings.filterwarnings('ignore', 'ase.atoms.*deprecated',) from ase.test import NotAvailable # if CMR_SETTINGS_FILE is missing, cmr raises simply # Exception("CMR is not configured properly. Please create the settings file with cmr --create-settings.") try: import cmr except (Exception, ImportError): raise NotAvailable('CMR is required') from ase.calculators.emt import EMT from ase.structure import molecule from ase.io import write # project id: must uniquely identify the project! project_id = 'simple reaction energies' reaction = [('N2', -1), ('N', 2)] calculator = EMT() for (formula, coef) in reaction: m = molecule(formula) m.set_calculator(calculator) m.get_potential_energy() cmr_params = { "db_keywords": [project_id], # add project_id also as a field to support search across projects "project_id": project_id, "formula": formula, "calculator": calculator.name, } write(filename=('reactions_xsimple.%s.db' % formula), images=m, format='db', cmr_params=cmr_params) # analyse the results with CMR from cmr.ui import DirectoryReader reader = DirectoryReader('.') # read all compounds in the project calculated with EMT all = reader.find(name_value_list=[('calculator', 'EMT')], keyword_list=[project_id]) all.print_table(0, columns=["formula", "ase_potential_energy"]) print() group = cmr.create_group() group_vars = {"reaction":reaction, "output":"group.db"} sum = 0.0 for (formula, coef) in reaction: data = all.get("formula", formula) if data is None: print("%s is missing"%formula) sum = None break sum += coef*data["ase_potential_energy"] group.add(data["db_hash"]) group_vars["result"] = sum group.write(group_vars) print("Energy: ",sum) group.dump() # clean for (formula, coef) in reaction: filename=('reactions_xsimple.%s.db' % formula) if os.path.exists(filename): os.unlink(filename) filename = "group.db" if os.path.exists(filename): os.unlink(filename) python-ase-3.9.1.4567/ase/test/cmr/reactions_test.py0000664000175000017500000000561612553425527022417 0ustar jensjjensj00000000000000from ase.test import NotAvailable import warnings # cmr calls all available methods in ase.atoms detected by the module inspect. # Therefore also deprecated methods are called - and we choose to silence those warnings. warnings.filterwarnings('ignore', 'ase.atoms.*deprecated',) # if CMR_SETTINGS_FILE is missing, cmr raises simply # Exception("CMR is not configured properly. Please create the settings file with cmr --create-settings.") try: import cmr except (Exception, ImportError): raise NotAvailable('CMR is required') from cmr.ui import DirectoryReader from cmr.test.examples.ase_reaction_energy import ASEReactionEnergy # see the module for the required format of reactions definition from ase.test.cmr.reactions import reactions from ase.test.cmr.reactions import reference # assure that all reactions define a reaction_id for r in reactions: assert r[-1][0] == 'reaction_id' # project id: must uniquely identify the project! project_id = 'EMT' + ' reaction energies' # if True, then results are uploaded to the database database = False # create assisting class for project with project_id, # that allows one to convert trajectory files into # db-files and perform analysis re = ASEReactionEnergy(project_id, reactions, prefix='', verbose=False) # compounds names compounds = re.get_compounds() # put additional fields here: cmr_params = {'calculator': 'EMT'} # convert all traj files in this directory to db-files re.create_db_files(cmr_params) # calculate the reaction energies and write the results to db-files # named 'reaction_id.index.db' # Each db-file defines a group (group of all compounds belonging to # the given reaction). # reaction energies on initial, unoptimized geometries cmr_params = {'geometries': 'initial'} re.make_reaction_groups(database=False, index=0, cmr_params=cmr_params) # print re.print_result(database=False) # reaction energies on final, optimized geometries cmr_params = {'geometries': 'final'} re.make_reaction_groups(database=False, index= -1, cmr_params=cmr_params) # print re.print_result(database=False) reader = DirectoryReader('.') # retrieve all reactions (groups) with project_id and optimized geometries from the current directory all = reader.find(name_value_list=[('db_calculator', 'group'), ('geometries', 'final') ], keyword_list=[project_id, 'reaction']) print('reaction_id, calc, ref, calc - ref') # compare with the reference for r in reactions: reaction_id = r[-1][1] res = all.get('reaction_id', reaction_id) if res is None: print("Could not find reaction_id %s in reference"%str(reaction_id)) else: calc = res['reaction_energy'] ref = reference[reaction_id] print(reaction_id, calc, ref, calc - ref) assert abs(calc - ref) < 1e-5 # upload the created groups to the database if database: re.upload_to_database() python-ase-3.9.1.4567/ase/test/cmr/cmr_rw.py0000664000175000017500000000143112553425527020651 0ustar jensjjensj00000000000000import os import warnings # cmr calls all available methods in ase.atoms detected by the module inspect. # Therefore also deprecated methods are called - and we choose to silence those warnings. #warnings.filterwarnings('ignore', 'ase.atoms.*deprecated',) import cmr from ase.calculators.emt import EMT from ase.structure import molecule m1 = molecule('O2') m1.set_calculator(EMT()) e1 = m1.get_potential_energy() data = cmr.atoms2cmr(m1) data.set_user_variable("molecule", "O2") data.set_user_variable("potential", "EMT") data.set_user_variable("db_keywords", ["O2", "EMT"]) data.write("O2.db") reread = cmr.read("O2.db") e2 = reread["ase_potential_energy"] assert abs(e1-e2) < 1.e-6, str(e1) + ' ' + str(e2) # clean filename = "O2.db" if os.path.exists(filename): os.unlink(filename) python-ase-3.9.1.4567/ase/test/cmr/reactions_run.py0000664000175000017500000000277512553425527022247 0ustar jensjjensj00000000000000from ase.test import NotAvailable import warnings # cmr calls all available methods in ase.atoms detected by the module inspect. # Therefore also deprecated methods are called - and we choose to silence those warnings. warnings.filterwarnings('ignore', 'ase.atoms.*deprecated',) # if CMR_SETTINGS_FILE is missing, cmr raises simply # Exception("CMR is not configured properly. Please create the settings file with cmr --create-settings.") try: import cmr except (Exception, ImportError): raise NotAvailable('CMR is required') from ase.calculators.emt import EMT from ase.structure import molecule from ase.io import write from ase.optimize import QuasiNewton # see the module for the required format of reactions definition from ase.test.cmr.reactions import reactions # assure that all reactions define a reaction_id for r in reactions: assert r[-1][0] == 'reaction_id' optimize = True calculator = EMT() # find names of compounds # (in one of the most obscure ways - python list flattening) compounds = [c[0] for c in sum([r[:-1] for r in reactions], [])] # unique compounds = list(set(compounds)) for formula in compounds: m = molecule(formula) m.set_calculator(calculator) if optimize: dyn = QuasiNewton(m, logfile=('%s.log' % formula), trajectory=('%s.traj' % formula), ) dyn.run() else: e = m.get_potential_energy() write(filename=('%s.traj' % formula), images=m, format='traj') python-ase-3.9.1.4567/ase/test/vtk_data.py0000775000175000017500000004573612553425527020417 0ustar jensjjensj00000000000000import sys from ase.test import NotAvailable if sys.platform in ['win32']: raise NotAvailable('Fails on Windows https://trac.fysik.dtu.dk/projects/ase/ticket/62') from ase.visualize.vtk import requirevtk, probe_vtk_kilobyte requirevtk() vtk_kilobyte = probe_vtk_kilobyte(1024) import numpy as np import sys, unittest, gc from ase.test import CustomTestCase, CustomTextTestRunner from ase.utils.memory import MemoryStatistics, MemorySingleton, shapeopt from vtk import vtkDataArray from ase.visualize.vtk.data import vtkFloatArrayFromNumPyArray, \ vtkDoubleArrayFromNumPyArray, \ vtkFloatArrayFromNumPyMultiArray, \ vtkDoubleArrayFromNumPyMultiArray # ------------------------------------------------------------------- class UTConversionDataArrayNumPy(CustomTestCase): """ Abstract class with test cases for VTK/NumPy data conversion. Leak tests the six possible permutations of deletion order for the objects involved in conversion between VTK and NumPy data formats. Objects: conv: instance of vtkDataArrayFromNumPyBuffer of subclass thereof The object in charge of the conversion data: NumPy array NumPy data with a specific memory footprint vtk_da: instance of vtkDataArray of subclass thereof VTK data array with a similar memory footprint Permutations: Case A: 012 i.e. deletion order is conv, data, vtk_da Case B: 021 i.e. deletion order is conv, vtk_da, data Case C: 102 i.e. deletion order is data, conv, vtk_da Case D: 120 i.e. deletion order is data, vtk_da, conv Case E: 201 i.e. deletion order is vtk_da, conv, data Case F: 210 i.e. deletion order is vtk_da, data, conv """ footprint = 100*1024**2 dtype = None verbose = 0 gc_threshold = (300,5,5) #default is (700,10,10) gc_flags = gc.DEBUG_LEAK # | gc.DEBUG_STATS ctol = -7 #10MB etol = -7 #10MB def setUp(self): self.mem_ini = MemorySingleton(self.verbose-1) self.mem_ref = MemoryStatistics(self.verbose-1) self.mem_cur = self.mem_ref.copy() self.gc_threshold_old = gc.get_threshold() self.gc_flags_old = gc.get_debug() gc.set_threshold(*self.gc_threshold) gc.set_debug(self.gc_flags) # Try to obtain a clean slate gc.collect() self.gc_count = len(gc.garbage) del gc.garbage[:] def tearDown(self): gc.collect() self.assertEqual(len(gc.garbage), self.gc_count) if len(gc.garbage)>0: if self.verbose>1: print(gc.get_objects()) #TODO be pedantic and fail? del gc.garbage[:] gc.set_threshold(*self.gc_threshold_old) gc.set_debug(self.gc_flags_old) def assertAlmostConsumed(self, bytes, digits=0, key='VmSize'): self.mem_cur.update() dm = self.mem_cur-self.mem_ref self.assertAlmostEqual(dm[key], bytes, digits) def assertAlmostExceeded(self, bytes, digits=0, key='VmPeak'): self.mem_cur.update() dm = self.mem_cur-self.mem_ini #self.assertAlmostEqual(dm[key], bytes, digits) #TODO what really? #self.assertAlmostEqual(max(0, dm[key]-bytes), 0, digits) #TODO ??? #dm = 200 MB, bytes = 100MB ok #dm = 101 MB, bytes = 100MB ok #dm = 0 MB, bytes = 100MB bad def convert_to_vtk_array(self, data): """Convert an ndarray to a VTK data array. data: NumPy array NumPy data with a specific memory footprint """ raise RuntimeError('Virtual member function.') def get_leaktest_scenario(self): """Construct the necessary conversion objects for leak testing. Returns tuple of the form (conv, data, vtk_da,) where: conv: instance of vtkDataArrayFromNumPyBuffer of subclass thereof The object in charge of the conversion data: NumPy array NumPy data with a specific memory footprint vtk_da: instance of vtkDataArray of subclass thereof VTK data array with a similar memory footprint """ raise RuntimeError('Virtual member function.') # ================================= def test_deletion_case_a(self): # Case A: 012 i.e. deletion order is conv, data, vtk_da (conv, data, vtk_da,) = self.get_leaktest_scenario() # Conversion cleanup del conv self.assertAlmostConsumed(2*self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion cleanup=', self.mem_cur-self.mem_ref) # NumPy cleanup del data self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('NumPy cleanup=', self.mem_cur-self.mem_ref) # VTK cleanup del vtk_da self.assertAlmostConsumed(0, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('VTK cleanup=', self.mem_cur-self.mem_ref) def test_deletion_case_b(self): # Case B: 021 i.e. deletion order is conv, vtk_da, data (conv, data, vtk_da,) = self.get_leaktest_scenario() # Conversion cleanup del conv self.assertAlmostConsumed(2*self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion cleanup=', self.mem_cur-self.mem_ref) # VTK cleanup del vtk_da self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('VTK cleanup=', self.mem_cur-self.mem_ref) # Numpy cleanup del data self.assertAlmostConsumed(0, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('NumPy cleanup=', self.mem_cur-self.mem_ref) def test_deletion_case_c(self): # Case C: 102 i.e. deletion order is data, conv, vtk_da (conv, data, vtk_da,) = self.get_leaktest_scenario() # NumPy cleanup del data self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('NumPy cleanup=', self.mem_cur-self.mem_ref) # Conversion cleanup del conv self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion cleanup=', self.mem_cur-self.mem_ref) # VTK cleanup del vtk_da self.assertAlmostConsumed(0, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('VTK cleanup=', self.mem_cur-self.mem_ref) def test_deletion_case_d(self): # Case D: 120 i.e. deletion order is data, vtk_da, conv (conv, data, vtk_da,) = self.get_leaktest_scenario() # NumPy cleanup del data self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('NumPy cleanup=', self.mem_cur-self.mem_ref) # VTK cleanup del vtk_da self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('VTK cleanup=', self.mem_cur-self.mem_ref) # Conversion cleanup del conv self.assertAlmostConsumed(0, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion cleanup=', self.mem_cur-self.mem_ref) def test_deletion_case_e(self): # Case E: 201 i.e. deletion order is vtk_da, conv, data (conv, data, vtk_da,) = self.get_leaktest_scenario() # VTK cleanup del vtk_da self.assertAlmostConsumed(2*self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('VTK cleanup=', self.mem_cur-self.mem_ref) # Conversion cleanup del conv self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion cleanup=', self.mem_cur-self.mem_ref) # NumPy cleanup del data self.assertAlmostConsumed(0, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('NumPy cleanup=', self.mem_cur-self.mem_ref) def test_deletion_case_f(self): # Case F: 210 i.e. deletion order is vtk_da, data, conv (conv, data, vtk_da,) = self.get_leaktest_scenario() # VTK cleanup del vtk_da self.assertAlmostConsumed(2*self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('VTK cleanup=', self.mem_cur-self.mem_ref) # NumPy cleanup del data self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('NumPy cleanup=', self.mem_cur-self.mem_ref) # Conversion cleanup del conv self.assertAlmostConsumed(0, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion cleanup=', self.mem_cur-self.mem_ref) # ------------------------------------------------------------------- # class UTDataArrayFromNumPyBuffer(...): TODO # ------------------------------------------------------------------- class UTDataArrayFromNumPyArray_Scalar(UTConversionDataArrayNumPy): """ Test cases for memory leaks during VTK/NumPy data conversion. Conversion of 1D NumPy array to VTK data array using buffers.""" def setUp(self): UTConversionDataArrayNumPy.setUp(self) self.shape = self.footprint//np.nbytes[self.dtype] def get_leaktest_scenario(self): self.assertAlmostEqual(np.prod(self.shape)*np.nbytes[self.dtype], \ self.footprint, -2) #100B # Update memory reference self.mem_ref.update() # NumPy allocation data = np.empty(self.shape, self.dtype) self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(self.footprint, self.etol) if self.verbose>=1: print('NumPy allocation=', self.mem_cur-self.mem_ref) # NumPy to VTK conversion np2da = self.convert_to_vtk_array(data) self.assertAlmostConsumed(2*self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion=', self.mem_cur-self.mem_ref) # VTK retrieval vtk_da = np2da.get_output() self.assertTrue(isinstance(vtk_da, vtkDataArray)) self.assertAlmostEqual(vtk_da.GetActualMemorySize()*vtk_kilobyte, \ self.footprint, -3) #1kB if self.verbose>=1: print('VTK retrieval=', self.mem_cur-self.mem_ref) return (np2da, data, vtk_da,) class UTFloatArrayFromNumPyArray_Scalar(UTDataArrayFromNumPyArray_Scalar): __doc__ = UTDataArrayFromNumPyArray_Scalar.__doc__ dtype = np.float32 convert_to_vtk_array = vtkFloatArrayFromNumPyArray class UTDoubleArrayFromNumPyArray_Scalar(UTDataArrayFromNumPyArray_Scalar): __doc__ = UTDataArrayFromNumPyArray_Scalar.__doc__ dtype = np.float64 convert_to_vtk_array = vtkDoubleArrayFromNumPyArray class UTDataArrayFromNumPyArray_Vector(UTConversionDataArrayNumPy): """ Test cases for memory leaks during VTK/NumPy data conversion. Conversion of 2D NumPy array to VTK data array using buffers.""" def setUp(self): UTConversionDataArrayNumPy.setUp(self) size = self.footprint//np.nbytes[self.dtype] self.shape = (size//3, 3) def get_leaktest_scenario(self): self.assertAlmostEqual(np.prod(self.shape)*np.nbytes[self.dtype], \ self.footprint, -2) #100B # Update memory reference self.mem_ref.update() # NumPy allocation data = np.empty(self.shape, self.dtype) self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(self.footprint, self.etol) if self.verbose>=1: print('NumPy allocation=', self.mem_cur-self.mem_ref) # NumPy to VTK conversion np2da = self.convert_to_vtk_array(data) self.assertAlmostConsumed(2*self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion=', self.mem_cur-self.mem_ref) # VTK retrieval vtk_da = np2da.get_output() self.assertTrue(isinstance(vtk_da, vtkDataArray)) self.assertAlmostEqual(vtk_da.GetActualMemorySize()*vtk_kilobyte, \ self.footprint, -3) #1kB if self.verbose>=1: print('VTK retrieval=', self.mem_cur-self.mem_ref) return (np2da, data, vtk_da,) class UTFloatArrayFromNumPyArray_Vector(UTDataArrayFromNumPyArray_Vector): __doc__ = UTDataArrayFromNumPyArray_Vector.__doc__ dtype = np.float32 convert_to_vtk_array = vtkFloatArrayFromNumPyArray class UTDoubleArrayFromNumPyArray_Vector(UTDataArrayFromNumPyArray_Vector): __doc__ = UTDataArrayFromNumPyArray_Vector.__doc__ dtype = np.float64 convert_to_vtk_array = vtkDoubleArrayFromNumPyArray # ------------------------------------------------------------------- class UTDataArrayFromNumPyMultiArray_Scalar(UTConversionDataArrayNumPy): """ Test cases for memory leaks during VTK/NumPy data conversion. Conversion of NumPy grid scalars to VTK data array using buffers.""" def setUp(self): UTConversionDataArrayNumPy.setUp(self) size = self.footprint//np.nbytes[self.dtype] digits, shape = shapeopt(1000, size, ndims=3, ecc=0.3) if self.verbose>=1: print('digits=%8.3f, shape=%s' % (digits,shape)) self.shape = shape + (1,) self.assertAlmostEqual(np.prod(self.shape)*np.nbytes[self.dtype], \ self.footprint, -4) #10kB def get_leaktest_scenario(self): # Update memory reference self.mem_ref.update() # NumPy allocation data = np.empty(self.shape, self.dtype) self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(self.footprint, self.etol) if self.verbose>=1: print('NumPy allocation=', self.mem_cur-self.mem_ref) # NumPy to VTK conversion np2da = self.convert_to_vtk_array(data) self.assertAlmostConsumed(2*self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion=', self.mem_cur-self.mem_ref) # VTK retrieval vtk_da = np2da.get_output() self.assertTrue(isinstance(vtk_da, vtkDataArray)) self.assertAlmostEqual(vtk_da.GetActualMemorySize()*vtk_kilobyte, \ self.footprint, -4) #10kB if self.verbose>=1: print('VTK retrieval=', self.mem_cur-self.mem_ref) return (np2da, data, vtk_da,) class UTFloatArrayFromNumPyMultiArray_Scalar(UTDataArrayFromNumPyMultiArray_Scalar): __doc__ = UTDataArrayFromNumPyMultiArray_Scalar.__doc__ dtype = np.float32 convert_to_vtk_array = vtkFloatArrayFromNumPyMultiArray class UTDoubleArrayFromNumPyMultiArray_Scalar(UTDataArrayFromNumPyMultiArray_Scalar): __doc__ = UTDataArrayFromNumPyMultiArray_Scalar.__doc__ dtype = np.float64 convert_to_vtk_array = vtkDoubleArrayFromNumPyMultiArray class UTDataArrayFromNumPyMultiArray_Vector(UTConversionDataArrayNumPy): """ Test cases for memory leaks during VTK/NumPy data conversion. Conversion of NumPy grid vectors to VTK data array using buffers.""" def setUp(self): UTConversionDataArrayNumPy.setUp(self) size = self.footprint//np.nbytes[self.dtype] digits, shape = shapeopt(1000, size//3, ndims=3, ecc=0.3) if self.verbose>=1: print('digits=%8.3f, shape=%s' % (digits,shape)) self.shape = shape + (3,) self.assertAlmostEqual(np.prod(self.shape)*np.nbytes[self.dtype], \ self.footprint, -4) #10kB def get_leaktest_scenario(self): # Update memory reference self.mem_ref.update() # NumPy allocation data = np.empty(self.shape, self.dtype) self.assertAlmostConsumed(self.footprint, self.ctol) self.assertAlmostExceeded(self.footprint, self.etol) if self.verbose>=1: print('NumPy allocation=', self.mem_cur-self.mem_ref) # NumPy to VTK conversion np2da = self.convert_to_vtk_array(data) self.assertAlmostConsumed(2*self.footprint, self.ctol) self.assertAlmostExceeded(2*self.footprint, self.etol) if self.verbose>=1: print('Conversion=', self.mem_cur-self.mem_ref) # VTK retrieval vtk_da = np2da.get_output() self.assertTrue(isinstance(vtk_da, vtkDataArray)) self.assertAlmostEqual(vtk_da.GetActualMemorySize()*vtk_kilobyte, \ self.footprint, -4) #10kB if self.verbose>=1: print('VTK retrieval=', self.mem_cur-self.mem_ref) return (np2da, data, vtk_da,) class UTFloatArrayFromNumPyMultiArray_Vector(UTDataArrayFromNumPyMultiArray_Vector): __doc__ = UTDataArrayFromNumPyMultiArray_Vector.__doc__ dtype = np.float32 convert_to_vtk_array = vtkFloatArrayFromNumPyMultiArray class UTDoubleArrayFromNumPyMultiArray_Vector(UTDataArrayFromNumPyMultiArray_Vector): __doc__ = UTDataArrayFromNumPyMultiArray_Vector.__doc__ dtype = np.float64 convert_to_vtk_array = vtkDoubleArrayFromNumPyMultiArray # ------------------------------------------------------------------- if __name__ in ['__main__', '__builtin__']: # We may have been imported by test.py, if so we should redirect to logfile if __name__ == '__builtin__': testrunner = CustomTextTestRunner('vtk_data.log', verbosity=2) else: testrunner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2) testcases = [UTFloatArrayFromNumPyArray_Scalar, \ UTDoubleArrayFromNumPyArray_Scalar, \ UTFloatArrayFromNumPyArray_Vector, \ UTDoubleArrayFromNumPyArray_Vector, \ UTFloatArrayFromNumPyMultiArray_Scalar, \ UTDoubleArrayFromNumPyMultiArray_Scalar, \ UTFloatArrayFromNumPyMultiArray_Vector, \ UTDoubleArrayFromNumPyMultiArray_Vector] for test in testcases: info = '\n' + test.__name__ + '\n' + test.__doc__.strip('\n') + '\n' testsuite = unittest.defaultTestLoader.loadTestsFromTestCase(test) testrunner.stream.writeln(info) testresult = testrunner.run(testsuite) # Provide feedback on failed tests if imported by test.py if __name__ == '__builtin__' and not testresult.wasSuccessful(): raise SystemExit('Test failed. Check vtk_data.log for details.') python-ase-3.9.1.4567/ase/test/gromacs/0000775000175000017500000000000012553427753017664 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/gromacs/__init__.py0000775000175000017500000000000012553425527021763 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/gromacs/test_gromacs.py0000775000175000017500000000475612553425527022744 0ustar jensjjensj00000000000000""" test run for gromacs calculator """ from ase.test import NotAvailable from ase.calculators.gromacs import Gromacs import os, glob if Gromacs().get_command() is None: raise NotAvailable( 'Gromacs required, setup your GMXCMD environmental variable') GRO_INIT_FILE = 'hise_box.gro' #write structure file outfile = open('hise_box.gro', 'w') outfile.write('HISE for testing \n') outfile.write(' 20 \n') outfile.write(' 3HISE N 1 1.966 1.938 1.722 \n') outfile.write(' 3HISE H1 2 2.053 1.892 1.711 \n') outfile.write(' 3HISE H2 3 1.893 1.882 1.683 \n') outfile.write(' 3HISE H3 4 1.969 2.026 1.675 \n') outfile.write(' 3HISE CA 5 1.939 1.960 1.866 \n') outfile.write(' 3HISE HA 6 1.934 1.869 1.907 \n') outfile.write(' 3HISE CB 7 2.055 2.041 1.927 \n') outfile.write(' 3HISE HB1 8 2.141 2.007 1.890 \n') outfile.write(' 3HISE HB2 9 2.043 2.137 1.903 \n') outfile.write(' 3HISE ND1 10 1.962 2.069 2.161 \n') outfile.write(' 3HISE CG 11 2.065 2.032 2.077 \n') outfile.write(' 3HISE CE1 12 2.000 2.050 2.287 \n') outfile.write(' 3HISE HE1 13 1.944 2.069 2.368 \n') outfile.write(' 3HISE NE2 14 2.123 2.004 2.287 \n') outfile.write(' 3HISE HE2 15 2.177 1.981 2.369 \n') outfile.write(' 3HISE CD2 16 2.166 1.991 2.157 \n') outfile.write(' 3HISE HD2 17 2.256 1.958 2.128 \n') outfile.write(' 3HISE C 18 1.806 2.032 1.888 \n') outfile.write(' 3HISE OT1 19 1.736 2.000 1.987 \n') outfile.write(' 3HISE OT2 20 1.770 2.057 2.016 \n') outfile.write(' 4.00000 4.00000 4.00000 \n') outfile.close() CALC_MM_RELAX = Gromacs(force_field='charmm27', define = '-DFLEXIBLE', integrator = 'cg', nsteps = '10000', nstfout = '10', nstlog = '10', nstenergy = '10', nstlist = '10', ns_type = 'grid', pbc = 'xyz', rlist = '0.7', coulombtype = 'PME-Switch', rcoulomb = '0.6', vdwtype = 'shift', rvdw = '0.6', rvdw_switch = '0.55', DispCorr = 'Ener') CALC_MM_RELAX.set_own_params_runs( 'init_structure', 'hise_box.gro') CALC_MM_RELAX.generate_topology_and_g96file() CALC_MM_RELAX.write_input() CALC_MM_RELAX.generate_gromacs_run_file() CALC_MM_RELAX.run() atoms = CALC_MM_RELAX.get_atoms() final_energy = CALC_MM_RELAX.get_potential_energy(atoms) assert abs(final_energy + 4.06503308131) < 5e-3 python-ase-3.9.1.4567/ase/test/mic.py0000664000175000017500000001145112553425527017352 0ustar jensjjensj00000000000000import ase import numpy as np tol = 1e-9 cell = np.array([[1., 0., 0.], [0.5, np.sqrt(3) / 2, 0.], [0., 0., 1.]]) * 10 pos = np.dot(np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5], [0.2, 0.2, 0.2], [0.25, 0.5, 0.0]]), cell) a = ase.Atoms('C4', pos, cell=cell, pbc=True) rpos = a.get_scaled_positions() # non-mic distance between atom 0 and 1 d01F = np.linalg.norm(np.dot(rpos[1], cell)) # mic distance between atom 0 (image [0,1,0]) and 1 d01T = np.linalg.norm(np.dot(rpos[1] - np.array([0, 1, 0]), cell)) d02F = np.linalg.norm(np.dot(rpos[2], cell)) d02T = d02F # non-mic distance between atom 0 and 3 d03F = np.linalg.norm(np.dot(rpos[3], cell)) # mic distance between atom 0 (image [0,1,0]) and 3 d03T = np.linalg.norm(np.dot(rpos[3] - np.array([0, 1, 0]), cell)) # get_distance(mic=False) assert abs(a.get_distance(0, 1, mic=False) - d01F) < tol assert abs(a.get_distance(0, 2, mic=False) - d02F) < tol assert abs(a.get_distance(0, 3, mic=False) - d03F) < tol # get_distance(mic=True) assert abs(a.get_distance(0, 1, mic=True) - d01T) < tol assert abs(a.get_distance(0, 2, mic=True) - d02T) < tol assert abs(a.get_distance(0, 3, mic=True) - d03T) < tol # get_distance(mic=False, vector=True) assert all(abs(a.get_distance(0, 1, mic=False, vector=True) - np.array([7.5, np.sqrt(18.75), 5.0])) < tol) assert all(abs(a.get_distance(0, 2, mic=False, vector=True) - np.array([3., np.sqrt(3.), 2.0])) < tol) # get_distance(mic=True, vector=True) assert np.all(abs(a.get_distance(0, 1, mic=True, vector=True) - np.array([-2.5, np.sqrt(18.75), -5.0])) < tol) assert np.all(abs(a.get_distance(0, 2, mic=True, vector=True) - np.array([3., np.sqrt(3.), 2.0])) < tol) # get_all_distances(mic=False) all_dist = a.get_all_distances(mic=False) assert abs(all_dist[0, 1] - d01F) < tol assert abs(all_dist[0, 2] - d02F) < tol assert abs(all_dist[0, 3] - d03F) < tol assert all(abs(np.diagonal(all_dist)) < tol) # get_all_distances(mic=True) all_dist_mic = a.get_all_distances(mic=True) assert abs(all_dist_mic[0, 1] - d01T) < tol assert abs(all_dist_mic[0, 2] - d02T) < tol assert abs(all_dist_mic[0, 3] - d03T) < tol assert all(abs(np.diagonal(all_dist)) < tol) # get_distances(mic=False) for i in range(4): assert all(abs(a.get_distances(i, [0, 1, 2, 3], mic=False) - all_dist[i]) < tol) # get_distances(mic=True) assert all(abs(a.get_distances(0, [0, 1, 2, 3], mic=True) - all_dist_mic[0]) < tol) assert all(abs(a.get_distances(1, [0, 1, 2, 3], mic=True) - all_dist_mic[1]) < tol) assert all(abs(a.get_distances(2, [0, 1, 2, 3], mic=True) - all_dist_mic[2]) < tol) assert all(abs(a.get_distances(3, [0, 1, 2, 3], mic=True) - all_dist_mic[3]) < tol) # get_distances(mic=False, vec=True) assert np.all(abs(a.get_distances(0, [0, 1, 2, 3], mic=False, vector=True) - np.array([a.get_distance(0, i, vector=True) for i in [0, 1, 2, 3]])) < tol) assert np.all(abs(a.get_distances(1, [0, 1, 2, 3], mic=False, vector=True) - np.array([a.get_distance(1, i, vector=True) for i in [0, 1, 2, 3]])) < tol) assert np.all(abs(a.get_distances(2, [0, 1, 2, 3], mic=False, vector=True) - np.array([a.get_distance(2, i, vector=True) for i in [0, 1, 2, 3]])) < tol) assert np.all(abs(a.get_distances(3, [0, 1, 2, 3], mic=False, vector=True) - np.array([a.get_distance(3, i, vector=True) for i in [0, 1, 2, 3]])) < tol) # get_distances(mic=True, vec=True) assert np.all(abs(a.get_distances(0, [0, 1, 2, 3], mic=True, vector=True) - np.array([a.get_distance(0, i, mic=True, vector=True) for i in [0, 1, 2, 3]])) < tol) assert np.all(abs(a.get_distances(1, [0, 1, 2, 3], mic=True, vector=True) - np.array([a.get_distance(1, i, mic=True, vector=True) for i in [0, 1, 2, 3]])) < tol) assert np.all(abs(a.get_distances(2, [0, 1, 2, 3], mic=True, vector=True) - np.array([a.get_distance(2, i, mic=True, vector=True) for i in [0, 1, 2, 3]])) < tol) assert np.all(abs(a.get_distances(3, [0, 1, 2, 3], mic=True, vector=True) - np.array([a.get_distance(3, i, mic=True, vector=True) for i in [0, 1, 2, 3]])) < tol) # set_distance a.set_distance(0, 1, 11., mic=False) assert abs(a.get_distance(0, 1, mic=False) - 11.) < tol assert abs(a.get_distance(0, 1, mic=True) - np.sqrt(46)) < tol # set_distance(mic=True) a.set_distance(0, 1, 3., mic=True) assert abs(a.get_distance(0, 1, mic=True) - 3.) < tol python-ase-3.9.1.4567/ase/test/fix_bond_length_mic.py0000664000175000017500000000136112553425527022562 0ustar jensjjensj00000000000000import ase from ase.calculators.lj import LennardJones from ase.constraints import FixBondLength from ase.optimize import FIRE for wrap in [False, True]: a = ase.Atoms('CCC', positions=[[1, 0, 5], [0, 1, 5], [-1, 0.5, 5]], cell=[10, 10, 10], pbc=True) if wrap: a.set_scaled_positions(a.get_scaled_positions() % 1.0) a.set_calculator(LennardJones()) a.set_constraint(FixBondLength(0, 2)) d1 = a.get_distance(0, 2, mic=True) FIRE(a, logfile=None).run(fmax=0.01) e = a.get_potential_energy() d2 = a.get_distance(0, 2, mic=True) assert abs(e - -2.034988) < 1e-6 assert abs(d1 - d2) < 1e-6 python-ase-3.9.1.4567/ase/test/constr_setpos.py0000664000175000017500000000142312553425527021505 0ustar jensjjensj00000000000000import numpy as np def array_almost_equal(a1, a2, tol=np.finfo(type(1.0)).eps): """Replacement for old numpy.testing.utils.array_almost_equal.""" return (np.abs(a1 - a2) < tol).all() from ase.structure import molecule from ase.constraints import FixAtoms m = molecule('H2') c = FixAtoms(indices=[atom.index for atom in m]) m.set_constraint(c) pos1 = m.get_positions() # shift z-coordinates by 1. pos = m.get_positions() pos[:, 2] += 1. m.set_positions(pos) # note that set_positions fails silently to set the new positions # due to the presence of constraints! assert array_almost_equal(pos1, m.get_positions()) m.positions = pos # atoms.positions allows one to set the new positions # even in the presence of constraints! assert array_almost_equal(pos, m.get_positions()) python-ase-3.9.1.4567/ase/test/elk/0000775000175000017500000000000012553427753017004 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/elk/__init__.py0000664000175000017500000000000012553425527021100 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/elk/elk_cmdline.py0000664000175000017500000000036512553425527021625 0ustar jensjjensj00000000000000from ase.test import cli, require # warning! parameters are not converged - only an illustration! require('elk') cli("""ase-build -x fcc -a 4.04 Al | \ ase-run elk -p \ "tasks=0,kpts=1.5,rgkmax=5.0,tforce=True,smearing=(fermi-dirac,0.05)" """) python-ase-3.9.1.4567/ase/test/elk/Al_rmt.py0000664000175000017500000000437512553425527020602 0ustar jensjjensj00000000000000import os from ase.test import NotAvailable from ase.lattice import bulk from ase.calculators.calculator import kpts2mp from ase.calculators.elk import ELK atoms = bulk('Al', 'bcc', a=4.0) # save ELK_SPECIES_PATH ELK_SPECIES_PATH = os.environ.get('ELK_SPECIES_PATH', None) if ELK_SPECIES_PATH is None: raise NotAvailable('ELK_SPECIES_PATH not set.') # find rmt of the default species sfile = os.path.join(os.environ['ELK_SPECIES_PATH'], 'elk.in') assert os.path.exists(sfile) slines = open(sfile, 'r').readlines() rmt_orig = {} for name in ['Al']: found = False for n, line in enumerate(slines): if line.find("'" + name + "'") > -1: begline = n - 1 for n, line in enumerate(slines[begline:]): if not line.strip(): # first empty line endline = n found = True break assert found # split needed because H is defined with comments rmt_orig[name] = float(slines[begline + 3].split()[0].strip()) assert rmt_orig['Al'] == 2.2 # 2.2 Bohr default # test1 # generate species with custom rmt 2.1 rmt = {'Al': 2.1} label = 'rmt2.1' atomsrmt = atoms.copy() os.environ['ELK_SPECIES_PATH'] = ELK_SPECIES_PATH atomsrmt.calc = ELK(tasks=0, label=label, rmt=rmt) # minimal calc atomsrmt.get_potential_energy() del atomsrmt.calc del atomsrmt # hack ELK_SPECIES_PATH to use custom species os.environ['ELK_SPECIES_PATH'] = os.path.abspath(label) + '/' # run calculation calc = ELK(tasks=0, label=label, rgkmax=4.0, kpts=tuple(kpts2mp(atoms, 2.0, even=True))) atoms.set_calculator(calc) e1 = atoms.get_potential_energy() # test2 # generate species with custom rmt 2.1 rmt = {'Al': -0.1} label = 'rmt0.1m' atomsrmt = atoms.copy() os.environ['ELK_SPECIES_PATH'] = ELK_SPECIES_PATH atomsrmt.calc = ELK(tasks=0, label=label, rmt=rmt) # minimal calc atomsrmt.get_potential_energy() del atomsrmt.calc del atomsrmt # hack ELK_SPECIES_PATH to use custom species os.environ['ELK_SPECIES_PATH'] = os.path.abspath(label) + '/' # run calculation calc = ELK(tasks=0, label=label, rgkmax=4.0, kpts=tuple(kpts2mp(atoms, 2.0, even=True))) atoms.set_calculator(calc) e2 = atoms.get_potential_energy() # restore ELK_SPECIES_PATH os.environ['ELK_SPECIES_PATH'] = ELK_SPECIES_PATH assert abs(e1 - e2) < 1.0e-4 python-ase-3.9.1.4567/ase/test/scientificpython_bug.py0000664000175000017500000000145612553425527023025 0ustar jensjjensj00000000000000from __future__ import print_function import sys import numpy as np msg = "\n'TypeError: array cannot be safely cast to required type'\n" msg += "means you are probably using a broken ScientficPython, \n" msg += "see: https://bugs.launchpad.net/ubuntu/+source/python-scientific/+bug/1041302\n" import Scientific.IO.NetCDF as netcdf import Scientific version = Scientific.__version__.split(".") print('Found ScientificPython version: ',Scientific.__version__) if list(map(int,version)) < [2,8]: print('ScientificPython 2.8 or greater required for numpy support in NetCDF') raise RuntimeError('ScientificPython version 2.8 or greater is requied') handle = netcdf.NetCDFFile("test.nc", "w") try: handle.test = np.array([1.0]) except TypeError: print(msg, file=sys.stderr) raise handle.close() python-ase-3.9.1.4567/ase/test/geometry.py0000664000175000017500000001442212553425527020436 0ustar jensjjensj00000000000000"""Test the ase.utils.geometry module""" import numpy as np from ase.lattice.spacegroup import crystal from ase.utils.geometry import get_layers, cut, stack from ase.atoms import Atoms np.set_printoptions(suppress=True) al = crystal('Al', [(0, 0, 0)], spacegroup=225, cellpar=4.05) # Cut out slab of 5 Al(001) layers al001 = cut(al, nlayers=5) correct_pos = np.array([[ 0. , 0. , 0. ], [ 0. , 0.5, 0.2], [ 0.5, 0. , 0.2], [ 0.5, 0.5, 0. ], [ 0. , 0. , 0.4], [ 0. , 0.5, 0.6], [ 0.5, 0. , 0.6], [ 0.5, 0.5, 0.4], [ 0. , 0. , 0.8], [ 0.5, 0.5, 0.8]]) assert np.allclose(correct_pos, al001.get_scaled_positions()) # Check layers along 001 tags, levels = get_layers(al001, (0, 0, 1)) assert np.allclose(tags, [0, 1, 1, 0, 2, 3, 3, 2, 4, 4]) assert np.allclose(levels, [ 0., 2.025, 4.05, 6.075, 8.1]) # Check layers along 101 tags, levels = get_layers(al001, (1, 0, 1)) assert np.allclose(tags, [0, 1, 5, 3, 2, 4, 8, 7, 6, 9]) assert np.allclose(levels, [0.000, 0.752, 1.504, 1.880, 2.256, 2.632, 3.008, 3.384, 4.136, 4.888], atol=0.001) # Check layers along 111 tags, levels = get_layers(al001, (1, 1, 1)) assert np.allclose(tags, [0, 2, 2, 4, 1, 5, 5, 6, 3, 7]) assert np.allclose(levels, [0.000, 1.102, 1.929, 2.205, 2.756, 3.031, 3.858, 4.960], atol=0.001) # Cut out slab of three Al(111) layers al111 = cut(al, (1, -1, 0), (0, 1, -1), nlayers=3) correct_pos = np.array([[ 0.5 , 0. , 0. ], [ 0. , 0.5 , 0. ], [ 0.5 , 0.5 , 0. ], [ 0. , 0. , 0. ], [ 1/6. , 1/3. , 1/3. ], [ 1/6. , 5/6. , 1/3. ], [ 2/3. , 5/6. , 1/3. ], [ 2/3. , 1/3. , 1/3. ], [ 1/3. , 1/6. , 2/3. ], [ 5/6. , 1/6. , 2/3. ], [ 5/6. , 2/3. , 2/3. ], [ 1/3. , 2/3. , 2/3. ]]) assert np.allclose(correct_pos, al111.get_scaled_positions()) # Cut out cell including all corner and edge atoms (non-periodic structure) al = cut(al, extend=1.1) correct_pos = np.array([[ 0. , 0. , 0. ], [ 0. , 2.025, 2.025], [ 2.025, 0. , 2.025], [ 2.025, 2.025, 0. ], [ 0. , 0. , 4.05 ], [ 2.025, 2.025, 4.05 ], [ 0. , 4.05 , 0. ], [ 2.025, 4.05 , 2.025], [ 0. , 4.05 , 4.05 ], [ 4.05 , 0. , 0. ], [ 4.05 , 2.025, 2.025], [ 4.05 , 0. , 4.05 ], [ 4.05 , 4.05 , 0. ], [ 4.05 , 4.05 , 4.05 ]]) assert np.allclose(correct_pos, al.positions) # Create an Ag(111)/Si(111) interface ag = crystal(['Ag'], basis=[(0, 0, 0)], spacegroup=225, cellpar=4.09) si = crystal(['Si'], basis=[(0, 0, 0)], spacegroup=227, cellpar=5.43) ag111 = cut(ag, a=(4, -4, 0), b=(4, 4, -8), nlayers=5) si111 = cut(si, a=(3, -3, 0), b=(3, 3, -6), nlayers=5) # #interface = stack(ag111, si111) #assert len(interface) == 1000 #assert np.allclose(interface.positions[::100], # [[ 4.08125 , -2.040625 , -2.040625 ], # [ 8.1625 , 6.121875 , -14.284375 ], # [ 10.211875 , 0.00875 , 2.049375 ], # [ 24.49041667, -4.07833333, -16.32208333], # [ 18.37145833, 14.29020833, -24.48166667], # [ 24.49916667, 12.25541667, -20.39458333], # [ 18.36854167, 16.32791667, -30.60645833], # [ 19.0575 , 0.01166667, 5.45333333], # [ 23.13388889, 6.80888889, 1.36722222], # [ 35.3825 , 5.45333333, -16.31333333]]) # # Test the wrap function. scaled_positions = np.array([ [ 2.0, 3.2, 4.3], ]) cell = np.array( [[5.43, 5.43, 0.0], [5.43, -5.43, 0.0], [0.00, 0.00, 40.0], ]) atoms = Atoms(scaled_positions=scaled_positions, symbols=['Si'], cell=cell, pbc=[True, True, False]) atoms.wrap() correct_pos = np.array([0.0, 0.2, 4.3]) assert np.allclose(correct_pos, atoms.get_scaled_positions(wrap=False)) positions = np.array([ [ 4.0725, -4.0725, -1.3575], [ 1.3575, -1.3575, -1.3575], [ 2.715 , -2.715 , 0. ], [ 4.0725, 1.3575, -1.3575], [ 0. , 0. , 0. ], [ 2.715 , 2.715 , 0. ], [ 6.7875, -1.3575, -1.3575], [ 5.43 , 0. , 0. ] ]) cell = np.array( [[5.43, 5.43, 0.0], [5.43, -5.43, 0.0], [0.00, 0.00, 40.0], ]) atoms = Atoms(positions=positions, symbols=['Si']*8, cell=cell, pbc=[True, True, False], ) atoms.translate(np.array([6.1, -0.1, 10.1])) result_atoms = atoms.copy() result_atoms.wrap() correct_pos = np.array([ [ 4.7425, 1.2575, 8.7425], [ 7.4575, -1.4575, 8.7425], [ 3.385 , 2.615 , 10.1 ], [ 4.7425, -4.1725, 8.7425], [ 6.1 , -0.1 , 10.1 ], [ 3.385 , -2.815 , 10.1 ], [ 2.0275, -1.4575, 8.7425], [ 0.67 , -0.1 , 10.1 ], ]) assert np.allclose(correct_pos, result_atoms.get_positions()) result_atoms = atoms.copy() result_atoms.wrap(pbc=[False, True, False]) correct_pos = np.array([ [ 4.7425, 1.2575, 8.7425], [ 7.4575, -1.4575, 8.7425], [ 3.385 , 2.615 , 10.1 ], [ 10.1725, 1.2575, 8.7425], [ 6.1 , -0.1 , 10.1 ], [ 8.815 , 2.615 , 10.1 ], [ 7.4575, 3.9725, 8.7425], [ 6.1 , 5.33 , 10.1 ], ]) assert np.allclose(correct_pos, result_atoms.get_positions()) python-ase-3.9.1.4567/ase/test/dependency_matplotlib.py0000664000175000017500000000210512553425527023143 0ustar jensjjensj00000000000000from __future__ import print_function import sys msg = "\nThe matplotlib python module is missing or not installed properly.\n" msg += "Is the PYTHONPATH environment variable set correctly?\n" msg += "Please verify your installation by running on the command line:\n" msg += "python -c 'import matplotlib'\n" msg += "\n" msg += "This module is optional and required in order to use " msg += "ASE's simple GUI (ase-gui).\n" msg += "If you don't wish to use ase-gui ignore this error, otherwise\n" msg += "please install the package using " msg += "your distribution package manager, i.e.:\n" msg += "\n" msg += " Debian/Ubuntu: sudo apt-get python-matplotlib\n" msg += "\n" msg += " OpenSUSE: yast -i python-matplotlib\n" msg += "\n" msg += " Red Hat/Fedora: yum install python-matplotlib\n" msg += "\n" msg += "or perform manual installation, preferably as non-root user,\n" msg += "following http://matplotlib.sourceforge.net/users/installing.html." if locals().get('display'): try: import matplotlib except ImportError: print(msg, file=sys.stderr) raise python-ase-3.9.1.4567/ase/test/bandgap.py0000664000175000017500000000302012553425527020167 0ustar jensjjensj00000000000000import numpy as np from ase.dft.bandgap import get_band_gap class Calculator: def __init__(self, e_skn): self.e_skn = np.array(e_skn, dtype=float) self.ns, self.nk, self.nb = self.e_skn.shape def get_ibz_k_points(self): k = np.zeros((self.nk, 3)) k[:, 0] += np.arange(self.nk) return k def get_fermi_level(self): return 0.0 def get_eigenvalues(self, kpt, spin): return self.e_skn[spin, kpt] def get_number_of_spins(self): return self.ns def test(e_skn): c = Calculator(e_skn) if c.ns == 1: result = [get_band_gap(c), get_band_gap(c, True)] else: result = [get_band_gap(c), get_band_gap(c, True), get_band_gap(c, False, 0), get_band_gap(c, True, 0), get_band_gap(c, False, 1), get_band_gap(c, True, 1)] print(result) return result r = test([[[-1, 1]]]) assert r == [(2, 0, 0), (2, 0, 0)] r = test([[[-1, 2], [-3, 1]]]) assert r == [(2, 0, 1), (3, 0, 0)] r = test([[[-1, 2, 3], [-1, -1, 1]]]) assert r == [(0, None, None), (0, None, None)] r = test([[[-1, 2, 3], [-1, -1, 1]], [[-1, 2, 2], [-3, 1, 1]]]) assert r == [(0, (None, None), (None, None)), (0, (None, None), (None, None)), (0, None, None), (0, None, None), (2, 0, 1), (3, 0, 0)] r = test([[[-1, 5], [-2, 2]], [[-2, 4], [-4, 1]]]) assert r == [(2, (0, 0), (1, 1)), (4, (0, 1), (0, 1)), (3, 0, 1), (4, 1, 1), (3, 0, 1), (5, 1, 1)] python-ase-3.9.1.4567/ase/test/vtk_pipeline.py0000775000175000017500000004044212553425527021300 0ustar jensjjensj00000000000000from ase.visualize.vtk import requirevtk requirevtk() import sys, unittest from ase.test import CustomTextTestRunner from vtk import vtkContourFilter, vtkPolyDataNormals, \ vtkLinearSubdivisionFilter, vtkPolyDataMapper from ase.visualize.vtk.pipeline import vtkPolyDataPipeline class UTPipeline(unittest.TestCase): """ Abstract test case class - TODO.""" def assertConnected(self, vtk_one, vtk_two, port=0): self.assertEqual(vtk_two.GetNumberOfInputConnections(port), 1) self.assertEqual(vtk_one.GetOutputPort(), vtk_two.GetInputConnection(port, 0)) def assertNotConnected(self, vtk_one, vtk_two, port=0): self.assertEqual(vtk_two.GetNumberOfInputConnections(port), 0) # ------------------------------------------------------------------- class UTPolyDataPipeline(UTPipeline): """ TODO""" def setUp(self): self.vtk_iso = vtkContourFilter() #self.vtk_iso.SetInput(...) self.vtk_dnorm = vtkPolyDataNormals() self.vtk_subdiv = vtkLinearSubdivisionFilter() self.vtk_dmap = vtkPolyDataMapper() def tearDown(self): del self.vtk_dmap del self.vtk_subdiv del self.vtk_dnorm del self.vtk_iso # ------------------------------------------------------------------- class UTPolyDataPipeline_PureVTK(UTPolyDataPipeline): """ Consistency tests for pure-VTK objects with the purpose of ultimately mapping the polygonal data within the pipeline.""" # ================================= def test_consistent_data_oninit(self): pipeline = vtkPolyDataPipeline(self.vtk_iso) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, self.vtk_iso) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(self.vtk_dnorm) self.assertConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.append(self.vtk_dmap) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasfilters()) self.assertTrue(pipeline.isclosed()) def test_consistent_data_direct(self): pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.set_data(self.vtk_iso) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, self.vtk_iso) pipeline.append(self.vtk_dnorm) self.assertConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.append(self.vtk_dmap) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasfilters()) self.assertTrue(pipeline.isclosed()) def test_consistent_data_postponed(self): pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(self.vtk_dnorm) self.assertTrue(pipeline.hasfilters()) self.assertNotConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.set_data(self.vtk_iso) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, self.vtk_iso) self.assertConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_dmap) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasdata()) self.assertTrue(pipeline.isclosed()) def test_consistent_data_onclose(self): pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(self.vtk_dnorm) self.assertTrue(pipeline.hasfilters()) self.assertNotConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.append(self.vtk_dmap) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.isclosed()) pipeline.set_data(self.vtk_iso) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, self.vtk_iso) self.assertConnected(self.vtk_iso, self.vtk_dnorm) # ================================= def test_failure_duplicate_data(self): pipeline = vtkPolyDataPipeline(self.vtk_iso) self.assertRaises(ValueError, pipeline.append, self.vtk_iso) def test_failure_duplicate_mixed(self): pipeline = vtkPolyDataPipeline(self.vtk_iso) pipeline.append(self.vtk_dnorm) self.assertRaises(ValueError, pipeline.append, self.vtk_iso) def test_failure_duplicate_cyclic(self): pipeline = vtkPolyDataPipeline(self.vtk_iso) pipeline.append(self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertRaises(ValueError, pipeline.append, self.vtk_dnorm) def test_failure_duplicate_filter(self): pipeline = vtkPolyDataPipeline(self.vtk_iso) pipeline.append(self.vtk_dnorm) self.assertRaises(ValueError, pipeline.append, self.vtk_dnorm) # ================================= def test_failure_output_missing(self): pipeline = vtkPolyDataPipeline() self.assertRaises(RuntimeError, pipeline.get_output_port) def test_failure_output_closed(self): pipeline = vtkPolyDataPipeline(self.vtk_iso) pipeline.append(self.vtk_dmap) self.assertRaises(RuntimeError, pipeline.append, self.vtk_dnorm) # ------------------------------------------------------------------- class UTPolyDataPipeline_PipelineVTK(UTPolyDataPipeline): """ Consistency tests for mixed VTK objects and pipelines with the purpose of ultimately mapping the polygonal data through embedded pipelines.""" # ================================= def get_consistent_datapipe(self): datapipe = vtkPolyDataPipeline(self.vtk_iso) self.assertTrue(datapipe.hasdata()) self.assertTrue(self.vtk_iso in datapipe) self.assertEqual(datapipe.vtkish_data, self.vtk_iso) self.assertFalse(datapipe.hasfilters()) self.assertFalse(datapipe.isclosed()) return datapipe def test_consistent_datapipe_oninit(self): datapipe = self.get_consistent_datapipe() pipeline = vtkPolyDataPipeline(datapipe) self.assertTrue(pipeline.hasdata()) self.assertTrue(datapipe in pipeline) self.assertTrue(self.vtk_iso in pipeline) self.assertEqual(pipeline.vtkish_data, datapipe) self.assertRaises(RuntimeError, datapipe.isclosed) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(self.vtk_dnorm) self.assertConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.append(self.vtk_dmap) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasfilters()) self.assertTrue(pipeline.isclosed()) def test_consistent_datapipe_direct(self): datapipe = self.get_consistent_datapipe() pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(datapipe in pipeline) self.assertFalse(self.vtk_iso in pipeline) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.set_data(datapipe) self.assertTrue(pipeline.hasdata()) self.assertTrue(datapipe in pipeline) self.assertTrue(self.vtk_iso in pipeline) self.assertEqual(pipeline.vtkish_data, datapipe) self.assertRaises(RuntimeError, datapipe.isclosed) pipeline.append(self.vtk_dnorm) self.assertConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.append(self.vtk_dmap) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasfilters()) self.assertTrue(pipeline.isclosed()) def test_consistent_datapipe_postponed(self): datapipe = self.get_consistent_datapipe() pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(datapipe in pipeline) self.assertFalse(self.vtk_iso in pipeline) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(self.vtk_dnorm) self.assertTrue(pipeline.hasfilters()) self.assertNotConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.set_data(datapipe) self.assertTrue(pipeline.hasdata()) self.assertTrue(datapipe in pipeline) self.assertTrue(self.vtk_iso in pipeline) self.assertEqual(pipeline.vtkish_data, datapipe) self.assertConnected(self.vtk_iso, self.vtk_dnorm) self.assertTrue(datapipe.isclosed()) pipeline.append(self.vtk_dmap) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasdata()) self.assertTrue(pipeline.isclosed()) def test_consistent_datapipe_onclose(self): datapipe = self.get_consistent_datapipe() pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(datapipe in pipeline) self.assertFalse(self.vtk_iso in pipeline) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(self.vtk_dnorm) self.assertTrue(pipeline.hasfilters()) self.assertNotConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.append(self.vtk_dmap) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.isclosed()) pipeline.set_data(datapipe) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, datapipe) self.assertConnected(self.vtk_iso, self.vtk_dnorm) self.assertTrue(datapipe.isclosed()) # ================================= def get_consistent_filterpipe(self): filterpipe = vtkPolyDataPipeline() self.assertFalse(filterpipe.hasdata()) self.assertFalse(self.vtk_iso in filterpipe) self.assertFalse(filterpipe.hasfilters()) self.assertFalse(filterpipe.isclosed()) filterpipe.append(self.vtk_dnorm) self.assertTrue(filterpipe.hasfilters()) self.assertNotConnected(self.vtk_iso, self.vtk_dnorm) filterpipe.append(self.vtk_subdiv) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) return filterpipe def test_consistent_filterpipe_oninit(self): filterpipe = self.get_consistent_filterpipe() pipeline = vtkPolyDataPipeline(self.vtk_iso) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, self.vtk_iso) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(filterpipe) self.assertRaises(RuntimeError, filterpipe.isclosed) self.assertConnected(self.vtk_iso, self.vtk_dnorm) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) self.assertFalse(pipeline.isclosed()) pipeline.append(self.vtk_dmap) self.assertTrue(filterpipe.isclosed()) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasfilters()) self.assertTrue(pipeline.isclosed()) def test_consistent_filterpipe_direct(self): filterpipe = self.get_consistent_filterpipe() pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.set_data(self.vtk_iso) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, self.vtk_iso) pipeline.append(filterpipe) self.assertRaises(RuntimeError, filterpipe.isclosed) self.assertConnected(self.vtk_iso, self.vtk_dnorm) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) self.assertFalse(pipeline.isclosed()) pipeline.append(self.vtk_dmap) self.assertTrue(filterpipe.isclosed()) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasfilters()) self.assertTrue(pipeline.isclosed()) def test_consistent_filterpipe_postponed(self): filterpipe = self.get_consistent_filterpipe() pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(filterpipe) self.assertRaises(RuntimeError, filterpipe.isclosed) self.assertNotConnected(self.vtk_iso, self.vtk_dnorm) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.set_data(self.vtk_iso) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, self.vtk_iso) self.assertConnected(self.vtk_iso, self.vtk_dnorm) pipeline.append(self.vtk_dmap) self.assertTrue(filterpipe.isclosed()) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertTrue(pipeline.hasdata()) self.assertTrue(pipeline.isclosed()) def test_consistent_filterdata_onclose(self): filterpipe = self.get_consistent_filterpipe() pipeline = vtkPolyDataPipeline() self.assertFalse(pipeline.hasdata()) self.assertFalse(pipeline.hasfilters()) self.assertFalse(pipeline.isclosed()) pipeline.append(filterpipe) self.assertRaises(RuntimeError, filterpipe.isclosed) self.assertNotConnected(self.vtk_iso, self.vtk_dnorm) self.assertConnected(self.vtk_dnorm, self.vtk_subdiv) pipeline.append(self.vtk_dmap) self.assertTrue(filterpipe.isclosed()) self.assertConnected(self.vtk_subdiv, self.vtk_dmap) self.assertFalse(pipeline.hasdata()) self.assertTrue(pipeline.isclosed()) pipeline.set_data(self.vtk_iso) self.assertTrue(pipeline.hasdata()) self.assertEqual(pipeline.vtkish_data, self.vtk_iso) self.assertConnected(self.vtk_iso, self.vtk_dnorm) # ================================= def test_failure_recursive_data(self): pipeline = vtkPolyDataPipeline() self.assertRaises(ValueError, pipeline.set_data, pipeline) def test_failure_recursive_mixed(self): pipeline = vtkPolyDataPipeline(self.vtk_iso) pipeline.append(self.vtk_dnorm) self.assertRaises(ValueError, pipeline.append, pipeline) def test_failure_recursive_filter(self): pipeline = vtkPolyDataPipeline() self.assertRaises(ValueError, pipeline.append, pipeline) # ------------------------------------------------------------------- if __name__ in ['__main__', '__builtin__']: # We may have been imported by test.py, if so we should redirect to logfile if __name__ == '__builtin__': testrunner = CustomTextTestRunner('vtk_pipeline.log', verbosity=2) else: testrunner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2) testcases = [UTPolyDataPipeline_PureVTK, UTPolyDataPipeline_PipelineVTK] for test in testcases: info = '\n' + test.__name__ + '\n' + test.__doc__.strip('\n') + '\n' testsuite = unittest.defaultTestLoader.loadTestsFromTestCase(test) testrunner.stream.writeln(info) testresult = testrunner.run(testsuite) # Provide feedback on failed tests if imported by test.py if __name__ == '__builtin__' and not testresult.wasSuccessful(): raise SystemExit('Test failed. Check vtk_pipeline.log for details.') python-ase-3.9.1.4567/ase/test/jacapo/0000775000175000017500000000000012553427753017466 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/jacapo/__init__.py0000664000175000017500000000000012553425527021562 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/jacapo/jacapo.py0000664000175000017500000000110012553425527021262 0ustar jensjjensj00000000000000import os from ase import Atoms, Atom from ase.io import write from ase.calculators.jacapo import Jacapo atoms = Atoms([Atom('H',[0,0,0])], cell=(2,2,2), pbc=True) calc = Jacapo('Jacapo-test.nc', pw=200, nbands=2, kpts=(1,1,1), spinpol=False, dipole=False, symmetry=False, ft=0.01) atoms.set_calculator(calc) print(atoms.get_potential_energy()) write('Jacapo-test.traj', atoms) os.system('rm -f Jacapo-test.nc Jacapo-test.txt Jacapo-test.traj') python-ase-3.9.1.4567/ase/test/pull.py0000664000175000017500000000044412553425527017556 0ustar jensjjensj00000000000000import numpy as np from ase import Atoms from ase.calculators.emt import EMT from ase.io import Trajectory Cu = Atoms('Cu', pbc=(1, 0, 0), calculator=EMT()) traj = Trajectory('Cu.traj', 'w') for a in np.linspace(2.0, 4.0, 20): Cu.set_cell([a, 1, 1], scale_atoms=True) traj.write(Cu) python-ase-3.9.1.4567/ase/test/abinit/0000775000175000017500000000000012553427753017477 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/abinit/__init__.py0000664000175000017500000000000012553425527021573 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/abinit/abinit_cmdline.py0000664000175000017500000000022712553425527023010 0ustar jensjjensj00000000000000from ase.test import cli cli(""" ase-build -x fcc -a 4.04 Al | ase-run abinit -p xc=PBE,kpts=3.0,ecut=340,toldfe=1e-5,chksymbreak=0""", 'abinit') python-ase-3.9.1.4567/ase/test/abinit/abinit_Si.py0000664000175000017500000000135012553425527021746 0ustar jensjjensj00000000000000from ase import Atoms from ase.units import Ry from ase.calculators.abinit import Abinit a0 = 5.43 bulk = Atoms('Si2', [(0, 0, 0), (0.25, 0.25, 0.25)], pbc=True) b = a0 / 2 bulk.set_cell([(0, b, b), (b, 0, b), (b, b, 0)], scale_atoms=True) calc = Abinit(label='Si', nbands=8, # one can specify any abinit keywords ecut=10 * Ry, # warning - used to speedup the test kpts=[4, 4, 4], # warning - used to speedup the test chksymbreak=0, ) # one can specify abinit keywords also using set calc.set(toldfe=1.0e-2) # warning - used to speedup the test bulk.set_calculator(calc) e = bulk.get_potential_energy() python-ase-3.9.1.4567/ase/test/verlet.py0000664000175000017500000000146512553425527020107 0ustar jensjjensj00000000000000import numpy as np from ase import Atoms from ase.units import fs from ase.calculators.test import TestPotential from ase.md import VelocityVerlet from ase.io import Trajectory, read from ase.optimize import QuasiNewton np.seterr(all='raise') a = Atoms('4X', masses=[1, 2, 3, 4], positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (0.1, 0.2, 0.7)], calculator=TestPotential()) print(a.get_forces()) md = VelocityVerlet(a, dt=0.5 * fs, logfile='-', loginterval=500) traj = Trajectory('4N.traj', 'w', a) md.attach(traj.write, 100) e0 = a.get_total_energy() md.run(steps=10000) del traj assert abs(read('4N.traj').get_total_energy() - e0) < 0.0001 qn = QuasiNewton(a) qn.run(0.001) assert abs(a.get_potential_energy() - 1.0) < 0.000002 python-ase-3.9.1.4567/ase/test/scaled_positions.py0000664000175000017500000000014512553425527022142 0ustar jensjjensj00000000000000from ase import Atoms assert Atoms('X', [(-1e-35, 0, 0)], pbc=True).get_scaled_positions()[0, 0] < 1 python-ase-3.9.1.4567/ase/test/surface.py0000664000175000017500000000143612553425527020234 0ustar jensjjensj00000000000000import numpy as np from ase import Atoms, Atom from ase.lattice.surface import fcc111, fcc211, add_adsorbate atoms = fcc211('Au', (3, 5, 8), vacuum=10.) assert len(atoms) == 120 atoms = atoms.repeat((2, 1, 1)) assert np.allclose(atoms.get_distance(0, 130), 2.88499566724) atoms = fcc111('Ni', (2, 2, 4), orthogonal=True) add_adsorbate(atoms, 'H', 1, 'bridge') add_adsorbate(atoms, Atom('O'), 1, 'fcc') add_adsorbate(atoms, Atoms('F'), 1, 'hcp') # The next test ensures that a simple string of multiple atoms cannot be used, # which should fail with a KeyError that reports the name of the molecule due # to the string failing to work with Atom(). failed = False try: add_adsorbate(atoms, 'CN', 1, 'ontop') except KeyError as e: failed = True assert e.args[0] == 'CN' assert failed python-ase-3.9.1.4567/ase/test/strain_emt.py0000664000175000017500000000072212553425527020746 0ustar jensjjensj00000000000000"""This test checks that the StrainFilter works using the default built-in EMT calculator.""" import numpy as np from ase.constraints import StrainFilter from ase.optimize.mdmin import MDMin from ase.calculators.emt import EMT from ase.lattice import bulk cu = bulk('Cu', 'fcc', a=3.6) class EMTPlus(EMT): def get_stress(self, atoms): return np.zeros(6) cu.set_calculator(EMTPlus()) f = StrainFilter(cu) opt = MDMin(f, dt=0.01) opt.run(0.1, steps=2) python-ase-3.9.1.4567/ase/test/things.py0000664000175000017500000000107112553425527020073 0ustar jensjjensj00000000000000from ase.dft.kpoints import monkhorst_pack assert [0, 0, 0] in monkhorst_pack((1, 3, 5)).tolist() assert [0, 0, 0] not in monkhorst_pack((1, 3, 6)).tolist() assert len(monkhorst_pack((3, 4, 6))) == 3 * 4 * 6 from ase.units import Hartree, Bohr, kJ, mol, kcal, kB, fs print(Hartree, Bohr, kJ/mol, kcal/mol, kB*300, fs, 1/fs) from ase.lattice import bulk hcp = bulk('X', 'hcp', a=1) * (2, 2, 1) assert abs(hcp.get_distance(0, 3, mic=True) - 1) < 1e-12 assert abs(hcp.get_distance(0, 4, mic=True) - 1) < 1e-12 assert abs(hcp.get_distance(2, 5, mic=True) - 1) < 1e-12 python-ase-3.9.1.4567/ase/test/properties.py0000664000175000017500000000040112553425527020767 0ustar jensjjensj00000000000000from ase import Atoms a = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1.1)]) a.pbc[0] = 1 assert a.pbc.any() assert not a.pbc.all() a.pbc = 1 assert a.pbc.all() a.cell = (1, 2, 3) a.cell *= 2 a.cell[0, 0] = 3 assert not (a.cell.diagonal() - (3, 4, 6)).any() python-ase-3.9.1.4567/ase/test/fleur/0000775000175000017500000000000012553427753017346 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/fleur/__init__.py0000664000175000017500000000000012553425527021442 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/fleur/fleur_cmdline.py0000664000175000017500000000017112553425527022524 0ustar jensjjensj00000000000000from ase.test import cli, require require('fleur') cli('ase-build -x fcc -a 4.04 Al | ase-run fleur -p kpts=3.0,xc=PBE') python-ase-3.9.1.4567/ase/test/com.py0000664000175000017500000000072212553425527017357 0ustar jensjjensj00000000000000"""Test that atoms.get_center_of_mass(scaled=True) works""" import numpy as np from ase import Atoms d = 1.142 a = Atoms('CO', positions=[(2, 0, 0), (2, -d, 0)], pbc=True) a.set_cell(np.array(((4, -4, 0), (0, 5.657, 0), (0, 0, 10)))) def array_almost_equal(a1, a2, tol=np.finfo(type(1.0)).eps): return (np.abs(a1 - a2) < tol).all() scaledref = np.array((0.5, 0.23823499, 0.)) assert array_almost_equal(a.get_center_of_mass(scaled=True), scaledref, tol=1e-8) python-ase-3.9.1.4567/ase/test/fcc111_root.py0000664000175000017500000000105612553425527020623 0ustar jensjjensj00000000000000from ase.lattice.surface import fcc111_root def check(root): try: slab = fcc111_root("Pt", root, (1,1,1), search_zone = (10,10)) return True except: return False # First test ability to generate existing confirguations in a range valid = [] for root in range(10): if check(root): valid.append(root) assert valid == [1, 3, 4, 7, 9] # Now check if it fails when supplied bad arguments failed = False try: slab = fcc111_root("H", root, (1,1,1), search_zone = (10,10)) except: failed = True assert failed python-ase-3.9.1.4567/ase/test/noncollinear.py0000664000175000017500000000113012553425527021256 0ustar jensjjensj00000000000000from ase import Atom, Atoms a = Atoms('H2') a[0].magmom = 1 m = a.get_initial_magnetic_moments() assert m.shape == (2,) and (m == [1, 0]).all() a[1].magmom = -1 m = a.get_initial_magnetic_moments() assert m.shape == (2,) and (m == [1, -1]).all() assert a[1].magmom == -1 a.set_initial_magnetic_moments() a[0].magmom = (0, 1, 0) m = a.get_initial_magnetic_moments() assert m.shape == (2, 3) and (m == [(0, 1, 0), (0, 0, 0)]).all() a[1].magmom = (1, 0, 0) m = a.get_initial_magnetic_moments() assert m.shape == (2, 3) and (m == [(0, 1, 0), (1, 0, 0)]).all() assert (a[1].magmom == (1, 0, 0)).all() python-ase-3.9.1.4567/ase/test/stm.py0000664000175000017500000000076412553425527017412 0ustar jensjjensj00000000000000from ase.calculators.test import make_test_dft_calculation from ase.dft.stm import STM atoms = make_test_dft_calculation() stm = STM(atoms, [0, 1, 2]) c = stm.get_averaged_current(-1.0, 4.5) x, y, h = stm.scan(-1.0, c) stm.write('stm.pckl') x, y, h2 = STM('stm.pckl').scan(-1, c) assert abs(h - h2).max() == 0 stm = STM(atoms, use_density=True) c = stm.get_averaged_current(42, 4.5) x, y = stm.linescan(42, c, [0, 0], [2, 2]) assert abs(x[-1] - 2 * 2**0.5) < 1e-13 assert abs(y[-1] - y[0]) < 1e-13 python-ase-3.9.1.4567/ase/test/set_get_angle.py0000664000175000017500000000062112553425527021377 0ustar jensjjensj00000000000000"Test that set_angle() and get_angle() in Atoms are consistent" from ase import Atoms atoms = Atoms('HHCCHH', [[-1, 1, 0], [-1, -1, 0], [0, 0, 0], [1, 0, 0], [2, 1, 0], [2, -1, 0]]) list = [2, 3, 4] theta = 0.1 old_angle = atoms.get_angle(list) atoms.set_angle(list, old_angle + theta) new_angle = atoms.get_angle(list) assert abs(new_angle - (old_angle + theta)) < 1.0e-9 python-ase-3.9.1.4567/ase/test/vib.py0000664000175000017500000000123512553425527017361 0ustar jensjjensj00000000000000from ase import Atoms from ase.calculators.emt import EMT from ase.optimize import QuasiNewton from ase.vibrations import Vibrations from ase.thermochemistry import IdealGasThermo n2 = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT()) QuasiNewton(n2).run(fmax=0.01) vib = Vibrations(n2) vib.run() print(vib.get_frequencies()) vib.summary() print(vib.get_mode(-1)) vib.write_mode(n=None, nimages=20) vib_energies = vib.get_energies() thermo = IdealGasThermo(vib_energies=vib_energies, geometry='linear', atoms=n2, symmetrynumber=2, spin=0) thermo.get_gibbs_energy(temperature=298.15, pressure=2 * 101325.) python-ase-3.9.1.4567/ase/test/emt.py0000664000175000017500000000306212553425527017366 0ustar jensjjensj00000000000000import numpy as np from ase.calculators.emt import EMT from ase import Atoms a = 3.60 b = a / 2 cu = Atoms('Cu', positions=[(0, 0, 0)], cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=1, calculator=EMT()) e0 = cu.get_potential_energy() print(e0) cu.set_cell(cu.get_cell() * 1.001, scale_atoms=True) e1 = cu.get_potential_energy() V = a**3 / 4 B = 2 * (e1 - e0) / 0.003**2 / V * 160.2 print(B) for i in range(4): x = 0.001 * i A = np.array([(x, b, b+x), (b, 0, b), (b, b, 0)]) cu.set_cell(A, scale_atoms=True) e = cu.get_potential_energy() - e0 if i == 0: print(i, e) else: print(i, e, e / x**2) A = np.array([(0, b, b), (b, 0, b), (6*b, 6*b, 0)]) R = np.zeros((2, 3)) for i in range(1, 2): R[i] = i * A[2] / 6 print((Atoms('Cu2', positions=R, pbc=1, cell=A, calculator=EMT()).get_potential_energy() - 2 * e0) / 2) A = np.array([(0, b, b), (b, 0, b), (10*b, 10*b, 0)]) R = np.zeros((3, 3)) for i in range(1, 3): R[i] = i * A[2] / 10 print((Atoms('Cu3', positions=R, pbc=1, cell=A, calculator=EMT()).get_potential_energy() - 3 * e0) / 2) A = np.array([(0, b, b), (b, 0, b), (b, b, 0)]) R = np.zeros((3, 3)) for i in range(1, 3): R[i] = i * A[2] print((Atoms('Cu3', positions=R, pbc=(1, 1, 0), cell=A, calculator=EMT()).get_potential_energy() - 3 * e0) / 2) python-ase-3.9.1.4567/ase/test/singlepointcalc.py0000664000175000017500000000253412553425527021762 0ustar jensjjensj00000000000000"""This test makes sure that the forces returned from a SinglePointCalculator are immutable. Previously, successive calls to atoms.get_forces(apply_constraint=x), with x alternating between True and False, would get locked into the constrained variation.""" from ase.lattice.surface import fcc111 from ase.calculators.emt import EMT from ase.io import read from ase.constraints import FixAtoms def check_forces(): """Makes sure the unconstrained forces stay that way.""" forces = atoms.get_forces(apply_constraint=False) funconstrained = float(forces[0, 0]) forces = atoms.get_forces(apply_constraint=True) forces = atoms.get_forces(apply_constraint=False) funconstrained2 = float(forces[0, 0]) assert funconstrained2 == funconstrained atoms = fcc111('Cu', (2, 2, 1), vacuum=10.) atoms[0].x += 0.2 atoms.set_constraint(FixAtoms(indices=[atom.index for atom in atoms])) # First run the tes with EMT and save a force component. atoms.set_calculator(EMT()) check_forces() f = float(atoms.get_forces(apply_constraint=False)[0, 0]) # Save and reload with a SinglePointCalculator. atoms.write('singlepointtest.traj') atoms = read('singlepointtest.traj') check_forces() # Manually change a value. forces = atoms.get_forces(apply_constraint=False) forces[0, 0] = 42. forces = atoms.get_forces(apply_constraint=False) assert forces[0, 0] == f python-ase-3.9.1.4567/ase/test/Ag-Cu100.py0000664000175000017500000000317212553425527017720 0ustar jensjjensj00000000000000from math import sqrt from ase import Atom, Atoms from ase.neb import NEB from ase.constraints import FixAtoms from ase.vibrations import Vibrations from ase.visualize import view from ase.calculators.emt import EMT from ase.optimize import QuasiNewton, BFGS # Distance between Cu atoms on a (100) surface: d = 3.6 / sqrt(2) initial = Atoms('Cu', positions=[(0, 0, 0)], cell=(d, d, 1.0), pbc=(True, True, False)) initial *= (2, 2, 1) # 2x2 (100) surface-cell # Approximate height of Ag atom on Cu(100) surfece: h0 = 2.0 initial += Atom('Ag', (d / 2, d / 2, h0)) if 0: view(initial) # Make band: images = [initial.copy() for i in range(6)] neb = NEB(images, climb=True) # Set constraints and calculator: constraint = FixAtoms(range(len(initial) - 1)) for image in images: image.set_calculator(EMT()) image.set_constraint(constraint) # Displace last image: images[-1].positions[-1] += (d, 0, 0) #images[-1].positions[-1] += (d, d, 0) # Relax height of Ag atom for initial and final states: dyn1 = QuasiNewton(images[0]) dyn1.run(fmax=0.01) dyn2 = QuasiNewton(images[-1]) dyn2.run(fmax=0.01) # Interpolate positions between initial and final states: neb.interpolate() for image in images: print(image.positions[-1], image.get_potential_energy()) #dyn = MDMin(neb, dt=0.4) #dyn = FIRE(neb, dt=0.4) dyn = BFGS(neb, trajectory='mep.traj') dyn.run(fmax=0.05) for image in images: print(image.positions[-1], image.get_potential_energy()) a = images[0] vib = Vibrations(a, [4]) vib.run() print(vib.get_frequencies()) vib.summary() print(vib.get_mode(-1)) vib.write_mode(-1, nimages=20) python-ase-3.9.1.4567/ase/test/example.py0000664000175000017500000000125212553425527020233 0ustar jensjjensj00000000000000from ase.all import * from ase.calculators.morse import MorsePotential atoms = Atoms('H7', positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0), (0, 2, 0), (1, 2, 0), (0.5, 0.5, 1)], constraint=[FixAtoms(range(6))], calculator=MorsePotential()) traj = Trajectory('H.traj', 'w', atoms) dyn = QuasiNewton(atoms, maxstep=0.2) dyn.attach(traj.write) dyn.run(fmax=0.01, steps=100) print(atoms) del atoms[-1] print(atoms) del atoms[5] print(atoms) assert len(atoms.constraints[0].index) == 5 python-ase-3.9.1.4567/ase/test/vasp/0000775000175000017500000000000012553427753017202 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/vasp/__init__.py0000664000175000017500000000041712553425527021312 0ustar jensjjensj00000000000000def installed(): import os from ase.test import NotAvailable vcmd = os.getenv('VASP_COMMAND') vscr = os.getenv('VASP_SCRIPT') if vcmd == None and vscr == None: raise NotAvailable('Neither VASP_COMMAND nor VASP_SCRIPT defined') return True python-ase-3.9.1.4567/ase/test/vasp/vasp_co.py0000664000175000017500000000324212553425527021204 0ustar jensjjensj00000000000000""" Run some VASP tests to ensure that the VASP calculator works. This is conditional on the existence of the VASP_COMMAND or VASP_SCRIPT environment variables """ from ase.test.vasp import installed assert installed() from ase import Atoms from ase.io import write from ase.calculators.vasp import Vasp import numpy as np def array_almost_equal(a1, a2, tol=np.finfo(type(1.0)).eps): """Replacement for old numpy.testing.utils.array_almost_equal.""" return (np.abs(a1 - a2) < tol).all() d = 1.14 co = Atoms('CO', positions=[(0, 0, 0), (0, 0, d)], pbc=True) co.center(vacuum=5.) calc = Vasp( xc = 'PBE', prec = 'Low', algo = 'Fast', ismear= 0, sigma = 1., istart = 0, lwave = False, lcharg = False) co.set_calculator(calc) en = co.get_potential_energy() write('vasp_co.traj', co) assert abs(en + 14.918933) < 5e-3 # Secondly, check that restart from the previously created VASP output works calc2 = Vasp(restart=True) co2 = calc2.get_atoms() # Need tolerance of 1e-14 because VASP itself changes coordinates # slightly between reading POSCAR and writing CONTCAR even if no ionic # steps are made. assert array_almost_equal(co.positions, co2.positions, 1e-14) assert en - co2.get_potential_energy() == 0. assert array_almost_equal(calc.get_stress(co), calc2.get_stress(co2)) assert array_almost_equal(calc.get_forces(co), calc2.get_forces(co2)) assert array_almost_equal(calc.get_eigenvalues(), calc2.get_eigenvalues()) assert calc.get_number_of_bands() == calc2.get_number_of_bands() assert calc.get_xc_functional() == calc2.get_xc_functional() # Cleanup calc.clean() python-ase-3.9.1.4567/ase/test/vasp/vasp_Al_volrelax.py0000664000175000017500000000425012553425527023053 0ustar jensjjensj00000000000000""" Run VASP tests to ensure that relaxation with the VASP calculator works. This is conditional on the existence of the VASP_COMMAND or VASP_SCRIPT environment variables. """ from ase.test.vasp import installed assert installed() import numpy as np from ase import io # QuasiNewton nowadays is an alias for BFGSLineSearch, which is # broken. Use BFGS instead. from ase.optimize import BFGS as QuasiNewton from ase.lattice import bulk from ase.calculators.vasp import Vasp # -- Perform Volume relaxation within Vasp def vasp_vol_relax(): Al = bulk('Al', 'fcc', a=4.5, cubic=True) calc = Vasp(xc='LDA', isif=7, nsw=5, ibrion=1, ediffg=-1e-3, lwave=False, lcharg=False) calc.calculate(Al) # Explicitly parse atomic position output file from Vasp CONTCAR_Al = io.read('CONTCAR', format='vasp') print('Stress after relaxation:\n', calc.read_stress()) print('Al cell post relaxation from calc:\n', calc.get_atoms().get_cell()) print('Al cell post relaxation from atoms:\n', Al.get_cell()) print('Al cell post relaxation from CONTCAR:\n', CONTCAR_Al.get_cell()) # All the cells should be the same. assert (calc.get_atoms().get_cell() == CONTCAR_Al.get_cell()).all() assert (Al.get_cell() == CONTCAR_Al.get_cell()).all() return Al # -- Perform Volume relaxation using ASE with Vasp as force/stress calculator def ase_vol_relax(): Al = bulk('Al', 'fcc', a=4.5, cubic=True) calc = Vasp(xc='LDA') Al.set_calculator(calc) from ase.constraints import StrainFilter sf = StrainFilter(Al) qn = QuasiNewton(sf, logfile='relaxation.log') qn.run(fmax=0.1, steps=5) print('Stress:\n', calc.read_stress()) print('Al post ASE volume relaxation\n', calc.get_atoms().get_cell()) return Al # Test function for comparing two cells def cells_almost_equal(cellA, cellB, tol=0.01): return (np.abs(cellA - cellB) < tol).all() # Correct LDA relaxed cell a_rel = 4.18 LDA_cell = np.diag([a_rel, a_rel, a_rel]) Al_vasp = vasp_vol_relax() Al_ase = ase_vol_relax() assert cells_almost_equal(LDA_cell, Al_vasp.get_cell()) assert cells_almost_equal(LDA_cell, Al_ase.get_cell()) # Cleanup Al_ase.get_calculator().clean() python-ase-3.9.1.4567/ase/test/exciting/0000775000175000017500000000000012553427753020043 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/exciting/__init__.py0000664000175000017500000000000012553425527022137 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/exciting/exciting.py0000664000175000017500000000107012553425527022222 0ustar jensjjensj00000000000000import os from ase import Atoms from ase.io import read, write from ase.calculators.exciting import Exciting from ase.units import Bohr, Hartree a = Atoms('N3O', [(0, 0, 0), (1, 0, 0), (0, 0, 1), (0.5, 0.5, 0.5)], pbc=True) write('geo.exi', a) b = read('geo.exi') print(a) print(a.get_positions()) print(b) print(b.get_positions()) calculator = Exciting(dir='excitingtestfiles', kpts=(4, 4, 3), maxscl=3, #bin='/fshome/chm/git/exciting/bin/excitingser' ) python-ase-3.9.1.4567/ase/test/gaussian/0000775000175000017500000000000012553427753020043 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/gaussian/__init__.py0000664000175000017500000000000012553425527022137 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/gaussian/gaussian_cmdline.py0000664000175000017500000000133412553425527023720 0ustar jensjjensj00000000000000from ase.test import cli, require from ase.db import connect from ase.io.jsonio import read_json from ase.calculators.gaussian import Gaussian require('gaussian') cli("""\ ase-build O | ase-run gaussian -d gaussian_cmdline.json && ase-build O2 | ase-run gaussian -d gaussian_cmdline.json""") c = connect('gaussian_cmdline.json') dct = read_json('gaussian_cmdline.json') for name in ['O2', 'O']: d = c.get([('name', '=', name)]) id = d.id e1 = d.energy e2 = c.get_atoms(id).get_potential_energy() e3 = Gaussian.read_atoms(name).get_potential_energy() e4 = dct[id]['energy'] assert e1 == e2 == e3 == e4 print(e1) ae = 2 * c.get('name=O').energy - c.get('name=O2').energy assert abs(ae - 1.060) < 1e-3 python-ase-3.9.1.4567/ase/test/gaussian/h2of.py0000664000175000017500000000433212553425527021252 0ustar jensjjensj00000000000000from ase import Atoms from ase.calculators.gaussian import Gaussian basis = """H 0 S 3 1.00 13.0107010 0.19682158E-01 1.9622572 0.13796524 0.44453796 0.47831935 S 1 1.00 0.12194962 1.0000000 P 1 1.00 0.8000000 1.0000000 **** O 0 S 5 1.00 2266.1767785 -0.53431809926E-02 340.87010191 -0.39890039230E-01 77.363135167 -0.17853911985 21.479644940 -0.46427684959 6.6589433124 -0.44309745172 S 1 1.00 0.80975975668 1.0000000 S 1 1.00 0.25530772234 1.0000000 P 3 1.00 17.721504317 0.43394573193E-01 3.8635505440 0.23094120765 1.0480920883 0.51375311064 P 1 1.00 0.27641544411 1.0000000 D 1 1.00 1.2000000 1.0000000 **** F 0 S 5 1.00 2894.8325990 -0.53408255515E-02 435.41939120 -0.39904258866E-01 98.843328866 -0.17912768038 27.485198001 -0.46758090825 8.5405498171 -0.44653131020 S 1 1.00 1.0654578038 1.0000000 S 1 1.00 0.33247346748 1.0000000 P 3 1.00 22.696633924 -0.45212874436E-01 4.9872339257 -0.23754317067 1.3491613954 -0.51287353587 P 1 1.00 0.34829881977 1.0000000 D 1 1.00 1.4000000 1.0000000 **** """ with open('def2-svp.gbs', 'w') as bfile: bfile.write(basis) atoms = Atoms('OH2F', positions=[(-1.853788, -0.071113, 0.000000), (-1.892204, 0.888768, 0.000000), (-0.888854, -0.232973, 0.000000), (1.765870, 0.148285, 0.000000)]) label = 'h2of-anion' calc = Gaussian(charge=-1.0, basis='gen', method='B3LYP', basisfile='@def2-svp.gbs/N', label=label, ioplist=['6/80=1', '6/35=4000000'], density='current', addsec=['%s.wfx' % label] ) atoms.set_calculator(calc) atoms.get_potential_energy() python-ase-3.9.1.4567/ase/test/gaussian/water.py0000664000175000017500000000152512553425527021537 0ustar jensjjensj00000000000000from ase.calculators.gaussian import Gaussian from ase.atoms import Atoms from ase.optimize.lbfgs import LBFGS # First test to make sure Gaussian works calc = Gaussian(method='pbepbe', basis='sto-3g', force='force', nproc=1, chk='water.chk', label='water') calc.clean() water = Atoms('OHH', positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0)], calculator=calc) opt = LBFGS(water) opt.run(fmax=0.05) forces = water.get_forces() energy = water.get_potential_energy() positions = water.get_positions() # Then test the IO routines from ase.io import read water2 = read('water.log') forces2 = water2.get_forces() energy2 = water2.get_potential_energy() positions2 = water2.get_positions() assert abs(energy - energy2) < 1e-7 assert abs(forces - forces2).max() < 1e-9 assert abs(positions - positions2).max() < 1e-6 python-ase-3.9.1.4567/ase/test/crystal.py0000664000175000017500000000521712553425527020266 0ustar jensjjensj00000000000000import numpy as np from ase.lattice.spacegroup import crystal from ase.io import write # A diamond unit cell diamond = crystal('C', [(0, 0, 0)], spacegroup=227, cellpar=[3.57, 3.57, 3.57, 90, 90, 90]) # Check that we can write to trajectory: write('c.traj', diamond) assert len(diamond) == 8 correct_pos = np.array([[ 0. , 0. , 0. ], [ 0. , 0.5 , 0.5 ], [ 0.5 , 0.5 , 0. ], [ 0.5 , 0. , 0.5 ], [ 0.75, 0.25, 0.75], [ 0.25, 0.25, 0.25], [ 0.25, 0.75, 0.75], [ 0.75, 0.75, 0.25]]) assert np.allclose(diamond.get_scaled_positions(), correct_pos) # 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]) assert len(skutterudite) == 32 correct_pos = np.array([[ 0.25 , 0.25 , 0.25 ], [ 0.75 , 0.75 , 0.25 ], [ 0.75 , 0.25 , 0.75 ], [ 0.25 , 0.75 , 0.75 ], [ 0.75 , 0.75 , 0.75 ], [ 0.25 , 0.25 , 0.75 ], [ 0.25 , 0.75 , 0.25 ], [ 0.75 , 0.25 , 0.25 ], [ 0. , 0.335, 0.158], [ 0. , 0.665, 0.158], [ 0. , 0.335, 0.842], [ 0. , 0.665, 0.842], [ 0.158, 0. , 0.335], [ 0.158, 0. , 0.665], [ 0.842, 0. , 0.335], [ 0.842, 0. , 0.665], [ 0.335, 0.158, 0. ], [ 0.665, 0.158, 0. ], [ 0.335, 0.842, 0. ], [ 0.665, 0.842, 0. ], [ 0.5 , 0.835, 0.658], [ 0.5 , 0.165, 0.658], [ 0.5 , 0.835, 0.342], [ 0.5 , 0.165, 0.342], [ 0.658, 0.5 , 0.835], [ 0.658, 0.5 , 0.165], [ 0.342, 0.5 , 0.835], [ 0.342, 0.5 , 0.165], [ 0.835, 0.658, 0.5 ], [ 0.165, 0.658, 0.5 ], [ 0.835, 0.342, 0.5 ], [ 0.165, 0.342, 0.5 ]]) assert np.allclose(skutterudite.get_scaled_positions(), correct_pos) python-ase-3.9.1.4567/ase/test/ga/0000775000175000017500000000000012553427753016620 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/ga/__init__.py0000664000175000017500000000000012553425527020714 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/ga/mutations.py0000664000175000017500000000427312553425527021220 0ustar jensjjensj00000000000000from ase.ga.startgenerator import StartGenerator from ase.ga.utilities import closest_distances_generator from ase.ga.standardmutations import RattleMutation, PermutationMutation import numpy as np from ase.lattice.surface import fcc111 from ase.constraints import FixAtoms # first create two random starting candidates slab = fcc111('Au', size=(4, 4, 2), vacuum=10.0, orthogonal=True) slab.set_constraint(FixAtoms(mask=slab.positions[:, 2] <= 10.)) pos = slab.get_positions() cell = slab.get_cell() p0 = np.array([0., 0., max(pos[:, 2]) + 2.]) v1 = cell[0, :] * 0.8 v2 = cell[1, :] * 0.8 v3 = cell[2, :] v3[2] = 3. cd = closest_distances_generator(atom_numbers=[47, 79], ratio_of_covalent_radii=0.7) atom_numbers = 2 * [47] + 2 * [79] n_top = len(atom_numbers) sg = StartGenerator(slab=slab, atom_numbers=atom_numbers, closest_allowed_distances=cd, box_to_place_in=[p0, [v1, v2, v3]]) c1 = sg.get_new_candidate() c1.info['confid'] = 1 # first verify that the rattle mutation works rmut = RattleMutation(cd, n_top, rattle_strength=0.8, rattle_prop=0.4) c2, desc = rmut.get_new_individual([c1]) assert np.all(c1.numbers == c2.numbers) top1 = c1[-n_top:] top2 = c2[-n_top:] slab2 = c2[0:(len(c1) - n_top)] assert len(slab) == len(slab2) assert np.all(slab.get_positions() == slab2.get_positions()) dp = np.sum((top2.get_positions() - top1.get_positions())**2, axis=1)**0.5 # check that all displacements are smaller than the rattle strength we # cannot check if 40 % of the structures have been rattled since it is # probabilistic and because the probability will be lower if two atoms # get too close for p in dp: assert p < 0.8 * 3**0.5 # now we check the permutation mutation mmut = PermutationMutation(n_top, probability=0.5) c3, desc = mmut.get_new_individual([c1]) assert np.all(c1.numbers == c3.numbers) top1 = c1[-n_top:] top2 = c3[-n_top:] slab2 = c3[0:(len(c1) - n_top)] assert len(slab) == len(slab2) assert np.all(slab.get_positions() == slab2.get_positions()) dp = np.sum((top2.get_positions() - top1.get_positions())**2, axis=1)**0.5 # verify that two positions have been changed assert len(dp[dp > 0]) == 2 python-ase-3.9.1.4567/ase/test/ga/database_logic.py0000664000175000017500000000443112553425527022112 0ustar jensjjensj00000000000000from ase.ga.data import PrepareDB from ase.ga.data import DataConnection from ase.ga.startgenerator import StartGenerator from ase.ga.utilities import closest_distances_generator import os import numpy as np from ase.lattice.surface import fcc111 from ase.constraints import FixAtoms db_file = 'gadb_logics_test.db' slab = fcc111('Au', size=(4, 4, 2), vacuum=10.0, orthogonal=True) slab.set_constraint(FixAtoms(mask=slab.positions[:, 2] <= 10.)) # define the volume in which the adsorbed cluster is optimized # the volume is defined by a corner position (p0) # and three spanning vectors (v1, v2, v3) pos = slab.get_positions() cell = slab.get_cell() p0 = np.array([0., 0., max(pos[:, 2]) + 2.]) v1 = cell[0, :] * 0.8 v2 = cell[1, :] * 0.8 v3 = cell[2, :] v3[2] = 3. # define the closest distance between two atoms of a given species cd = closest_distances_generator(atom_numbers=[47, 79], ratio_of_covalent_radii=0.7) # Define the composition of the atoms to optimize atom_numbers = 2 * [47] + 2 * [79] # create the starting population sg = StartGenerator(slab=slab, atom_numbers=atom_numbers, closest_allowed_distances=cd, box_to_place_in=[p0, [v1, v2, v3]]) # generate the starting population starting_population = [sg.get_new_candidate() for i in range(20)] d = PrepareDB(db_file_name=db_file, simulation_cell=slab, stoichiometry=atom_numbers) for a in starting_population: d.add_unrelaxed_candidate(a) # and now for the actual test dc = DataConnection(db_file) slab_get = dc.get_slab() an_get = dc.get_atom_numbers_to_optimize() assert dc.get_number_of_unrelaxed_candidates() == 20 a1 = dc.get_an_unrelaxed_candidate() dc.mark_as_queued(a1) assert dc.get_number_of_unrelaxed_candidates() == 19 assert len(dc.get_all_candidates_in_queue()) == 1 a1.set_raw_score(0.0) dc.add_relaxed_step(a1) assert dc.get_number_of_unrelaxed_candidates() == 19 assert len(dc.get_all_candidates_in_queue()) == 0 assert len(dc.get_all_relaxed_candidates()) == 1 a2 = dc.get_an_unrelaxed_candidate() dc.mark_as_queued(a2) confid = a2.info['confid'] assert dc.get_all_candidates_in_queue()[0] == confid dc.remove_from_queue(confid) assert len(dc.get_all_candidates_in_queue()) == 0 os.remove(db_file) python-ase-3.9.1.4567/ase/test/ga/basic_example_create_database.py0000664000175000017500000000352612553425527025140 0ustar jensjjensj00000000000000from ase.ga.data import PrepareDB from ase.ga.startgenerator import StartGenerator from ase.ga.utilities import closest_distances_generator from ase.ga.utilities import get_all_atom_types from ase.constraints import FixAtoms import numpy as np from ase.lattice.surface import fcc111 db_file = 'gadb.db' # create the surface slab = fcc111('Au', size=(4, 4, 1), vacuum=10.0, orthogonal=True) slab.set_constraint(FixAtoms(mask=len(slab) * [True])) # define the volume in which the adsorbed cluster is optimized # the volume is defined by a corner position (p0) # and three spanning vectors (v1, v2, v3) pos = slab.get_positions() cell = slab.get_cell() p0 = np.array([0., 0., max(pos[:, 2]) + 2.]) v1 = cell[0, :] * 0.8 v2 = cell[1, :] * 0.8 v3 = cell[2, :] v3[2] = 3. # Define the composition of the atoms to optimize atom_numbers = 2 * [47] + 2 * [79] # define the closest distance two atoms of a given species can be to each other unique_atom_types = get_all_atom_types(slab, atom_numbers) cd = closest_distances_generator(atom_numbers=unique_atom_types, ratio_of_covalent_radii=0.7) # create the starting population sg = StartGenerator(slab=slab, atom_numbers=atom_numbers, closest_allowed_distances=cd, box_to_place_in=[p0, [v1, v2, v3]]) # generate the starting population population_size = 5 starting_population = [sg.get_new_candidate() for i in range(population_size)] # from ase.visualize import view # uncomment these lines # view(starting_population) # to see the starting population # create the database to store information in d = PrepareDB(db_file_name=db_file, simulation_cell=slab, stoichiometry=atom_numbers,) # population_size=population_size) for a in starting_population: d.add_unrelaxed_candidate(a) python-ase-3.9.1.4567/ase/test/ga/particle_comparators.py0000664000175000017500000000145612553425527023412 0ustar jensjjensj00000000000000from ase.cluster import Icosahedron from ase.ga.particle_comparator import NNMatComparator from ase.ga.utilities import get_nnmat from ase.ga.particle_mutations import RandomPermutation ico1 = Icosahedron('Cu', 4) ico1.info['confid'] = 1 ico2 = Icosahedron('Ni', 4) ico1.numbers[:55] = [28] * 55 ico2.numbers[:92] = [29] * 92 ico1.info['data'] = {} ico1.info['data']['nnmat'] = get_nnmat(ico1) ico2.info['data'] = {} ico2.info['data']['nnmat'] = get_nnmat(ico2) comp = NNMatComparator() assert not comp.looks_like(ico1, ico2) op = RandomPermutation() a3, desc = op.get_new_individual([ico1]) assert a3.get_chemical_formula() == ico1.get_chemical_formula() hard_comp = NNMatComparator(d=100) assert hard_comp.looks_like(ico1, a3) soft_comp = NNMatComparator(d=.0001) assert not soft_comp.looks_like(ico1, a3) python-ase-3.9.1.4567/ase/test/ga/cutandsplicepairing.py0000664000175000017500000000365312553425527023226 0ustar jensjjensj00000000000000from ase.ga.startgenerator import StartGenerator from ase.ga.utilities import closest_distances_generator, atoms_too_close from ase.ga.cutandsplicepairing import CutAndSplicePairing import numpy as np from ase.lattice.surface import fcc111 from ase.constraints import FixAtoms # first create two random starting candidates slab = fcc111('Au', size=(4, 4, 2), vacuum=10.0, orthogonal=True) slab.set_constraint(FixAtoms(mask=slab.positions[:, 2] <= 10.)) pos = slab.get_positions() cell = slab.get_cell() p0 = np.array([0., 0., max(pos[:, 2]) + 2.]) v1 = cell[0, :] * 0.8 v2 = cell[1, :] * 0.8 v3 = cell[2, :] v3[2] = 3. cd = closest_distances_generator(atom_numbers=[47, 79], ratio_of_covalent_radii=0.7) atom_numbers = 2 * [47] + 2 * [79] sg = StartGenerator(slab=slab, atom_numbers=atom_numbers, closest_allowed_distances=cd, box_to_place_in=[p0, [v1, v2, v3]]) c1 = sg.get_new_candidate() c1.info['confid'] = 1 c2 = sg.get_new_candidate() c2.info['confid'] = 2 n_top = len(atom_numbers) pairing = CutAndSplicePairing(slab, n_top, cd) c3, desc = pairing.get_new_individual([c1, c2]) # verify that the stoichiometry is preserved assert np.all(c3.numbers == c1.numbers) top1 = c1[-n_top:] top2 = c2[-n_top:] top3 = c3[-n_top:] # verify that the positions in the new candidate come from c1 or c2 n1 = -1 * np.ones((n_top, )) n2 = -1 * np.ones((n_top, )) for i in range(n_top): for j in range(n_top): if np.all(top1.positions[j, :] == top3.positions[i, :]): n1[i] = j break elif np.all(top2.positions[j, :] == top3.positions[i, :]): n2[i] = j break assert (n1[i] > -1 and n2[i] == -1) or (n1[i] == -1 and n2[i] > -1) # verify that c3 includes atoms from both c1 and c2 assert len(n1[n1 > -1]) > 0 and len(n2[n2 > -1]) > 0 # verify no atoms too close assert not atoms_too_close(top3, cd) python-ase-3.9.1.4567/ase/test/ga/standardcomparator.py0000664000175000017500000000365212553425527023065 0ustar jensjjensj00000000000000from ase.ga.standard_comparators import InteratomicDistanceComparator from ase import Atoms from ase.calculators.singlepoint import SinglePointCalculator a1 = Atoms('AgAgAg', positions=[[0, 0, 0], [1.5, 0, 0], [1.5, 1.5, 0]]) a2 = Atoms('AgAgAg', positions=[[0, 0, 0], [1.4, 0, 0], [1.5, 1.5, 0]]) e1 = 1.0 e2 = 0.8 a1.set_calculator(SinglePointCalculator(e1, None, None, None, a1)) a2.set_calculator(SinglePointCalculator(e2, None, None, None, a2)) comp1 = InteratomicDistanceComparator(n_top=3, pair_cor_cum_diff=0.03, pair_cor_max=0.7, dE=0.3) assert comp1.looks_like(a1, a2) comp2 = InteratomicDistanceComparator(n_top=3, pair_cor_cum_diff=0.03, pair_cor_max=0.7, dE=0.15) assert not comp2.looks_like(a1, a2) comp3 = InteratomicDistanceComparator(n_top=3, pair_cor_cum_diff=0.02, pair_cor_max=0.7, dE=0.3) assert not comp3.looks_like(a1, a2) from ase.ga.standard_comparators import EnergyComparator hard_E_comp = EnergyComparator(dE=1.0) assert hard_E_comp.looks_like(a1, a2) soft_E_comp = EnergyComparator(dE=.01) assert not soft_E_comp.looks_like(a1, a2) from ase.ga.atoms_attach import enable_raw_score_methods from ase.ga.standard_comparators import RawScoreComparator enable_raw_score_methods(a1) a1.set_raw_score(.1) enable_raw_score_methods(a2) a2.set_raw_score(.27) rs_comp = RawScoreComparator(0.15) assert not rs_comp.looks_like(a1, a2) from ase.ga.standard_comparators import SequentialComparator comp1 = SequentialComparator([hard_E_comp, rs_comp], [0, 0]) assert not comp1.looks_like(a1, a2) comp2 = SequentialComparator([hard_E_comp, rs_comp], [0, 1]) assert comp2.looks_like(a1, a2) python-ase-3.9.1.4567/ase/test/ga/particle_operators.py0000664000175000017500000000332512553425527023073 0ustar jensjjensj00000000000000from ase.cluster import Icosahedron from ase.ga.particle_crossovers import CutSpliceCrossover from random import shuffle ico1 = Icosahedron('Cu', 3) ico1.info['confid'] = 1 ico2 = Icosahedron('Ni', 3) ico2.info['confid'] = 2 # TODO: Change this crossover to one for fixed particles # op = CutSpliceCrossover({(28, 29): 2.0, (28, 28): 2.0, (29, 29): 2.0}, # keep_composition=False) # a3, desc = op.get_new_individual([ico1, ico2]) # assert len(set(a3.get_chemical_symbols())) == 2 # assert len(a3) == 55 ico1.numbers[:20] = [28] * 20 shuffle(ico1.numbers) ico2.numbers[:35] = [29] * 35 shuffle(ico2.numbers) op = CutSpliceCrossover({(28, 29): 2.0, (28, 28): 2.0, (29, 29): 2.0}) a3, desc = op.get_new_individual([ico1, ico2]) assert a3.get_chemical_formula() == 'Cu35Ni20' from ase.ga.particle_mutations import COM2surfPermutation # from ase.ga.particle_mutations import RandomPermutation # from ase.ga.particle_mutations import Poor2richPermutation # from ase.ga.particle_mutations import Rich2poorPermutation op = COM2surfPermutation(min_ratio=0.05) a3, desc = op.get_new_individual([ico1]) a3.info['confid'] = 3 assert a3.get_chemical_formula() == 'Cu35Ni20' aconf = op.get_atomic_configuration(a3) core = aconf[1] shell = aconf[-1] for i, sym in zip(core, 6 * ['Ni'] + 6 * ['Cu']): a3[i].symbol = sym for i, sym in zip(shell, 6 * ['Ni'] + 6 * ['Cu']): a3[i].symbol = sym atomic_conf = op.get_atomic_configuration(a3, elements=['Cu'])[-2:] cu3 = len([item for sublist in atomic_conf for item in sublist]) a4, desc = op.get_new_individual([a3]) atomic_conf = op.get_atomic_configuration(a4, elements=['Cu'])[-2:] cu4 = len([item for sublist in atomic_conf for item in sublist]) assert abs(cu4 - cu3) == 1 python-ase-3.9.1.4567/ase/test/ga/create_database.py0000664000175000017500000000136512553425527022263 0ustar jensjjensj00000000000000from ase.ga.data import PrepareDB from ase.ga.data import DataConnection import os import numpy as np db_file = 'gadb.db' if os.path.isfile(db_file): os.remove(db_file) from ase.lattice.surface import fcc111 atom_numbers = np.array([78, 78, 79, 79]) slab = fcc111('Ag', size=(4, 4, 2), vacuum=10.) d = PrepareDB(db_file_name=db_file, simulation_cell=slab, stoichiometry=atom_numbers) assert os.path.isfile(db_file) dc = DataConnection(db_file) slab_get = dc.get_slab() an_get = dc.get_atom_numbers_to_optimize() assert len(slab) == len(slab_get) assert np.all(slab.numbers == slab_get.numbers) assert np.all(slab.get_positions() == slab_get.get_positions()) assert np.all(an_get == atom_numbers) os.remove(db_file) python-ase-3.9.1.4567/ase/test/ga/basic_example_main_run.py0000664000175000017500000000615412553425527023661 0ustar jensjjensj00000000000000from random import random from ase.io import write from ase.optimize import BFGS from ase.calculators.emt import EMT from ase.ga.data import DataConnection from ase.ga.population import Population from ase.ga.standard_comparators import InteratomicDistanceComparator from ase.ga.cutandsplicepairing import CutAndSplicePairing from ase.ga.utilities import closest_distances_generator from ase.ga.utilities import get_all_atom_types from ase.ga.offspring_creator import OperationSelector from ase.ga.standardmutations import MirrorMutation from ase.ga.standardmutations import RattleMutation from ase.ga.standardmutations import PermutationMutation # Change the following three parameters to suit your needs population_size = 5 mutation_probability = 0.3 n_to_test = 5 # Initialize the different components of the GA da = DataConnection('gadb.db') atom_numbers_to_optimize = da.get_atom_numbers_to_optimize() n_to_optimize = len(atom_numbers_to_optimize) slab = da.get_slab() all_atom_types = get_all_atom_types(slab, atom_numbers_to_optimize) blmin = closest_distances_generator(all_atom_types, ratio_of_covalent_radii=0.7) comp = InteratomicDistanceComparator(n_top=n_to_optimize, pair_cor_cum_diff=0.015, pair_cor_max=0.7, dE=0.02, mic=False) pairing = CutAndSplicePairing(slab, n_to_optimize, blmin) mutations = OperationSelector([1., 1., 1.], [MirrorMutation(blmin, n_to_optimize), RattleMutation(blmin, n_to_optimize), PermutationMutation(n_to_optimize)]) # Relax all unrelaxed structures (e.g. the starting population) while da.get_number_of_unrelaxed_candidates() > 0: a = da.get_an_unrelaxed_candidate() a.set_calculator(EMT()) print('Relaxing starting candidate {0}'.format(a.info['confid'])) dyn = BFGS(a, trajectory=None, logfile=None) dyn.run(fmax=0.05, steps=100) a.set_raw_score(-a.get_potential_energy()) da.add_relaxed_step(a) # create the population population = Population(data_connection=da, population_size=population_size, comparator=comp) # test n_to_test new candidates for i in range(n_to_test): print('Now starting configuration number {0}'.format(i)) a1, a2 = population.get_two_candidates() a3, desc = pairing.get_new_individual([a1, a2]) if a3 == None: continue da.add_unrelaxed_candidate(a3, description=desc) # Check if we want to do a mutation if random() < mutation_probability: a3_mut, desc = mutations.get_new_individual([a3]) if a3_mut != None: da.add_unrelaxed_step(a3_mut, desc) a3 = a3_mut # Relax the new candidate a3.set_calculator(EMT()) dyn = BFGS(a3, trajectory=None, logfile=None) dyn.run(fmax=0.05, steps=100) a3.set_raw_score(-a3.get_potential_energy()) da.add_relaxed_step(a3) population.update() write('all_candidates.traj', da.get_all_relaxed_candidates()) python-ase-3.9.1.4567/ase/test/ga/element_operators.py0000664000175000017500000000407512553425527022724 0ustar jensjjensj00000000000000from ase import Atoms from ase.ga.element_crossovers import OnePointElementCrossover a1 = Atoms('SrSrSrBaClClClClBrBrBrBr') a1.info['confid'] = 1 a2 = Atoms('CaCaMgBaFFFFFFFF') a2.info['confid'] = 2 cations = ['Sr', 'Ba', 'Ca', 'Mg'] anions = ['Cl', 'F', 'Br'] op = OnePointElementCrossover([cations, anions], [3, 2], [.25, .5]) a3, desc = op.get_new_individual([a1, a2]) syms = a3.get_chemical_symbols() assert len(set([i for i in syms if i in cations])) < 4 assert len(set([i for i in syms if i in anions])) < 3 from ase.ga.element_mutations import RandomElementMutation op = RandomElementMutation([cations, anions], [3, 2], [.25, .5]) a4, desc = op.get_new_individual([a1]) syms = a4.get_chemical_symbols() assert len(set([i for i in syms if i in cations])) < 4 assert len(set([i for i in syms if i in anions])) < 3 op = RandomElementMutation(anions, 2, .5) a4, desc = op.get_new_individual([a2]) syms = a4.get_chemical_symbols() assert len(set([i for i in syms if i in anions])) == 2 from ase.ga.element_mutations import MoveDownMutation from ase.ga.element_mutations import MoveUpMutation from ase.ga.element_mutations import MoveRightMutation from ase.ga.element_mutations import MoveLeftMutation a1 = Atoms('SrSrClClClCl') a1.info['confid'] = 1 op = MoveDownMutation(cations, 2, .5) a2, desc = op.get_new_individual([a1]) a2.info['confid'] = 2 syms = a2.get_chemical_symbols() assert 'Ba' in syms assert len(set(syms)) == 3 op = MoveUpMutation(cations, 1, 1.) a3, desc = op.get_new_individual([a2]) syms = a3.get_chemical_symbols() assert 'Ba' not in syms assert len(set(syms)) == 2 cations = ['Co', 'Ni', 'Cu'] a1 = Atoms('NiNiBrBr') a1.info['confid'] = 1 op = MoveRightMutation(cations, 1, 1.) a2, desc = op.get_new_individual([a1]) a2.info['confid'] = 2 syms = a2.get_chemical_symbols() assert len(set(syms)) == 2 assert len([i for i in syms if i == 'Cu']) == 2 op = MoveLeftMutation(cations, 2, .5) a3, desc = op.get_new_individual([a2]) syms = a3.get_chemical_symbols() assert len(set(syms)) == 3 a3.set_raw_score(5.0) assert a3.get_raw_score() == 5.0 python-ase-3.9.1.4567/ase/test/db2.py0000664000175000017500000000271012553425527017247 0ustar jensjjensj00000000000000import numpy as np from ase import Atoms from ase.calculators.emt import EMT from ase.constraints import FixAtoms, FixBondLength from ase.db import connect from ase.io import read from ase.structure import molecule from ase.test import must_raise for name in ['y2.json', 'y2.db']: c = connect(name) print(name, c) id = c.reserve(abc=7) c.delete([d.id for d in c.select(abc=7)]) id = c.reserve(abc=7) assert c[id].abc == 7 a = c.get_atoms(id) c.write(Atoms()) ch4 = molecule('CH4', calculator=EMT()) ch4.constraints = [FixAtoms(indices=[1]), FixBondLength(0, 2)] f1 = ch4.get_forces() print(f1) c.delete([d.id for d in c.select(C=1)]) chi = np.array([1 + 0.5j, 0.5]) id = c.write(ch4, data={'1-butyne': 'bla-bla', 'chi': chi}) row = c.get(id) print(row.data['1-butyne'], row.data.chi) assert (row.data.chi == chi).all() assert len(c.get_atoms(C=1).constraints) == 2 f2 = c.get(C=1).forces assert abs(f2.sum(0)).max() < 1e-14 f3 = c.get_atoms(C=1).get_forces() assert abs(f1 - f3).max() < 1e-14 a = read(name + '@' + str(id)) f4 = a.get_forces() assert abs(f1 - f4).max() < 1e-14 with must_raise(ValueError): c.update(id, abc={'a': 42}) c.update(id, grr='hmm') row = c.get(C=1) assert row.id == id assert (row.data.chi == chi).all() with must_raise(ValueError): c.write(ch4, foo=['bar', 2]) python-ase-3.9.1.4567/ase/test/basin.py0000664000175000017500000000340212553425527017673 0ustar jensjjensj00000000000000import numpy as np from math import pi, sqrt from ase import Atoms, io, optimize from ase.calculators.lj import LennardJones from ase.optimize.basin import BasinHopping from ase.io import Trajectory, read from ase.units import kB # Global minima from # Wales and Doye, J. Phys. Chem. A, vol 101 (1997) 5111-5116 E_global = { 4: -6.000000, 5: -9.103852, 6: -12.712062, 7: -16.505384, } N = 7 R = N**(1./3.) np.random.seed(42) pos = np.random.uniform(-R, R, (N, 3)) s = Atoms('He' + str(N), positions = pos) s.set_calculator(LennardJones()) original_positions = 1. * s.get_positions() ftraj = 'lowest.traj' for GlobalOptimizer in [BasinHopping(s, temperature=100 * kB, dr=0.5, trajectory=ftraj, optimizer_logfile=None), ]: if isinstance(GlobalOptimizer, BasinHopping): GlobalOptimizer.run(10) Emin, smin = GlobalOptimizer.get_minimum() else: GlobalOptimizer(totalsteps=10) Emin = s.get_potential_energy() smin = s print("N=", N, 'minimal energy found', Emin, ' global minimum:', E_global[N]) # recalc energy smin.set_calculator(LennardJones()) E = smin.get_potential_energy() assert abs(E - Emin) < 1e-15 smim = read(ftraj) E = smin.get_potential_energy() assert abs(E - Emin) < 1e-15 # check that only minima were written last_energy = None for im in io.read(ftraj + '@:'): energy = im.get_potential_energy() if last_energy is not None: assert energy < last_energy last_energy = energy # reset positions s.set_positions(original_positions) python-ase-3.9.1.4567/ase/test/rotate_euler.py0000664000175000017500000000053312553425527021273 0ustar jensjjensj00000000000000from math import pi, sqrt from ase import Atoms, Atom d = 1.14 a = Atoms([Atom('C', (0, 0, 0)), Atom('O', (d, 0, 0))]) a.rotate_euler(phi=pi/2, theta=pi/4, psi=pi) for p in a[0].position: assert p == 0.0 assert abs(a[1].position[0]) < 1e-15 d2 = d / sqrt(2) assert abs(a[1].position[1] - d2) < 1e-15 assert abs(a[1].position[2] - d2) < 1e-15 python-ase-3.9.1.4567/ase/test/distance.py0000664000175000017500000000333212553425527020373 0ustar jensjjensj00000000000000import itertools import numpy as np from ase import Atoms, Atom, visualize from ase.utils.distance import distance # artificial structure org = Atoms('COPNS', [[-1.75072, 0.62689, 0.00000], [0.58357, 2.71652, 0.00000], [-5.18268, 1.36522, 0.00000], [-1.86663, -0.77867, 2.18917], [-1.80586, 0.20783, -2.79331]]) #visualize.view(org) maxdist = 3.0e-13 # translate for dx in range(3, 10, 2): new = org.copy() new.translate([dx / np.sqrt(2), -dx / np.sqrt(2), 0]) dist = distance(org, new, True) dist2 = distance(org, new, False) print('translation', dx, '-> distance', dist) assert dist < maxdist assert dist == dist2 # rotate for axis in ['x', '-y', 'z', np.array([1, 1, 1] / np.sqrt(3))]: for rot in [20, 200]: new = org.copy() new.translate(-new.get_center_of_mass()) new.rotate(axis, np.pi * rot / 180) dist = distance(org, new, True) dist2 = distance(org, new, False) print('rotation', axis, ', angle', rot, '-> distance', dist) assert dist < maxdist assert dist == dist2 if 0: # reflect new = Atoms() cm = org.get_center_of_mass() for a in org: new.append(Atom(a.symbol, -(a.position - cm))) dist = distance(org, new) print('reflected -> distance', dist) # permute for i, a in enumerate(org): if i < 3: a.symbol = 'H' if hasattr(itertools, 'permutations'): for indxs in itertools.permutations(range(3)): new = org.copy() for c in range(3): new[c].position = org[indxs[c]].position dist = distance(org, new) print('permutation', indxs, '-> distance', dist) assert dist < maxdist python-ase-3.9.1.4567/ase/test/calculator/0000775000175000017500000000000012553427753020362 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/calculator/h2.py0000664000175000017500000000306712553425527021250 0ustar jensjjensj00000000000000from ase.test import NotAvailable from ase.structure import molecule from ase.calculators.calculator import get_calculator required = {'abinit': dict(ecut=200, toldfe=0.0001), 'aims': dict(sc_accuracy_rho=5.e-3), 'gpaw': dict(mode='lcao', basis='sz(dzp)', realspace=False), 'cp2k': dict(auto_write=True, uks=True)} def h2dft(name): Calculator = get_calculator(name) par = required.get(name, {}) calc = Calculator(label=name, xc='LDA', **par) h2 = molecule('H2', calculator=calc) h2.center(vacuum=2.0) e2 = h2.get_potential_energy() calc.set(xc='PBE') e2pbe = h2.get_potential_energy() h1 = h2.copy() del h1[1] h1.set_initial_magnetic_moments([1]) h1.calc = calc e1pbe = h1.get_potential_energy() calc.set(xc='LDA') e1 = h1.get_potential_energy() try: m1 = h1.get_magnetic_moment() except NotImplementedError: pass else: print(m1) print(2 * e1 - e2) print(2 * e1pbe - e2pbe) print(e1, e2, e1pbe, e2pbe) calc = Calculator(name) print(calc.parameters, calc.results, calc.atoms) assert not calc.calculation_required(h1, ['energy']) h1 = calc.get_atoms() print(h1.get_potential_energy()) label = 'dir/' + name + '-h1' calc = Calculator(label=label, atoms=h1, xc='LDA', **par) print(h1.get_potential_energy()) print(Calculator.read_atoms(label).get_potential_energy()) names = ['abinit', 'aims', 'gaussian', 'nwchem', 'cp2k'] for name in names: try: h2dft(name) except NotAvailable: pass python-ase-3.9.1.4567/ase/test/calculator/__init__.py0000664000175000017500000000000012553425527022456 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/test/calculator/traj.py0000664000175000017500000000230712553425527021673 0ustar jensjjensj00000000000000import os from ase.calculators.calculator import get_calculator from ase.io import read, write from ase.structure import molecule from ase.test import test_calculator_names def h2(name, par): h2 = molecule('H2', pbc=par.pop('pbc', False)) h2.center(vacuum=2.0) h2.calc = get_calculator(name)(**par) e = h2.get_potential_energy() f = h2.get_forces() assert not h2.calc.calculation_required(h2, ['energy', 'forces']) write('h2.traj', h2) h2 = read('h2.traj') assert abs(e - h2.get_potential_energy()) < 1e-12 assert abs(f - h2.get_forces()).max() < 1e-12 parameters = { 'abinit': dict(ecut=200, toldfe=0.0001), 'aims': dict(sc_accuracy_rho=5.e-3, sc_accuracy_forces=1e-4, xc='LDA'), 'gpaw': dict(mode='lcao', basis='sz(dzp)', realspace=False), 'elk': dict(tasks=0, rgkmax=5.0, epsengy=1.0, epspot=1.0, tforce=True, pbc=True), 'jacapo': dict(pbc=True), 'vasp': dict(xc='LDA')} for name in test_calculator_names + ['emt']: if name in ['cp2k', 'gromacs', 'lammpslib', 'mopac', 'turbomole']: continue par = parameters.get(name, {}) os.mkdir(name + '-test') os.chdir(name + '-test') h2(name, par) os.chdir('..') python-ase-3.9.1.4567/ase/test/calculator/kd2mp.py0000664000175000017500000000040012553425527021740 0ustar jensjjensj00000000000000import numpy as np from ase import Atoms from ase.calculators.calculator import kptdensity2monkhorstpack as kd2mp kd = 25 / (2 * np.pi) a = 6.0 N = kd2mp(Atoms(cell=(a, a, a), pbc=True), kd)[0] assert N * a / (2 * np.pi) >= kd, 'Too small k-point density' python-ase-3.9.1.4567/ase/test/calculator/al.py0000664000175000017500000000240212553425527021323 0ustar jensjjensj00000000000000from ase.test import NotAvailable from ase.lattice import bulk from ase.calculators.calculator import get_calculator required = {'abinit': dict(ecut=200, toldfe=0.0001, chksymbreak=0), 'aims': dict(sc_accuracy_rho=5.e-3), 'elk': dict(tasks=0, rgkmax=5.0), 'gpaw': dict(mode='pw'), 'cp2k': dict(auto_write=True, uks=True, max_scf=1, cutoff=400)} def run(name): Calculator = get_calculator(name) par = required.get(name, {}) calc = Calculator(label=name, xc='LDA', kpts=1.0, **par) al = bulk('AlO', crystalstructure='rocksalt', a=4.5) al.calc = calc e = al.get_potential_energy() calc.set(xc='PBE', kpts=(2, 2, 2)) epbe = al.get_potential_energy() print(e, epbe) calc = Calculator(name) print(calc.parameters, calc.results, calc.atoms) assert not calc.calculation_required(al, ['energy']) al = calc.get_atoms() print(al.get_potential_energy()) label = 'dir/' + name + '-2' calc = Calculator(label=label, atoms=al, xc='LDA', kpts=1.0, **par) print(al.get_potential_energy()) print(Calculator.read_atoms(label).get_potential_energy()) names = ['abinit', 'aims', 'elk', 'cp2k'] for name in names: try: run(name) except NotAvailable: pass python-ase-3.9.1.4567/ase/test/calculator/bandgap.py0000664000175000017500000000411212553425527022323 0ustar jensjjensj00000000000000from ase.test import NotAvailable from ase.lattice import bulk from ase.dft.bandgap import get_band_gap from ase.calculators.calculator import get_calculator kpts = (4, 4, 4) required = {'abinit': dict(ecut=200, toldfe=0.0001, chksymbreak=0), 'aims': dict(sc_accuracy_rho=5.e-4, output=['k_point_list', 'k_eigenvalue,' + str(kpts[0]*kpts[1]*kpts[2])]), 'elk': dict(tasks=0, rgkmax=5.0), 'gpaw': dict(mode='pw')} def run(name): Calculator = get_calculator(name) par = required.get(name, {}) calc = Calculator(label=name + '_bandgap', xc='PBE', kpts=kpts, **par) # abinit, aims, elk - do not recognize the syntax below: # https://trac.fysik.dtu.dk/projects/ase/ticket/98 #kpts={'size': kpts, 'gamma': True}, **par) si = bulk('Si', crystalstructure='diamond', a=5.43) si.calc = calc e = si.get_potential_energy() print(name, get_band_gap(si.calc)) del si.calc # test spin-polarization calc = Calculator(label=name + '_bandgap_spinpol', xc='PBE', kpts=kpts, **par) # abinit, aims, elk - do not recognize the syntax below: # https://trac.fysik.dtu.dk/projects/ase/ticket/98 #kpts={'size': kpts, 'gamma': True}, **par) si.set_initial_magnetic_moments([-0.1, 0.1]) # this should not be neccesary in the new ase interface standard ... if si.get_initial_magnetic_moments().any(): # spin-polarization if name == 'aims': calc.set(spin='collinear') if name == 'elk': calc.set(spinpol=True) si.set_calculator(calc) e = si.get_potential_energy() print(name, get_band_gap(si.calc)) # gpaw does not conform to the new ase interface standard: # https://trac.fysik.dtu.dk/projects/gpaw/ticket/268 names = ['abinit', 'aims', 'elk'] #, 'gpaw'] for name in names: try: run(name) except NotAvailable: pass python-ase-3.9.1.4567/ase/test/neb.py0000664000175000017500000000351112553425527017344 0ustar jensjjensj00000000000000import threading from ase.test import World from ase.io import Trajectory, read from ase.neb import NEB, NEBtools from ase.calculators.morse import MorsePotential from ase.optimize import BFGS fmax = 0.05 nimages = 3 print([a.get_potential_energy() for a in Trajectory('H.traj')]) images = [Trajectory('H.traj')[-1]] for i in range(nimages): images.append(images[0].copy()) images[-1].positions[6, 1] = 2 - images[0].positions[6, 1] neb = NEB(images) neb.interpolate() if 0: # verify that initial images make sense from ase.visualize import view view(neb.images) for image in images: image.set_calculator(MorsePotential()) images[0].get_potential_energy() images[-1].get_potential_energy() dyn = BFGS(neb, trajectory='mep.traj', logfile='mep.log') dyn.run(fmax=fmax) for a in neb.images: print(a.positions[-1], a.get_potential_energy()) results = [images[2].get_potential_energy()] # Check NEB tools. nt_images = [read('mep.traj', index=_) for _ in range(-4, 0)] nebtools = NEBtools(nt_images) nt_fmax = nebtools.get_fmax() Ef, dE = nebtools.get_barrier() assert nt_fmax < fmax def run_neb_calculation(cpu): images = [Trajectory('H.traj')[-1]] for i in range(nimages): images.append(images[0].copy()) images[-1].positions[6, 1] = 2 - images[0].positions[6, 1] neb = NEB(images, parallel=True, world=cpu) neb.interpolate() images[cpu.rank + 1].set_calculator(MorsePotential()) dyn = BFGS(neb) dyn.run(fmax=fmax) if cpu.rank == 1: results.append(images[2].get_potential_energy()) w = World(nimages - 1) ranks = [w.get_rank(r) for r in range(w.size)] threads = [threading.Thread(target=run_neb_calculation, args=(rank,)) for rank in ranks] for t in threads: t.start() for t in threads: t.join() print(results) assert abs(results[0] - results[1]) < 1e-13 python-ase-3.9.1.4567/ase/test/eoswoase.py0000664000175000017500000000066512553425527020434 0ustar jensjjensj00000000000000# Test ase.utils.eos without ASE (eoswoase) # This test will run if numpy is in the default sys.path # because PYTHONPATH is overwritten under os.system call! import os import sys import ase dir = os.path.abspath(os.path.dirname(ase.__file__)) utilsdir = os.path.join(dir, 'utils') sjeos = os.path.join(utilsdir, 'sjeos.py') if sys.platform not in ['win32']: assert os.system("PYTHONPATH=" + utilsdir + " python " + sjeos) == 0 python-ase-3.9.1.4567/ase/test/neighbor.py0000664000175000017500000000454212553425527020402 0ustar jensjjensj00000000000000import numpy.random as random import numpy as np from ase import Atoms from ase.calculators.neighborlist import NeighborList from ase.lattice import bulk atoms = Atoms(numbers=range(10), cell=[(0.2, 1.2, 1.4), (1.4, 0.1, 1.6), (1.3, 2.0, -0.1)]) atoms.set_scaled_positions(3 * random.random((10, 3)) - 1) def count(nl, atoms): c = np.zeros(len(atoms), int) R = atoms.get_positions() cell = atoms.get_cell() d = 0.0 for a in range(len(atoms)): i, offsets = nl.get_neighbors(a) for j in i: c[j] += 1 c[a] += len(i) d += (((R[i] + np.dot(offsets, cell) - R[a])**2).sum(1)**0.5).sum() return d, c for sorted in [False, True]: for p1 in range(2): for p2 in range(2): for p3 in range(2): print(p1, p2, p3) atoms.set_pbc((p1, p2, p3)) nl = NeighborList(atoms.numbers * 0.2 + 0.5, skin=0.0, sorted=sorted) nl.update(atoms) d, c = count(nl, atoms) atoms2 = atoms.repeat((p1 + 1, p2 + 1, p3 + 1)) nl2 = NeighborList(atoms2.numbers * 0.2 + 0.5, skin=0.0, sorted=sorted) nl2.update(atoms2) d2, c2 = count(nl2, atoms2) c2.shape = (-1, 10) dd = d * (p1 + 1) * (p2 + 1) * (p3 + 1) - d2 print(dd) print(c2 - c) assert abs(dd) < 1e-10 assert not (c2 - c).any() h2 = Atoms('H2', positions=[(0, 0, 0), (0, 0, 1)]) nl = NeighborList([0.5, 0.5], skin=0.1, sorted=True, self_interaction=False) assert nl.update(h2) assert not nl.update(h2) assert (nl.get_neighbors(0)[0] == [1]).all() h2[1].z += 0.09 assert not nl.update(h2) assert (nl.get_neighbors(0)[0] == [1]).all() h2[1].z += 0.09 assert nl.update(h2) assert (nl.get_neighbors(0)[0] == []).all() assert nl.nupdates == 2 x = bulk('X', 'fcc', a=2**0.5) print(x) nl = NeighborList([0.5], skin=0.01, bothways=True, self_interaction=False) nl.update(x) assert len(nl.get_neighbors(0)[0]) == 12 nl = NeighborList([0.5] * 27, skin=0.01, bothways=True, self_interaction=False) nl.update(x * (3, 3, 3)) for a in range(27): assert len(nl.get_neighbors(a)[0]) == 12 assert not np.any(nl.get_neighbors(13)[1]) python-ase-3.9.1.4567/ase/test/n2.py0000664000175000017500000000040412553425527017115 0ustar jensjjensj00000000000000from ase import Atoms from ase.calculators.emt import EMT from ase.optimize import QuasiNewton n2 = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT()) QuasiNewton(n2).run(0.01) print(n2.get_distance(0, 1), n2.get_potential_energy()) python-ase-3.9.1.4567/ase/tasks/0000775000175000017500000000000012553427753016377 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/tasks/main.py0000664000175000017500000000602012553425527017670 0ustar jensjjensj00000000000000import 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', task=None): if isinstance(args, str): # leading/trailing/extra-mid spaces result in weird errors args = ' '.join(args.split()) args = args.split(' ') argsoriginal = args[:] if len(args) > 0 and args[0] in calcnames: calcname = args.pop(0) if task is None: taskname = 'molecule' if (len(args) > 0 and (args[0] in ['molecule', 'bulk'] or args[0].endswith('.py'))): taskname = args.pop(0) if taskname.endswith('.py'): locals = {} exec(compile(open(taskname).read(), taskname, 'exec'), 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() if len(args) == 0 and task.collection is None: sys.stderr.write( usage % textwrap.fill(', '.join(calcnames[:-1]) + ' or ' + calcnames[-1] + '. Default value is emt.', initial_indent='calculator: ', subsequent_indent=' ' * 12)) return 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.9.1.4567/ase/tasks/__init__.py0000664000175000017500000000000012553425527020473 0ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/tasks/io.py0000664000175000017500000000273312553425527017362 0ustar jensjjensj00000000000000import 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 __init__(self): json.JSONEncoder.__init__(self, sort_keys=True, indent=4) 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, results): if world.rank == 0: fd = open(name, 'w') fd.write(dumps(results)) fd.close() def read_json(name): fd = open(name, 'r') results = loads(fd.read()) fd.close() world.barrier() return numpyfy(results) python-ase-3.9.1.4567/ase/tasks/molecule.py0000664000175000017500000002205512553425527020557 0ustar jensjjensj00000000000000from 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 Trajectory 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_keys = ['energy', 'relaxed energy', 'distance', 'frequency', 'atomic energy'] 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: Z = atomic_numbers[symbols[0]] magmom = ground_state_magnetic_moments[Z] 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, data=None): N, x = self.fit d0 = atoms.get_distance(0, 1) distances = np.linspace(d0 * (1 - x), d0 * (1 + x), N) energies = [] traj = Trajectory(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() if data is not None: data['distances'] = distances data['energies'] = energies else: assert N % 2 == 1 data = {'energy': energies[N // 2], 'distances': distances, 'energies': energies} return data def calculate(self, name, atoms): if self.fmax is not None: # this performs relaxation of internal degrees of freedom data = OptimizeTask.calculate(self, name, atoms) data['distance'] = atoms.get_distance(0, -1) else: # no optimization if self.fit is None or len(atoms) != 2: # for dimers: only calculate single-point energy if no fit follows data = OptimizeTask.calculate(self, name, atoms) if self.fit is not None and len(atoms) == 2: if self.fmax is not None: # fit after optimization self.fit_bond_length(name, atoms, data) else: # fit is the only task performed data = self.fit_bond_length(name, atoms) self.check_occupation_numbers(atoms) return data def 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(name + ': 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['relaxed energy'] = emin data['distance'] = dmin data['frequency'] = hnu for name, data in self.data.items(): atoms = self.create_system(name) if len(atoms) == 1: 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: data['atomic energy'] = eatoms 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.9.1.4567/ase/tasks/task.py0000664000175000017500000004152212553425527017714 0ustar jensjjensj00000000000000import os 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 import ase.optimize from ase.utils import Lock, 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='-', collection=None): """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. collection: dict Collection of systems. 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.data = {} self.interactive_python_session = False self.contains = None self.modify = None self.after = None self.clean = False self.write_funcs = [] self.lock = None self.summary_keys = ['energy'] self.collection = collection 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=None): filename = self.taskname if self.tag: filename += '-' + self.tag if name: filename = name + '-' + filename if ext: filename += '.' + ext return filename 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=None): """Run task for all names. The task will be one of these four: * Open ASE's GUI * Write configuration to file * Write summary * Do the actual calculation """ if self.lock is None: # Create lock object: self.lock = Lock(self.get_filename(ext='lock')) if self.clean: self.clean_json_file(names) return if names is None or len(names) == 0: names = self.collection.keys() 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() self.analyse() self.summarize(names) return atoms = None for name in names: if self.use_lock_files: try: filename = self.get_filename(ext='json') self.lock.acquire() if os.path.isfile(filename): data = read_json(filename) if name not in data: data[name] = {} write_json(filename, data) else: self.log('Skipping', name) continue else: write_json(filename, {name: {}}) finally: self.lock.release() if atoms is not None: del atoms.calc atoms = self.run_single(name) return atoms def run_single(self, name): self.log('Running', 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) if self.after: exec(self.after) except KeyboardInterrupt: raise except Exception: self.log(name, 'FAILED') traceback.print_exc(file=self.logfile) return tstop = time() data['time'] = tstop - tstart filename = self.get_filename(ext='json') try: self.lock.acquire() if os.path.isfile(filename): alldata = read_json(filename) else: alldata = {} alldata[name] = data write_json(filename, alldata) finally: self.lock.release() 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: if self.collection is None: system = self.build_system(name) else: system = self.collection[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() data = {'energy': e} return data def read(self, skipempty=True): self.data = read_json(self.get_filename(ext='json')) if skipempty: self.data = dict((key.encode('ascii'), value) for key, value in self.data.items() if value) def clean_json_file(self, names=None): self.read(skipempty=False) n = len(self.data) if names: for name in names: del self.data[name] else: self.data = dict((key, value) for key, value in self.data.items() if value) filename = self.get_filename(ext='json') try: self.lock.acquire() write_json(filename, self.data) finally: self.lock.release() n -= len(self.data) self.log('Cleaned', n, ['tasks', 'task'][n == 1]) def summarize(self, names): lines = [['name'] + self.summary_keys] for name in names: if name not in self.data: continue d = self.data[name] line = [name] for key in self.summary_keys: if key in d: line.append('%.6f' % d[key]) else: line.append('') lines.append(line) lengths = [max(len(line[i]) for line in lines) for i in range(len(lines[0]))] for line in lines: for txt, l in zip(line, lengths): self.log('%*s' % (l, txt), end=' ') self.log() 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: --modify="system.positions[-1,2]+=0.1".') general.add_option('--after', metavar='...', help='Execute Python statement after calculation.') general.add_option('--clean', action='store_true', help='Remove unfinished tasks from json file.') 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 and self.collection is None: 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 self.modify is not None: try: assert not isinstance(eval(self.modify), str), \ '--modify option received a string argument. Check quoting.' except SyntaxError: pass self.after = opts.after self.clean = opts.clean if opts.slice: self.slice = string2index(opts.slice) class OptimizeTask(Task): taskname = 'opt' def __init__(self, fmax=None, constrain_tags=[], optimizer='LBFGS', steps=100000000, **kwargs): self.fmax = fmax self.constrain_tags = constrain_tags self.optimizer = optimizer self.steps = steps Task.__init__(self, **kwargs) self.summary_keys = ['energy', 'relaxed energy'] def optimize(self, name, atoms, data, trajectory=None): mask = [t in self.constrain_tags for t in atoms.get_tags()] if mask: constrain = FixAtoms(mask=mask) atoms.constraints = [constrain] optstr = "ase.optimize." + self.optimizer optstr += "(atoms, " if trajectory is not None: # allow existing trajectory to append new optimizations # or create new one if trajectory is str optstr += "trajectory=trajectory," else: # create new trajectory with default name optstr += "trajectory=self.get_filename(name, 'traj')," optstr += "logfile=self.logfile)" optimizer = eval(optstr) try: # handle scipy optimizers who raise Converged when done from ase.optimize import Converged try: optimizer.run(fmax=self.fmax, steps=self.steps) except Converged: pass except ImportError: optimizer.run(fmax=self.fmax, steps=self.steps) # StrainFilter optimizer steps steps = optimizer.get_number_of_steps() if data.get('optimizer steps', None) is None: data['optimizer steps'] = steps else: data['optimizer steps'] += steps # optimizer force calls if hasattr(optimizer, 'force_calls'): calls = optimizer.force_calls else: calls = steps if data.get('optimizer force calls', None) is None: data['optimizer force calls'] = calls else: data['optimizer force calls'] += calls def calculate(self, name, atoms): data = Task.calculate(self, name, atoms) if self.fmax is not None: self.optimize(name, atoms, data) e = atoms.get_potential_energy() data['relaxed energy'] = e return data def add_options(self, parser): Task.add_options(self, parser) optimize = optparse.OptionGroup(parser, 'Optimize') optimize.add_option('-R', '--relax', metavar='FMAX[,OPTIMIZER]', help='Relax internal coordinates using ' 'OPTIMIZER algorithm. The OPTIMIZER keyword is ' 'optional, and if omitted LBFGS is used by default.') optimize.add_option('--relaxsteps', type='int', metavar='steps', help='Limit the number of optimizer steps.') 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) if opts.relax: if len(opts.relax.split(',')) > 1: self.fmax, self.optimizer = opts.relax.split(',') else: self.fmax = opts.relax self.optimizer = 'LBFGS' self.fmax = float(self.fmax) if opts.relaxsteps is not None: self.steps = int(opts.relaxsteps) else: # yes, the default number of ASE optimizer steps # ase/optimize/optimize.py self.steps = 100000000 if opts.constrain_tags: self.constrain_tags = [int(t) for t in opts.constrain_tags.split(',')] python-ase-3.9.1.4567/ase/tasks/bulk.py0000664000175000017500000002741312553425527017712 0ustar jensjjensj00000000000000import optparse import numpy as np from ase.lattice import bulk from ase.constraints import StrainFilter import ase.optimize 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 Trajectory class BulkTask(OptimizeTask): taskname = 'bulk' def __init__(self, crystal_structure=None, lattice_constant=None, c_over_a=None, cubic=False, orthorhombic=False, fit=None, eos=None, sfmax=None, soptimizer='BFGS', ssteps=100000000, **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.eos = eos self.fit = fit self.sfmax = sfmax self.soptimizer = soptimizer self.ssteps = ssteps self.repeat = None OptimizeTask.__init__(self, **kwargs) self.summary_keys = ['energy', 'fitted energy', 'volume', 'B'] 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, data=None): N, x = self.fit cell0 = atoms.get_cell() v = atoms.get_volume() if x > 0: strains = np.linspace(1 - x, 1 + x, N) else: strains = np.linspace(1 + x / v, 1 - x / v, N)**(1./3) energies = [] traj = Trajectory(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() if data is not None: data['strains'] = strains data['energies'] = energies else: assert N % 2 == 1 data = {'energy': energies[N // 2], 'strains': strains, 'energies': energies} return data def soptimize(self, name, atoms, data, trajectory=None): # Call it soptimize to avoid conflicts with OptimizeTask.optimize. # With so many levels of inheritance one never knows ... optstr = "ase.optimize." + self.soptimizer optstr += "(atoms, logfile=self.logfile)" optimizer = eval(optstr) if trajectory is not None: if not isinstance(trajectory, str): optimizer.attach(trajectory) try: # handle scipy optimizers who raise Converged when done from ase.optimize import Converged try: optimizer.run(fmax=self.sfmax, steps=self.ssteps) except Converged: raise except ImportError: optimizer.run(fmax=self.sfmax, steps=self.ssteps) # StrainFilter optimizer steps steps = optimizer.get_number_of_steps() if data.get('strain optimizer steps', None) is None: data['strain optimizer steps'] = steps else: data['strain optimizer steps'] += steps # optimizer force calls if hasattr(optimizer, 'force_calls'): calls = optimizer.force_calls else: calls = steps if data.get('strain optimizer force calls', None) is None: data['strain optimizer force calls'] = calls else: data['strain optimizer force calls'] += calls def converged(self, atoms, sfmax, fmax): # The same criteria as in ASE optimizers: # see ase.constraints: StrainFilter sforces = - atoms.get_stress().ravel()*atoms.get_volume() rmssforces = np.sum(sforces**2)**0.5 maxsforce = rmssforces # see ase.optimize.optimize: converged rmsforces = np.sum(atoms.get_forces()**2, axis=1)**0.5 maxforce = max(rmsforces) if maxforce < fmax and maxsforce < sfmax: return True return False def calculate(self, name, atoms): #???? if self.sfmax is not None and self.fmax is not None: # this performs first relaxation of internal degrees of freedom data = OptimizeTask.calculate(self, name, atoms) # writing traj from optimizer does not work for StrainFilter! traj = Trajectory(self.get_filename(name, 'traj'), 'a', atoms) sf = StrainFilter(atoms) while not self.converged(atoms, sfmax=self.sfmax, fmax=self.fmax): # take a step on the cell self.soptimize(name, sf, data, trajectory=traj) # relax internal degrees of freedom OptimizeTask.optimize(self, name, atoms, data, trajectory=traj) data['relaxed energy'] = atoms.get_potential_energy() data['relaxed volume'] = atoms.get_volume() elif self.sfmax is not None: # this performs single-point energy calculation data = OptimizeTask.calculate(self, name, atoms) sf = StrainFilter(atoms) # writing traj from optimizer does not work for StrainFilter! traj = Trajectory(self.get_filename(name, 'traj'), 'w', atoms) self.soptimize(name, sf, data, trajectory=traj) data['relaxed energy'] = atoms.get_potential_energy() data['relaxed volume'] = atoms.get_volume() elif self.fmax is not None: data = OptimizeTask.calculate(self, name, atoms) else: # no optimization if self.fit is None: # only calculate single-point energy if no fit follows data = OptimizeTask.calculate(self, name, atoms) if self.fit is not None: if self.sfmax is not None or self.fmax is not None: # fit after optimization self.fit_volume(name, atoms, data) else: # fit is the only task performed data = self.fit_volume(name, atoms) return data def analyse(self): for name, data in self.data.items(): if 'strains' in data: atoms = self.create_system(name) # use relaxed volume if present if 'relaxed volume' in data: volume = data['relaxed volume'] else: volume = atoms.get_volume() volumes = data['strains']**3 * volume energies = data['energies'] # allow selection of eos type independent of data if self.eos is not None: eos = EquationOfState(volumes, energies, self.eos) else: eos = EquationOfState(volumes, energies) try: v, e, B = eos.fit() except (RuntimeError, ValueError): pass else: data['fitted energy'] = e data['volume'] = v data['B'] = B if abs(v) < min(volumes) or abs(v) > max(volumes): raise ValueError(name + ': fit outside of range! ' + \ str(abs(v)) + ' not in ' + \ str(volumes)) 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 odd N points and variations of the lattice ' + 'constant a from -x % to +x %, i.e. in the interval ' '. ' + 'This method gives non-equidistant sampling of volume. ' + 'With x negative (in Angstrom**3) the sampling of ' + 'the cell volume (v) in the interval ' + '<(1 + x /v), ..., 1, ..., (1 - x /v)> is used. ' + 'This method gives equidistant sampling of volume.') bulk.add_option('--eos', type='str', metavar='eos', help='Selects the type of eos.') bulk.add_option('--srelax', metavar='SFMAX[,SOPTIMIZER]', help='Relax cell by minimizing stress using StranFilter ' 'with SOPTIMIZER algorithm. The SOPTIMIZER keyword is ' 'optional, and if omitted BFGS is used by default.') bulk.add_option('--srelaxsteps', type='int', metavar='ssteps', help='Limit the number of SF optimizer steps.') bulk.add_option('-x', '--crystal-structure', help='Crystal structure.', choices=['sc', 'fcc', 'bcc', 'hcp', 'diamond', 'zincblende', 'rocksalt', 'cesiumchloride', 'fluorite']) 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.srelax: if len(opts.srelax.split(',')) > 1: self.sfmax, self.soptimizer = opts.srelax.split(',') else: self.sfmax = opts.srelax self.soptimizer = 'BFGS' self.sfmax = float(self.sfmax) if opts.srelaxsteps is not None: self.ssteps = int(opts.srelaxsteps) else: # yes, the default number of ASE optimizer steps # ase/optimize/optimize.py self.ssteps = 100000000 if opts.fit: points, strain = opts.fit.split(',') if float(strain) > 0: self.fit = (int(points), float(strain) * 0.01) else: self.fit = (int(points), float(strain)) self.eos = opts.eos 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.9.1.4567/ase/tasks/calcfactory.py0000664000175000017500000001502512553425527021243 0ustar jensjjensj00000000000000import optparse from math import sqrt, pi import numpy as np from ase.dft.kpoints import monkhorst_pack def str2dict(s, namespace={}, sep='='): """Convert comma-separated key=value string to dictionary. Examples: >>> str2dict('xc=PBE,nbands=200,parallel={band:4}') {'xc': 'PBE', 'nbands': 200, 'parallel': {'band': 4}} >>> str2dict('a=1.2,b=True,c=ab,d=1,2,3,e={f:42,g:cd}') {'a': 1.2, 'c': 'ab', 'b': True, 'e': {'g': 'cd', 'f': 42}, 'd': (1, 2, 3)} """ dct = {} s = (s + ',').split(sep) for i in range(len(s) - 1): key = s[i] m = s[i + 1].rfind(',') value = s[i + 1][:m] if value[0] == '{': assert value[-1] == '}' value = str2dict(value[1:-1], {}, ':') else: 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': if self.name == 'aims': # XXX Aims uses k_grid! self.kwargs['k_grid'] = kpts else: self.kwargs['kpts'] = kpts if self.label is not None: self.kwargs[self.label] = name return self.Class(**self.kwargs) if self.label is None: return self.Class(**self.kwargs) else: return self.Class(name, **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', 'gaussian', 'hotbit', 'jacapo', 'lammps', 'lj', 'mopac', 'morse', 'nwchem', 'siesta', 'turbomole', 'vasp'] classnames = {'asap': 'EMT', 'aims': 'Aims', 'elk': 'ELK', 'emt': 'EMT', 'fleur': 'FLEUR', 'gaussian': 'Gaussian', 'jacapo': 'Jacapo', 'lammps': 'LAMMPS', 'lj': 'LennardJones', 'mopac': 'Mopac', 'morse': 'MorsePotential', 'nwchem': 'NWChem', 'vasp': 'Vasp'} def calculator_factory(name, **kwargs): """Create an ASE calculator factory.""" if name == 'abinit': from ase.calculators.abinit import Abinit return CalculatorFactory(Abinit, 'Abinit', 'label', **kwargs) if name == 'aims': from ase.calculators.aims import Aims return CalculatorFactory(Aims, 'aims', 'label', **kwargs) if name == 'nwchem': from ase.calculators.nwchem import NWChem return CalculatorFactory(NWChem, 'NWChem', 'label', 'no k-points', **kwargs) 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', 'label', **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', 'gaussian', 'lammpsrun', 'lj', 'mopac', '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.9.1.4567/ase/md/0000775000175000017500000000000012553427753015652 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/md/fix.py0000664000175000017500000000232312553425527017007 0ustar jensjjensj00000000000000import numpy as np class FixRotation: """Remove rotation from an atoms object. This class is intended as an observer on an atoms class during a molecular dynamics simulation. When it is called, it removes any rotation around the center of mass. It assumes that the system is a (nano)particle with free boundary conditions. Bugs: Should check that the boundary conditions make sense. """ def __init__(self, atoms): self.atoms = atoms def __call__(self): atoms = self.atoms r = atoms.get_positions() - atoms.get_center_of_mass() v = atoms.get_velocities() p = atoms.get_momenta() m = atoms.get_masses() x = r[:,0] y = r[:,1] z = r[:,2] I11 = np.sum(m * (y**2 + z**2)) I22 = np.sum(m * (x**2 + z**2)) I33 = np.sum(m * (x**2 + y**2)) I12 = np.sum(-m * x * y) I13 = np.sum(-m * x * z) I23 = np.sum(-m * y * z) I = np.array([[I11, I12, I13], [I12, I22, I23], [I13, I23, I33]]) w = np.dot(np.linalg.inv(I), np.sum(np.cross(r, p), axis=0)) self.atoms.set_velocities(v - np.cross(w, r)) python-ase-3.9.1.4567/ase/md/__init__.py0000664000175000017500000000021412553425527017755 0ustar jensjjensj00000000000000"""Molecular Dynamics.""" from ase.md.logger import MDLogger from ase.md.verlet import VelocityVerlet from ase.md.langevin import Langevin python-ase-3.9.1.4567/ase/md/md.py0000664000175000017500000000242312553425527016622 0ustar jensjjensj00000000000000"""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 range(steps): f = self.step(f) self.nsteps += 1 self.call_observers() def get_time(self): return self.nsteps * self.dt python-ase-3.9.1.4567/ase/md/velocitydistribution.py0000664000175000017500000000532312553425527022522 0ustar jensjjensj00000000000000# 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, force_temp=False): """Sets the momenta to a Maxwell-Boltzmann distribution. temp should be fed in energy units; i.e., for 300 K use temp=300.*units.kB. If force_temp is set to True, it scales the random momenta such that the temperature request is precise. """ momenta = _maxwellboltzmanndistribution(atoms.get_masses(), temp, communicator) atoms.set_momenta(momenta) if force_temp: temp0 = atoms.get_kinetic_energy() / len(atoms) / 1.5 gamma = temp / temp0 atoms.set_momenta(atoms.get_momenta() * np.sqrt(gamma)) 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.9.1.4567/ase/md/langevin.py0000664000175000017500000001043212553425527020024 0ustar jensjjensj00000000000000"""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.""" _lgv_version = 2 # Helps Asap doing the right thing. Increment when changing stuff. 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.reshape(-1) * (2.0/3.0 - 0.5 * lt) * lt) sdpos.shape = (-1, 1) sdmom = np.sqrt(self.temp * masses.reshape(-1) * 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.reshape(-1) c1.shape = (-1, 1) c2 = act2 * dt * dt / masses.reshape(-1) 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 self.natoms = self.atoms.get_number_of_atoms() # Also works in parallel Asap. 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)) if self.communicator is not None: 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) rrnd *= np.sqrt(self.natoms / (self.natoms - 1.0)) prnd *= np.sqrt(self.natoms / (self.natoms - 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(atoms.get_momenta() + self.c4 * f) return f python-ase-3.9.1.4567/ase/md/npt.py0000664000175000017500000007627712553425527017045 0ustar jensjjensj00000000000000from __future__ import print_function '''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. mask may also be specified as a symmetric 3x3 array indicating which strain values may change. 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: run(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. _npt_version = 2 # Version number, used for Asap compatibility. 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 isinstance(stress, type(1.0)) or isinstance(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 RuntimeError('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 range(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) self.q_past = self.q self.q = self.q_future 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() 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 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.stresscalculator() - 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) # Why scale_atoms ... r = dot(q + 0.5, h) self.atoms.set_positions(r) # ... they are overwritten here ??? # 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.9.1.4567/ase/md/verlet.py0000664000175000017500000000202012553425527017514 0ustar jensjjensj00000000000000import 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.9.1.4567/ase/md/nptberendsen.py0000664000175000017500000001354712553425527020722 0ustar jensjjensj00000000000000"""Berendsen NPT dynamics class.""" import numpy as np from ase.md.nvtberendsen import NVTBerendsen import ase.units as units 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(voigt=False) old_pressure = -stress.trace() / 3 * 1e-5 / units.Pascal 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 Inhomogeneous_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)) pbc = self.atoms.get_pbc() scl_pressurex = 1.0 - taupscl * (self.pressure - stress[0]) * pbc[0] scl_pressurey = 1.0 - taupscl * (self.pressure - stress[1]) * pbc[1] scl_pressurez = 1.0 - taupscl * (self.pressure - stress[2]) * pbc[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.9.1.4567/ase/md/logger.py0000664000175000017500000000630312553425527017502 0ustar jensjjensj00000000000000"""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 standard 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, 1) self.ownlogfile = True self.stress = stress self.peratom = peratom if self.dyn is not None: self.hdr = "%-9s " % ("Time[ps]",) self.fmt = "%-9.3f " 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 <= 100: digits = 4 elif self.natoms <= 1000: digits = 3 elif self.natoms <= 10000: 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.9.1.4567/ase/md/nvtberendsen.py0000664000175000017500000000621112553425527020716 0ustar jensjjensj00000000000000"""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.9.1.4567/ase/dimer.py0000664000175000017500000013121412553425526016722 0ustar jensjjensj00000000000000"""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: * Henkelman and Jonsson, JCP 111, 7010 (1999) * Olsen, Kroes, Henkelman, Arnaldsson, and Jonsson, JCP 121, 9776 (2004). * Heyden, Bell, and Keil, JCP 123, 224101 (2005). * Kastner and Sherwood, JCP 128, 014106 (2008). """ 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 is 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.atoms0, energy=self.atoms.get_potential_energy(), forces=self.atoms.get_forces()) 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 is not 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 __len__(self): return len(self.atoms) 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 isinstance(c, 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 isinstance(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.9.1.4567/ase/db/0000775000175000017500000000000012553427753015637 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/db/convert.py0000664000175000017500000000150512553425526017666 0ustar jensjjensj00000000000000import optparse import os from ase.db import connect from ase.db.sqlite import index_statements def convert(name): con1 = connect(name, use_lock_file=False) con1._allow_reading_old_format = True newname = name[:-2] + 'new.db' with connect(newname, create_indices=False, use_lock_file=False) as con2: for dct in con1.select(): kvp = dct.get('key_value_pairs', {}) con2.write(dct, data=dct.get('data'), **kvp) c = con2._connect() for statement in index_statements: c.execute(statement) c.commit() os.rename(name, name[:-2] + 'old.db') os.rename(newname, name) def main(): parser = optparse.OptionParser() opts, args = parser.parse_args() for name in args: convert(name) if __name__ == '__main__': main() python-ase-3.9.1.4567/ase/db/__init__.py0000664000175000017500000000004012553425526017736 0ustar jensjjensj00000000000000from ase.db.core import connect python-ase-3.9.1.4567/ase/db/jsondb.py0000664000175000017500000001342012553425526017464 0ustar jensjjensj00000000000000from __future__ import absolute_import, print_function import os import numpy as np from ase.db.core import Database, ops, parallel, lock, now from ase.db.row import AtomsRow from ase.io.jsonio import encode, read_json from ase.parallel import world class JSONDatabase(Database): def __enter__(self): return self def __exit__(self, exc_type, exc_value, tb): pass def _write(self, atoms, key_value_pairs, data): Database._write(self, atoms, key_value_pairs, data) bigdct = {} ids = [] nextid = 1 if isinstance(self.filename, str) and os.path.isfile(self.filename): try: bigdct, ids, nextid = self._read_json() except (SyntaxError, ValueError): pass if isinstance(atoms, AtomsRow): row = atoms unique_id = row.unique_id for id in ids: if bigdct[id]['unique_id'] == unique_id: break else: id = None mtime = now() else: row = AtomsRow(atoms) row.ctime = mtime = now() row.user = os.getenv('USER') id = None dct = {} for key in row.__dict__: if key[0] == '_' or key in row._keys or key == 'id': continue dct[key] = row[key] dct['mtime'] = mtime kvp = key_value_pairs or row.key_value_pairs if kvp: dct['key_value_pairs'] = kvp data = data or row.get('data') if data: dct['data'] = data constraints = row.get('constraints') if constraints: dct['constraints'] = constraints if id is None: id = nextid ids.append(id) nextid += 1 bigdct[id] = dct self._write_json(bigdct, ids, nextid) return id def _read_json(self): bigdct = read_json(self.filename) ids = bigdct['ids'] if not isinstance(ids, list): ids = ids.tolist() return bigdct, ids, bigdct['nextid'] def _write_json(self, bigdct, ids, nextid): if world.rank > 0: return if isinstance(self.filename, str): fd = open(self.filename, 'w') else: fd = self.filename print('{', end='', file=fd) for id in ids: dct = bigdct[id] txt = ',\n '.join('"{0}": {1}'.format(key, encode(dct[key])) for key in sorted(dct.keys())) print('"{0}": {{\n {1}}},'.format(id, txt), file=fd) print('"ids": {0},'.format(ids), file=fd) print('"nextid": {0}}}'.format(nextid), file=fd) if fd is not self.filename: fd.close() @parallel @lock def delete(self, ids): bigdct, myids, nextid = self._read_json() for id in ids: del bigdct[id] myids.remove(id) self._write_json(bigdct, myids, nextid) def _get_row(self, id): bigdct, ids, nextid = self._read_json() if id is None: assert len(ids) == 1 id = ids[0] dct = bigdct[id] dct['id'] = id return AtomsRow(dct) def _select(self, keys, cmps, explain=False, verbosity=0, limit=None, offset=0, sort=None): if explain: yield {'explain': (0, 0, 0, 'scan table')} return if sort: if sort[0] == '-': reverse = True sort = sort[1:] else: reverse = False def f(row): return row[sort] rows = sorted(self._select(keys + [sort], cmps), key=f, reverse=reverse) if limit: rows = rows[offset:offset + limit] for row in rows: yield row return try: bigdct, ids, nextid = self._read_json() except IOError: return if not limit: limit = -offset - 1 cmps = [(key, ops[op], val) for key, op, val in cmps] n = 0 for id in ids: if n - offset == limit: return row = AtomsRow(bigdct[id]) row.id = id for key in keys: if key not in row: break else: for key, op, val in cmps: if isinstance(key, int): value = np.equal(row.numbers, key).sum() else: value = row.get(key) if key == 'pbc': assert op in [ops['='], ops['!=']] value = ''.join('FT'[x] for x in value) if value is None or not op(value, val): break else: if n >= offset: yield row n += 1 def _update(self, ids, delete_keys, add_key_value_pairs): bigdct, myids, nextid = self._read_json() t = now() m = 0 n = 0 for id in ids: dct = bigdct[id] kvp = dct.get('key_value_pairs', {}) n += len(kvp) for key in delete_keys: kvp.pop(key, None) n -= len(kvp) m -= len(kvp) kvp.update(add_key_value_pairs) m += len(kvp) if kvp: dct['key_value_pairs'] = kvp dct['mtime'] = t self._write_json(bigdct, myids, nextid) return m, n python-ase-3.9.1.4567/ase/db/cli.py0000664000175000017500000002400412553425526016754 0ustar jensjjensj00000000000000from __future__ import print_function import collections import optparse import sys from random import randint import ase.io from ase.db import connect from ase.db.core import convert_str_to_float_or_str from ase.db.summary import Summary from ase.db.table import Table, all_columns from ase.calculators.calculator import get_calculator from ase.utils import plural try: input = raw_input # Python 2+3 compatibility except NameError: pass description = """Selecton is a comma-separated list of selections where each selection is of the type "ID", "key" or "key=value". Instead of "=", one can also use "<", "<=", ">=", ">" and "!=" (these must be protected from the shell by using quotes). Special keys: id, user, calculator, age, natoms, energy, magmom, and charge. Chemical symbols can also be used to select number of specific atomic species (H, He, Li, ...).""" examples = ['calculator=nwchem', 'age<1d', 'natoms=1', 'user=alice', '2.2=10'] def main(args=sys.argv[1:]): if isinstance(args, str): args = args.split(' ') parser = optparse.OptionParser( usage='Usage: %prog db-name [selection] [options]', description=description, epilog='Selection examples: ' + ', '.join(examples) + '.') add = parser.add_option add('-v', '--verbose', action='store_true', default=False) add('-q', '--quiet', action='store_true', default=False) add('-n', '--count', action='store_true', help='Count number of selected rows.') add('-l', '--long', action='store_true', help='Long description of selected row') add('-i', '--insert-into', metavar='db-name', help='Insert selected rows into another database.') add('-a', '--add-from-file', metavar='[type:]filename', help='Add results from file.') add('-k', '--add-key-value-pairs', metavar='key1=val1,key2=val2,...', help='Add key-value pairs to selected rows. Values must be numbers ' 'or strings and keys must follow the same rules as keywords.') add('-L', '--limit', type=int, default=20, metavar='N', help='Show only first N rows (default is 20 rows). Use --limit=0 ' 'to show all.') add('--offset', type=int, default=0, metavar='N', help='Skip first N rows. By default, no rows are skipped') add('--delete', action='store_true', help='Delete selected rows.') add('--delete-keys', metavar='key1,key2,...', help='Delete keys for selected rows.') add('-y', '--yes', action='store_true', help='Say yes.') add('--explain', action='store_true', help='Explain query plan.') add('-c', '--columns', metavar='col1,col2,...', help='Specify columns to show. Precede the column specification ' 'with a "+" in order to add columns to the default set of columns. ' 'Precede by a "-" to remove columns. Use "++" for all.') add('-s', '--sort', metavar='column', default='id', help='Sort rows using column. Use -column for a descendin sort. ' 'Default is to sort after id.') add('--cut', type=int, default=35, help='Cut keywords and key-value ' 'columns after CUT characters. Use --cut=0 to disable cutting. ' 'Default is 35 characters') add('-p', '--plot', metavar='[a,b:]x,y1,y2,...', help='Example: "-p x,y": plot y row against x row. Use ' '"-p a:x,y" to make a plot for each value of a.') add('--csv', action='store_true', help='Write comma-separated-values file.') add('-w', '--open-web-browser', action='store_true', help='Open results in web-browser.') add('--no-lock-file', action='store_true', help="Don't use lock-files") add('--analyse', action='store_true', help='Gathers statistics about tables and indices to help make ' 'better query planning choices.') add('-j', '--json', action='store_true', help='Write json representation of selected row.') add('--unique', action='store_true', help='Give rows a new unique id when using --insert-into.') opts, args = parser.parse_args(args) if not args: parser.error('No database given') verbosity = 1 - opts.quiet + opts.verbose try: run(opts, args, verbosity) except Exception as x: if verbosity < 2: print('{0}: {1}'.format(x.__class__.__name__, x)) sys.exit(1) else: raise def run(opts, args, verbosity): filename = args.pop(0) query = ','.join(args) if query.isdigit(): query = int(query) add_key_value_pairs = {} if opts.add_key_value_pairs: for pair in opts.add_key_value_pairs.split(','): key, value = pair.split('=') add_key_value_pairs[key] = convert_str_to_float_or_str(value) if opts.delete_keys: delete_keys = opts.delete_keys.split(',') else: delete_keys = [] con = connect(filename, use_lock_file=not opts.no_lock_file) def out(*args): if verbosity > 0: print(*args) if opts.analyse: con.analyse() return if opts.add_from_file: filename = opts.add_from_file if ':' in filename: calculator_name, filename = filename.split(':') atoms = get_calculator(calculator_name)(filename).get_atoms() else: atoms = ase.io.read(filename) con.write(atoms, key_value_pairs=add_key_value_pairs) out('Added {0} from {1}'.format(atoms.get_chemical_formula(), filename)) return if opts.count: n = con.count(query) print('%s' % plural(n, 'row')) return if opts.explain: for dct in con.select(query, explain=True, verbosity=verbosity, limit=opts.limit, offset=opts.offset): print(dct['explain']) return if opts.insert_into: nkvp = 0 nrows = 0 with connect(opts.insert_into, use_lock_file=not opts.no_lock_file) as con2: for dct in con.select(query): kvp = dct.get('key_value_pairs', {}) nkvp -= len(kvp) kvp.update(add_key_value_pairs) nkvp += len(kvp) if opts.unique: dct['unique_id'] = '%x' % randint(16**31, 16**32 - 1) con2.write(dct, data=dct.get('data'), **kvp) nrows += 1 out('Added %s (%s updated)' % (plural(nkvp, 'key-value pair'), plural(len(add_key_value_pairs) * nrows - nkvp, 'pair'))) out('Inserted %s' % plural(nrows, 'row')) return if add_key_value_pairs or delete_keys: ids = [dct['id'] for dct in con.select(query)] m, n = con.update(ids, delete_keys, **add_key_value_pairs) out('Added %s (%s updated)' % (plural(m, 'key-value pair'), plural(len(add_key_value_pairs) * len(ids) - m, 'pair'))) out('Removed', plural(n, 'key-value pair')) return if opts.delete: ids = [dct['id'] for dct in con.select(query)] if ids and not opts.yes: msg = 'Delete %s? (yes/No): ' % plural(len(ids), 'row') if input(msg).lower() != 'yes': return con.delete(ids) out('Deleted %s' % plural(len(ids), 'row')) return if opts.plot: if ':' in opts.plot: tags, keys = opts.plot.split(':') tags = tags.split(',') else: tags = [] keys = opts.plot keys = keys.split(',') plots = collections.defaultdict(list) X = {} labels = [] for row in con.select(query, sort=opts.sort): name = ','.join(row[tag] for tag in tags) x = row.get(keys[0]) if x is not None: if isinstance(x, (unicode, str)): if x not in X: X[x] = len(X) labels.append(x) x = X[x] plots[name].append([x] + [row.get(key) for key in keys[1:]]) import matplotlib.pyplot as plt for name, plot in plots.items(): xyy = zip(*plot) x = xyy[0] for y, key in zip(xyy[1:], keys[1:]): plt.plot(x, y, label=name + key) if X: plt.xticks(range(len(labels)), labels, rotation=90) plt.legend() plt.show() return if opts.long: dct = con.get(query) summary = Summary(dct) summary.write() elif opts.json: dct = con.get(query) con2 = connect(sys.stdout, 'json', use_lock_file=False) kvp = dct.get('key_value_pairs', {}) con2.write(dct, data=dct.get('data'), **kvp) else: if opts.open_web_browser: import ase.db.app as app app.db = con app.app.run(host='0.0.0.0', debug=True) else: columns = list(all_columns) c = opts.columns if c and c.startswith('++'): keys = set() for row in con.select(query, limit=opts.limit, offset=opts.offset): keys.update(row._keys) columns.extend(keys) if c[2:3] == ',': c = c[3:] else: c = '' if c: if c[0] == '+': c = c[1:] elif c[0] != '-': columns = [] for col in c.split(','): if col[0] == '-': columns.remove(col[1:]) else: columns.append(col.lstrip('+')) table = Table(con, verbosity, opts.cut) table.select(query, columns, opts.sort, opts.limit, opts.offset) if opts.csv: table.write_csv() else: table.write(query) python-ase-3.9.1.4567/ase/db/sqlite.py0000664000175000017500000005074212553425526017516 0ustar jensjjensj00000000000000"""SQLite3 backend. Versions: 1) Added 3 more columns. 2) Changed "user" to "username". 3) Now adding keys to keyword table and added an "information" table containing a version number. 4) Got rid of keywords. 5) Add fmax, smax, mass, volume, charge """ from __future__ import absolute_import, print_function import os import sqlite3 import sys import numpy as np from ase.data import atomic_numbers from ase.db.row import AtomsRow from ase.db.core import Database, ops, now, lock, parallel, invop from ase.io.jsonio import encode, decode from ase.utils import basestring if sys.version >= '3': buffer = memoryview VERSION = 5 init_statements = [ """CREATE TABLE systems ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- ID's, timestamps and user name unique_id TEXT UNIQUE, ctime REAL, mtime REAL, username TEXT, numbers BLOB, -- stuff that defines an Atoms object positions BLOB, cell BLOB, pbc INTEGER, initial_magmoms BLOB, initial_charges BLOB, masses BLOB, tags BLOB, momenta BLOB, constraints TEXT, -- constraints and calculator calculator TEXT, calculator_parameters TEXT, energy REAL, -- calculated properties free_energy REAL, forces BLOB, stress BLOB, dipole BLOB, magmoms BLOB, magmom BLOB, charges BLOB, key_value_pairs TEXT, -- key-value pairs and data as json data TEXT, natoms INTEGER, -- stuff for making queries faster fmax REAL, smax REAL, volume REAL, mass REAL, charge REAL)""", """CREATE TABLE species ( Z INTEGER, n INTEGER, id INTEGER, FOREIGN KEY (id) REFERENCES systems(id))""", """CREATE TABLE keys ( key TEXT, id INTEGER, FOREIGN KEY (id) REFERENCES systems(id))""", """CREATE TABLE text_key_values ( key TEXT, value TEXT, id INTEGER, FOREIGN KEY (id) REFERENCES systems(id))""", """CREATE TABLE number_key_values ( key TEXT, value REAL, id INTEGER, FOREIGN KEY (id) REFERENCES systems(id))""", """CREATE TABLE information ( name TEXT, value TEXT)""", "INSERT INTO information VALUES ('version', '{0}')".format(VERSION)] index_statements = [ 'CREATE INDEX unique_id_index ON systems(unique_id)', 'CREATE INDEX ctime_index ON systems(ctime)', 'CREATE INDEX username_index ON systems(username)', 'CREATE INDEX calculator_index ON systems(calculator)', 'CREATE INDEX species_index ON species(Z)', 'CREATE INDEX key_index ON keys(key)', 'CREATE INDEX text_index ON text_key_values(key)', 'CREATE INDEX number_index ON number_key_values(key)'] all_tables = ['systems', 'species', 'keys', 'text_key_values', 'number_key_values'] def float_if_not_none(x): """Convert numpy.float64 to float - old db-interfaces need that.""" if x is not None: return float(x) class SQLite3Database(Database): initialized = False _allow_reading_old_format = False default = 'NULL' # used for autoincrement id connection = None version = None def _connect(self): return sqlite3.connect(self.filename, timeout=600) def __enter__(self): self.connection = self._connect() return self def __exit__(self, exc_type, exc_value, tb): if exc_type is None: self.connection.commit() else: self.connection.rollback() self.connection.close() self.connection = None def _initialize(self, con): if self.initialized: return cur = con.execute( 'SELECT COUNT(*) FROM sqlite_master WHERE name="systems"') if cur.fetchone()[0] == 0: for statement in init_statements: con.execute(statement) if self.create_indices: for statement in index_statements: con.execute(statement) con.commit() self.version = VERSION else: cur = con.execute( 'SELECT COUNT(*) FROM sqlite_master WHERE name="user_index"') if cur.fetchone()[0] == 1: # Old version with "user" instead of "username" column self.version = 1 else: try: cur = con.execute( 'SELECT value FROM information WHERE name="version"') except sqlite3.OperationalError: self.version = 2 else: self.version = int(cur.fetchone()[0]) if self.version < VERSION and not self._allow_reading_old_format: raise IOError('Please convert to new format. ' + 'Use: python -m ase.db.convert ' + self.filename) self.initialized = True def _write(self, atoms, key_value_pairs, data): Database._write(self, atoms, key_value_pairs, data) con = self.connection or self._connect() self._initialize(con) cur = con.cursor() id = None if not isinstance(atoms, AtomsRow): row = AtomsRow(atoms) row.ctime = mtime = now() row.user = os.getenv('USER') else: row = atoms cur.execute('SELECT id FROM systems WHERE unique_id=?', (row.unique_id,)) results = cur.fetchall() if results: id = results[0][0] self._delete(cur, [id], ['keys', 'text_key_values', 'number_key_values']) mtime = now() constraints = row._constraints if constraints: if isinstance(constraints, list): constraints = encode(constraints) else: constraints = None values = (row.unique_id, row.ctime, mtime, row.user, blob(row.numbers), blob(row.positions), blob(row.cell), int(np.dot(row.pbc, [1, 2, 4])), blob(row.get('initial_magmoms')), blob(row.get('initial_charges')), blob(row.get('masses')), blob(row.get('tags')), blob(row.get('momenta')), constraints) if 'calculator' in row: values += (row.calculator, encode(row.calculator_parameters)) else: values += (None, None) magmom = row.get('magmom') if magmom is not None: # magmom can be one or three numbers (non-collinear case) magmom = np.array(magmom) if not key_value_pairs: key_value_pairs = row.key_value_pairs if not data: data = row._data if not isinstance(data, basestring): data = encode(data) values += (row.get('energy'), row.get('free_energy'), blob(row.get('forces')), blob(row.get('stress')), blob(row.get('dipole')), blob(row.get('magmoms')), blob(magmom), blob(row.get('charges')), encode(key_value_pairs), data, len(row.numbers), float_if_not_none(row.get('fmax')), float_if_not_none(row.get('smax')), float(row.volume), float(row.mass), float(row.charge)) if id is None: q = self.default + ', ' + ', '.join('?' * len(values)) cur.execute('INSERT INTO systems VALUES ({0})'.format(q), values) else: q = ', '.join(line.split()[0].lstrip() + '=?' for line in init_statements[0].splitlines()[2:]) cur.execute('UPDATE systems SET {0} WHERE id=?'.format(q), values + (id,)) if id is None: id = self.get_last_id(cur) count = row.count_atoms() if count: species = [(atomic_numbers[symbol], n, id) for symbol, n in count.items()] cur.executemany('INSERT INTO species VALUES (?, ?, ?)', species) text_key_values = [] number_key_values = [] for key, value in key_value_pairs.items(): if isinstance(value, (float, int)): number_key_values.append([key, float(value), id]) else: assert isinstance(value, basestring) text_key_values.append([key, value, id]) cur.executemany('INSERT INTO text_key_values VALUES (?, ?, ?)', text_key_values) cur.executemany('INSERT INTO number_key_values VALUES (?, ?, ?)', number_key_values) cur.executemany('INSERT INTO keys VALUES (?, ?)', [(key, id) for key in key_value_pairs]) if self.connection is None: con.commit() con.close() return id def get_last_id(self, cur): cur.execute('SELECT seq FROM sqlite_sequence WHERE name="systems"') id = cur.fetchone()[0] return id def _get_row(self, id): con = self._connect() c = con.cursor() if id is None: c.execute('SELECT COUNT(*) FROM systems') assert c.fetchone()[0] == 1 c.execute('SELECT * FROM systems') else: c.execute('SELECT * FROM systems WHERE id=?', (id,)) values = c.fetchone() if self.version < VERSION: values = self._old2new(values) return self._convert_tuple_to_row(values) def _convert_tuple_to_row(self, values): dct = {'id': values[0], 'unique_id': values[1], 'ctime': values[2], 'mtime': values[3], 'user': values[4], 'numbers': deblob(values[5], np.int32), 'positions': deblob(values[6], shape=(-1, 3)), 'cell': deblob(values[7], shape=(3, 3)), 'pbc': (values[8] & np.array([1, 2, 4])).astype(bool)} if values[9] is not None: dct['initial_magmoms'] = deblob(values[9]) if values[10] is not None: dct['initial_charges'] = deblob(values[10]) if values[11] is not None: dct['masses'] = deblob(values[11]) if values[12] is not None: dct['tags'] = deblob(values[12], np.int32) if values[13] is not None: dct['momenta'] = deblob(values[13], shape=(-1, 3)) if values[14] is not None: dct['constraints'] = values[14] if values[15] is not None: dct['calculator'] = values[15] dct['calculator_parameters'] = values[16] if values[17] is not None: dct['energy'] = values[17] if values[18] is not None: dct['free_energy'] = values[18] if values[19] is not None: dct['forces'] = deblob(values[19], shape=(-1, 3)) if values[20] is not None: dct['stress'] = deblob(values[20]) if values[21] is not None: dct['dipole'] = deblob(values[21]) if values[22] is not None: dct['magmoms'] = deblob(values[22]) if values[23] is not None: dct['magmom'] = deblob(values[23])[0] if values[24] is not None: dct['charges'] = deblob(values[24]) if values[25] != '{}': dct['key_value_pairs'] = decode(values[25]) if values[26] != 'null': dct['data'] = values[26] return AtomsRow(dct) def _old2new(self, values): if self.version == 4: return values # should be ok for reading by convert.py script if len(values) == 26: extra = decode(values[25]) return values[:-1] + (encode(extra['key_value_pairs']), encode(extra['data'])) elif len(values) == 29: keywords = decode(values[-4]) kvp = decode(values[-3]) kvp.update(dict((keyword, 1) for keyword in keywords)) return values[:-4] + (encode(kvp),) + values[-2:] assert False def create_select_statement(self, keys, cmps, sort=None, order=None, sort_table=None, what='systems.*'): tables = ['systems'] where = [] args = [] for n, key in enumerate(keys): tables.append('keys AS keys{0}'.format(n)) where.append('systems.id=keys{0}.id AND keys{0}.key=?'.format(n)) args.append(key) # Special handling of "H=0" and "H<2" type of selections: bad = {} for key, op, value in cmps: if isinstance(key, int): bad[key] = bad.get(key, True) and ops[op](0, value) found_sort_table = False nspecies = 0 ntext = 0 nnumber = 0 for key, op, value in cmps: if key in ['id', 'energy', 'magmom', 'ctime', 'user', 'calculator', 'natoms', 'pbc', 'unique_id']: if key == 'user' and self.version >= 2: key = 'username' elif key == 'pbc': assert op in ['=', '!='] value = int(np.dot([x == 'T' for x in value], [1, 2, 4])) where.append('systems.{0}{1}?'.format(key, op)) args.append(value) elif isinstance(key, int): if bad[key]: where.append( 'NOT EXISTS (SELECT id FROM species WHERE\n' + ' species.id=systems.id AND species.Z==? AND ' + 'species.n{0}?)'.format(invop[op])) args += [key, value] else: tables.append('species AS specie{0}'.format(nspecies)) where.append(('systems.id=specie{0}.id AND ' + 'specie{0}.Z=? AND ' + 'specie{0}.n{1}?').format(nspecies, op)) args += [key, value] nspecies += 1 elif isinstance(value, basestring): tables.append('text_key_values AS text{0}'.format(ntext)) where.append(('systems.id=text{0}.id AND ' + 'text{0}.key=? AND ' + 'text{0}.value{1}?').format(ntext, op)) args += [key, value] if sort_table == 'text_key_values' and sort == key: sort_table = 'text{0}'.format(ntext) found_sort_table = True ntext += 1 else: tables.append('number_key_values AS number{0}'.format(nnumber)) where.append(('systems.id=number{0}.id AND ' + 'number{0}.key=? AND ' + 'number{0}.value{1}?').format(nnumber, op)) args += [key, float(value)] if sort_table == 'number_key_values' and sort == key: sort_table = 'number{0}'.format(nnumber) found_sort_table = True nnumber += 1 if sort: if sort_table == 'systems': if sort in ['energy', 'fmax', 'smax', 'calculator']: where.append('systems.{0} IS NOT NULL'.format(sort)) else: if not found_sort_table: tables.append('{0} AS sort_table'.format(sort_table)) where.append('systems.id=sort_table.id AND ' 'sort_table.key=?') args.append(sort) sort_table = 'sort_table' sort = 'value' sql = 'SELECT {0} FROM\n '.format(what) + ', '.join(tables) if where: sql += '\n WHERE\n ' + ' AND\n '.join(where) if sort: sql += '\nORDER BY {0}.{1} {2}'.format(sort_table, sort, order) return sql, args def _select(self, keys, cmps, explain=False, verbosity=0, limit=None, offset=0, sort=None): con = self._connect() self._initialize(con) if sort: if sort[0] == '-': order = 'DESC' sort = sort[1:] else: order = 'ASC' if sort in ['id', 'energy', 'username', 'calculator', 'ctime', 'mtime', 'magmom', 'pbc', 'fmax', 'smax', 'volume', 'mass', 'charge', 'natoms']: sort_table = 'systems' else: for dct in self._select(keys + [sort], cmps, limit=1): if isinstance(dct['key_value_pairs'][sort], basestring): sort_table = 'text_key_values' else: sort_table = 'number_key_values' break else: return else: order = None sort_table = None sql, args = self.create_select_statement(keys, cmps, sort, order, sort_table) if explain: sql = 'EXPLAIN QUERY PLAN ' + sql if limit: sql += '\nLIMIT {0}'.format(limit) if offset: sql += '\nOFFSET {0}'.format(offset) if verbosity == 2: print(sql, args) cur = con.cursor() cur.execute(sql, args) if explain: for row in cur.fetchall(): yield {'explain': row} else: for values in cur.fetchall(): yield self._convert_tuple_to_row(values) @parallel @lock def count(self, selection=None, **kwargs): keys, cmps = self.parse_selection(selection, **kwargs) sql, args = self.create_select_statement(keys, cmps, what='COUNT(*)') con = self._connect() self._initialize(con) cur = con.cursor() cur.execute(sql, args) return cur.fetchone()[0] def analyse(self): con = self._connect() self._initialize(con) con.execute('ANALYZE') def _update(self, ids, delete_keys, add_key_value_pairs): """Update row(s). ids: int or list of int ID's of rows to update. delete_keys: list of str Keys to remove. add_key_value_pairs: dict Key-value pairs to add. Returns number of key-value pairs added and keys removed. """ rows = [self._get_row(id) for id in ids] m = 0 n = 0 with self: for row in rows: kvp = row.key_value_pairs n += len(kvp) for key in delete_keys: kvp.pop(key, None) n -= len(kvp) m -= len(kvp) kvp.update(add_key_value_pairs) m += len(kvp) self._write(row, kvp, None) return m, n @parallel @lock def delete(self, ids): con = self._connect() self._delete(con.cursor(), ids) con.commit() con.close() def _delete(self, cur, ids, tables=None): tables = tables or all_tables[::-1] for table in tables: cur.executemany('DELETE FROM {0} WHERE id=?'.format(table), ((id,) for id in ids)) def blob(array): """Convert array to blob/buffer object.""" if array is None: return None if array.dtype == np.int64: array = array.astype(np.int32) return buffer(np.ascontiguousarray(array)) def deblob(buf, dtype=float, shape=None): """Convert blob/buffer object to ndarray of correct dtype and shape. (without creating an extra view).""" if buf is None: return None if len(buf) == 0: array = np.zeros(0, dtype) else: array = np.frombuffer(buf, dtype) if shape is not None: array.shape = shape return array if __name__ == '__main__': import sys from ase.db import connect con = connect(sys.argv[1]) con._initialize(con._connect()) print('Version:', con.version) python-ase-3.9.1.4567/ase/db/summary.py0000664000175000017500000001041612553425526017704 0ustar jensjjensj00000000000000from __future__ import print_function from ase.data import atomic_masses, chemical_symbols from ase.db.core import float_to_time_string, now from ase.utils import hill import numpy as np class Summary: def __init__(self, dct, subscript=None): self.dct = dct self.cell = [['{0:.3f}'.format(a) for a in axis] for axis in dct.cell] forces = dct.get('constrained_forces') if forces is None: fmax = None self.forces = None else: fmax = (forces**2).sum(1).max()**0.5 N = len(forces) self.forces = [] for n, f in enumerate(forces): if n < 5 or n >= N - 5: f = tuple('{0:10.3f}'.format(x) for x in f) symbol = chemical_symbols[dct.numbers[n]] self.forces.append((n, symbol) + f) elif n == 5: self.forces.append((' ...', '', ' ...', ' ...', ' ...')) self.stress = dct.get('stress') if self.stress is not None: self.stress = ', '.join('{0:.3f}'.format(s) for s in self.stress) if 'masses' in dct: mass = dct.masses.sum() else: mass = atomic_masses[dct.numbers].sum() formula = hill(dct.numbers) if subscript: formula = subscript.sub(r'\1', formula) table = [ ('id', '', dct.id), ('age', '', float_to_time_string(now() - dct.ctime, True)), ('formula', '', formula), ('user', '', dct.user), ('calculator', '', dct.get('calculator')), ('energy', 'eV', dct.get('energy')), ('fmax', 'eV/Ang', fmax), ('charge', '|e|', dct.get('charge')), ('mass', 'au', mass), ('magnetic moment', 'au', dct.get('magmom')), ('unique id', '', dct.unique_id), ('volume', 'Ang^3', abs(np.linalg.det(dct.cell)))] self.table = [(name, unit, value) for name, unit, value in table if value is not None] self.key_value_pairs = sorted(dct.key_value_pairs.items()) or None self.dipole = dct.get('dipole') if self.dipole is not None: self.dipole = ', '.join('{0:.3f}'.format(d) for d in self.dipole) self.data = dct.get('data') if self.data: self.data = ', '.join(self.data.keys()) self.constraints = dct.get('constraints') if self.constraints: self.constraints = ', '.join(d['name'] for d in self.constraints) def write(self): dct = self.dct width = max(len(name) for name, unit, value in self.table) print('{0:{width}}|unit |value'.format('name', width=width)) for name, unit, value in self.table: print('{0:{width}}|{1:6}|{2}'.format(name, unit, value, width=width)) print('\nUnit cell in Ang:') print('axis|periodic| x| y| z') c = 1 for p, axis in zip(dct.pbc, self.cell): print(' {0}| {1}|{2[0]:>11}|{2[1]:>11}|{2[2]:>11}'.format( c, [' no', 'yes'][p], axis)) c += 1 if self.key_value_pairs: print('\nKey-value pairs:') width = max(len(key) for key, value in self.key_value_pairs) for key, value in self.key_value_pairs: print('{0:{width}}|{1}'.format(key, value, width=width)) if self.forces: print('\nForces in ev/Ang:') for f in self.forces: print('{0:4}|{1:2}|{2}|{3}|{4}'.format(*f)) if self.stress: print('\nStress tensor (xx, yy, zz, zy, zx, yx) in eV/Ang^3:') print(' ', self.stress) if self.dipole: print('\nDipole moment in e*Ang: ({0})'.format(self.dipole)) if self.constraints: print('\nConstraints:', self.constraints) if self.data: print('\nData:', self.data) python-ase-3.9.1.4567/ase/db/row.py0000664000175000017500000001543212553425526017021 0ustar jensjjensj00000000000000from random import randint import numpy as np from ase import Atoms from ase.constraints import dict2constraint from ase.calculators.calculator import get_calculator, all_properties from ase.calculators.singlepoint import SinglePointCalculator from ase.data import chemical_symbols, atomic_masses from ase.io.jsonio import decode from ase.utils import hill class FancyDict(dict): """Dictionary with keys available as attributes also.""" def __getattr__(self, key): if key not in self: return dict.__getattribute__(self, key) value = self[key] if isinstance(value, dict): return FancyDict(value) return value def __dir__(self): return self.keys() # for tab-completion def atoms2dict(atoms): dct = { 'numbers': atoms.numbers, 'pbc': atoms.pbc, 'cell': atoms.cell, 'positions': atoms.positions, 'unique_id': '%x' % randint(16**31, 16**32 - 1)} if atoms.has('magmoms'): dct['initial_magmoms'] = atoms.get_initial_magnetic_moments() if atoms.has('charges'): dct['initial_charges'] = atoms.get_initial_charges() if atoms.has('masses'): dct['masses'] = atoms.get_masses() if atoms.has('tags'): dct['tags'] = atoms.get_tags() if atoms.has('momenta'): dct['momenta'] = atoms.get_momenta() if atoms.constraints: dct['constraints'] = [c.todict() for c in atoms.constraints] if atoms.calc is not None: dct['calculator'] = atoms.calc.name.lower() dct['calculator_parameters'] = atoms.calc.todict() if len(atoms.calc.check_state(atoms)) == 0: dct.update(atoms.calc.results) return dct class AtomsRow: def __init__(self, dct): if isinstance(dct, dict): dct = dct.copy() else: dct = atoms2dict(dct) self._constraints = dct.pop('constraints', []) self._data = dct.pop('data', None) kvp = dct.pop('key_value_pairs', {}) self._keys = list(kvp.keys()) self.__dict__.update(kvp) self.__dict__.update(dct) def __contains__(self, key): return key in self.__dict__ def __iter__(self): return (key for key in self.__dict__ if key[0] != '_') def get(self, key, default=None): """Return value of key if present or default if not.""" return getattr(self, key, default) @property def key_value_pairs(self): """Return dict of key-value pairs.""" return dict((key, self.get(key)) for key in self._keys) def count_atoms(self): """Count atoms. Return dict mapping chemical symbol strings to number of atoms. """ count = {} for symbol in self.symbols: count[symbol] = count.get(symbol, 0) + 1 return count def __getitem__(self, key): return getattr(self, key) def __setitem__(self, key, value): setattr(self, key, value) @property def constraints(self): """List of constraints.""" if not isinstance(self._constraints, list): # Lazy decoding: cs = decode(self._constraints) self._constraints = [] for c in cs: # Convert to new format: name = c.pop('__name__', None) if name: c = {'name': name, 'kwargs': c} if c['name'].startswith('ase'): c['name'] = c['name'].rsplit('.', 1)[1] self._constraints.append(c) return [dict2constraint(d) for d in self._constraints] @property def data(self): """Data dict.""" if self._data is None: raise AttributeError if not isinstance(self._data, dict): self._data = decode(self._data) # lazy decoding return FancyDict(self._data) @property def natoms(self): """Number of atoms.""" return len(self.numbers) @property def formula(self): """Chemical formula string.""" return hill(self.numbers) @property def symbols(self): """List of chemical symbols.""" return [chemical_symbols[Z] for Z in self.numbers] @property def fmax(self): """Maximum atomic force.""" forces = self.constrained_forces return (forces**2).sum(1).max()**0.5 @property def constrained_forces(self): """Forces after applying constraints.""" forces = self.forces constraints = self.constraints if constraints: forces = forces.copy() for constraint in constraints: constraint.adjust_forces(self.positions, forces) return forces @property def smax(self): """Maximum stress tensor component.""" return (self.stress**2).max()**0.5 @property def mass(self): """Total mass.""" if 'masses' in self: return self.masses.sum() return atomic_masses[self.numbers].sum() @property def volume(self): """Volume of unit cell.""" return abs(np.linalg.det(self.cell)) @property def charge(self): """Total charge.""" charges = self.get('inital_charges') if charges is None: return 0.0 return charges.sum() def toatoms(self, attach_calculator=False, add_additional_information=False): """Create Atoms object.""" atoms = Atoms(self.numbers, self.positions, cell=self.cell, pbc=self.pbc, magmoms=self.get('initial_magmoms'), charges=self.get('initial_charges'), tags=self.get('tags'), masses=self.get('masses'), momenta=self.get('momenta'), constraint=self.constraints) if attach_calculator: params = decode(self.get('calculator_parameters', '{}')) atoms.calc = get_calculator(self.calculator)(**params) else: results = {} for prop in all_properties: if prop in self: results[prop] = self[prop] if results: atoms.calc = SinglePointCalculator(atoms, **results) atoms.calc.name = self.calculator if add_additional_information: atoms.info = {} atoms.info['unique_id'] = self.unique_id if self._keys: atoms.info['key_value_pairs'] = self.key_value_pairs data = self.get('data') if data: atoms.info['data'] = data return atoms python-ase-3.9.1.4567/ase/db/core.py0000664000175000017500000003551612553425526017147 0ustar jensjjensj00000000000000import collections import functools import operator import os import re from time import time from ase.atoms import Atoms, symbols2numbers from ase.calculators.calculator import all_properties, all_changes from ase.data import atomic_numbers from ase.parallel import world, broadcast, DummyMPI from ase.utils import Lock, basestring T2000 = 946681200.0 # January 1. 2000 YEAR = 31557600.0 # 365.25 days def now(): """Return time since January 1. 2000 in years.""" return (time() - T2000) / YEAR seconds = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400, 'w': 604800, 'M': 2629800, 'y': YEAR} longwords = {'s': 'second', 'm': 'minute', 'h': 'hour', 'd': 'day', 'w': 'week', 'M': 'month', 'y': 'year'} ops = {'<': operator.lt, '<=': operator.le, '=': operator.eq, '>=': operator.ge, '>': operator.gt, '!=': operator.ne} invop = {'<': '>=', '<=': '>', '>=': '<', '>': '<=', '=': '!=', '!=': '='} word = re.compile('[_a-zA-Z][_0-9a-zA-Z]*$') reserved_keys = set(all_properties + all_changes + ['id', 'unique_id', 'ctime', 'mtime', 'user', 'momenta', 'constraints', 'calculator', 'calculator_parameters', 'key_value_pairs', 'data']) numeric_keys = set(['id', 'energy', 'magmom', 'charge', 'natoms']) def check(key_value_pairs): for key, value in key_value_pairs.items(): if not word.match(key) or key in reserved_keys: raise ValueError('Bad key: {0}'.format(key)) if not isinstance(value, (int, float, basestring)): raise ValueError('Bad value: {0}'.format(value)) def connect(name, type='extract_from_name', create_indices=True, use_lock_file=True, append=True): """Create connection to database. name: str Filename or address of database. type: str One of 'json', 'db', 'postgresql', 'mysql' (JSON, SQLite, PostgreSQL, MySQL/MariaDB). Default is 'extract_from_name', which will ... guess the type from the name. use_lock_file: bool You can turn this off if you know what you are doing ... append: bool Use append=False to start a new database. """ if type == 'extract_from_name': if name is None: type = None elif name.startswith('pg://'): type = 'postgresql' else: type = os.path.splitext(name)[1][1:] if type is None: return Database() if not append and world.rank == 0 and os.path.isfile(name): os.remove(name) if type == 'json': from ase.db.jsondb import JSONDatabase return JSONDatabase(name, use_lock_file=use_lock_file) if type == 'db': from ase.db.sqlite import SQLite3Database return SQLite3Database(name, create_indices, use_lock_file) if type == 'postgresql': from ase.db.postgresql import PostgreSQLDatabase return PostgreSQLDatabase(name[5:]) raise ValueError('Unknown database type: ' + type) def lock(method): """Decorator for using a lock-file.""" @functools.wraps(method) def new_method(self, *args, **kwargs): if self.lock is None: return method(self, *args, **kwargs) else: with self.lock: return method(self, *args, **kwargs) return new_method def parallel(method): """Decorator for broadcasting from master to slaves using MPI.""" if world.size == 1: return method @functools.wraps(method) def new_method(*args, **kwargs): ex = None result = None if world.rank == 0: try: result = method(*args, **kwargs) except Exception as ex: pass ex, result = broadcast((ex, result)) if ex is not None: raise ex return result return new_method def parallel_generator(generator): """Decorator for broadcasting yields from master to slaves using MPI.""" if world.size == 1: return generator @functools.wraps(generator) def new_generator(*args, **kwargs): if world.rank == 0: for result in generator(*args, **kwargs): result = broadcast(result) yield result broadcast(None) else: result = broadcast(None) while result is not None: yield result result = broadcast(None) return new_generator def convert_str_to_float_or_str(value): """Safe eval()""" try: value = float(value) except ValueError: value = {'True': 1.0, 'False': 0.0}.get(value, value) return value class Database: """Base class for all databases.""" def __init__(self, filename=None, create_indices=True, use_lock_file=False): if isinstance(filename, str): filename = os.path.expanduser(filename) self.filename = filename self.create_indices = create_indices if use_lock_file and isinstance(filename, str): self.lock = Lock(filename + '.lock', world=DummyMPI()) else: self.lock = None @parallel @lock def write(self, atoms, key_value_pairs={}, data={}, **kwargs): """Write atoms to database with key-value pairs. atoms: Atoms object Write atomic numbers, positions, unit cell and boundary conditions. If a calculator is attached, write also already calculated properties such as the energy and forces. key_value_pairs: dict Dictionary of key-value pairs. Values must be strings or numbers. data: dict Extra stuff (not for searching). Key-value pairs can also be set using keyword arguments:: connection.write(atoms, name='ABC', frequency=42.0) Returns integer id of the new row. """ if atoms is None: atoms = Atoms() kvp = dict(key_value_pairs) # modify a copy kvp.update(kwargs) id = self._write(atoms, kvp, data) return id def _write(self, atoms, key_value_pairs, data): check(key_value_pairs) return 1 @parallel @lock def reserve(self, **key_value_pairs): """Write empty row if not already present. Usage:: id = conn.reserve(key1=value1, key2=value2, ...) Write an empty row with the given key-value pairs and return the integer id. If such a row already exists, don't write anything and return None. """ for dct in self._select([], [(key, '=', value) for key, value in key_value_pairs.items()]): return None atoms = Atoms() calc_name = key_value_pairs.pop('calculator', None) if calc_name: # Allow use of calculator key assert calc_name.lower() == calc_name # Fake calculator class: class Fake: name = calc_name def todict(self): return {} def check_state(self, atoms): return ['positions'] atoms.calc = Fake() id = self._write(atoms, key_value_pairs, {}) return id def __delitem__(self, id): self.delete([id]) def get_atoms(self, selection=None, attach_calculator=False, add_additional_information=False, **kwargs): """Get Atoms object. selection: int, str or list See the select() method. attach_calculator: bool Attach calculator object to Atoms object (default value is False). add_additional_information: bool Put key-value pairs and data into Atoms.info dictionary. In addition, one can use keyword arguments to select specific key-value pairs. """ row = self.get(selection, **kwargs) return row.toatoms(attach_calculator, add_additional_information) def __getitem__(self, selection): return self.get(selection) def get(self, selection=None, **kwargs): """Select a single row and return it as a dictionary. selection: int, str or list See the select() method. fancy: bool return fancy dictionary with keys as attributes (this is the default). """ rows = list(self.select(selection, limit=2, **kwargs)) if not rows: raise KeyError('no match') assert len(rows) == 1, 'more than one row matched' return rows[0] def parse_selection(self, selection, **kwargs): if selection is None or selection == '': expressions = [] elif isinstance(selection, int): expressions = [('id', '=', selection)] elif isinstance(selection, list): expressions = selection else: expressions = [w.strip() for w in selection.split(',')] keys = [] comparisons = [] for expression in expressions: if isinstance(expression, (list, tuple)): comparisons.append(expression) continue if expression.count('<') == 2: value, expression = expression.split('<', 1) if expression[0] == '=': op = '>=' expression = expression[1:] else: op = '>' key = expression.split('<', 1)[0] comparisons.append((key, op, value)) for op in ['!=', '<=', '>=', '<', '>', '=']: if op in expression: break else: if expression in atomic_numbers: comparisons.append((expression, '>', 0)) else: keys.append(expression) continue key, value = expression.split(op) comparisons.append((key, op, value)) cmps = [] for key, value in kwargs.items(): comparisons.append((key, '=', value)) for key, op, value in comparisons: if key == 'age': key = 'ctime' op = invop[op] value = now() - time_string_to_float(value) elif key == 'formula': assert op == '=' numbers = symbols2numbers(value) count = collections.defaultdict(int) for Z in numbers: count[Z] += 1 cmps.extend((Z, '=', count[Z]) for Z in count) key = 'natoms' value = len(numbers) elif key in atomic_numbers: key = atomic_numbers[key] value = int(value) elif isinstance(value, basestring): value = convert_str_to_float_or_str(value) if key in numeric_keys and not isinstance(value, (int, float)): msg = 'Wrong type for "{0}{1}{2}" - must be a number' raise ValueError(msg.format(key, op, value)) cmps.append((key, op, value)) return keys, cmps @parallel_generator def select(self, selection=None, filter=None, explain=False, verbosity=1, limit=None, offset=0, sort=None, **kwargs): """Select rows. Return AtomsRow iterator with results. Selection is done using key-value pairs and the special keys: formula, age, user, calculator, natoms, energy, magmom and/or charge. selection: int, str or list Can be: * an integer id * a string like 'key=value', where '=' can also be one of '<=', '<', '>', '>=' or '!='. * a string like 'key' * comma separated strings like 'key1 5: break if long: return '{0:.3f} {1}s'.format(x, longwords[s]) else: return '{0:.0f}{1}'.format(round(x), s) python-ase-3.9.1.4567/ase/db/app.py0000664000175000017500000001670112553425526016772 0ustar jensjjensj00000000000000"""WSGI Flask-app for browsing a database. You can launch Flask's local webserver like this:: $ ase-db abc.db -w For a real webserver, you need to set the $ASE_DB_APP_CONFIG environment variable to point to a configuration file like this:: ASE_DB_NAME = '/path/to/db-file/abc.db' ASE_DB_HOMEPAGE = 'HOME ::' Start with something like:: twistd web --wsgi=ase.db.app.app --port=8000 """ import collections import functools import io import os import re import tempfile from flask import Flask, render_template, request, send_from_directory import ase.db from ase.db.summary import Summary from ase.db.table import Table, all_columns from ase.io.png import write_png from ase.visualize import view # Every client-connetions gets one of these tuples: Connection = collections.namedtuple( 'Connection', ['query', # query string 'nrows', # number of rows matched 'page', # page number 'columns', # what columns to show 'sort', # what column to sort after 'limit', # number of rows per page 'opened' # list of id's in the table that are open ]) app = Flask(__name__) db = None home = '' # link to homepage open_ase_gui = True # click image to open ase-gui if 'ASE_DB_APP_CONFIG' in os.environ: app.config.from_envvar('ASE_DB_APP_CONFIG') db = ase.db.connect(app.config['ASE_DB_NAME']) home = app.config['ASE_DB_HOMEPAGE'] open_ase_gui = False next_con_id = 1 connections = {} tmpdir = tempfile.mkdtemp() # used to cache png-files # Find numbers in formulas so that we can convert H2O to H2O: SUBSCRIPT = re.compile(r'(\d+)') @app.route('/') def index(): global next_con_id con_id = int(request.args.get('x', '0')) if con_id not in connections: con_id = next_con_id next_con_id += 1 query = '' columns = list(all_columns) sort = 'id' limit = 25 opened = set() nrows = None page = 0 else: query, nrows, page, columns, sort, limit, opened = connections[con_id] if 'sort' in request.args: column = request.args['sort'] if column == sort: sort = '-' + column elif '-' + column == sort: sort = 'id' else: sort = column page = 0 elif 'query' in request.args: query = request.args['query'].encode() try: limit = max(1, min(int(request.args.get('limit', limit)), 200)) except ValueError: pass sort = 'id' opened = set() page = 0 nrows = None elif 'page' in request.args: page = int(request.args['page']) if 'toggle' in request.args: tcolumns = request.args['toggle'].split(',') if tcolumns == ['reset']: columns = list(all_columns) else: for column in tcolumns: if column in columns: columns.remove(column) if column == sort.lstrip('-'): sort = 'id' page = 0 else: columns.append(column) if nrows is None: nrows = db.count(query) table = Table(db) table.select(query, columns, sort, limit, offset=page * limit) con = Connection(query, nrows, page, columns, sort, limit, opened) connections[con_id] = con table.format(SUBSCRIPT) addcolumns = [column for column in all_columns + table.keys if column not in table.columns] return render_template('table.html', t=table, con=con, cid=con_id, home=home, pages=pages(page, nrows, limit), nrows=nrows, addcolumns=addcolumns, row1=page * limit + 1, row2=min((page + 1) * limit, nrows)) @app.route('/open_row/') def open_row(id): con_id = int(request.args['x']) opened = connections[con_id].opened if id in opened: opened.remove(id) return '' opened.add(id) return render_template('more.html', dct=db.get(id), id=id, cid=con_id) @app.route('/image/') def image(name): path = os.path.join(tmpdir, name).encode() if not os.path.isfile(path): id = int(name[:-4]) atoms = db.get_atoms(id) if atoms: size = atoms.positions.ptp(0) i = size.argmin() rotation = ['-90y', '90x', ''][i] size[i] = 0.0 scale = min(20, 20 / size.max() * 10.0) else: scale = 20 rotation = '' write_png(path, atoms, show_unit_cell=1, rotation=rotation, scale=scale) return send_from_directory(tmpdir, name) @app.route('/gui/') def gui(id): if open_ase_gui: atoms = db.get_atoms(id) view(atoms) return '', 204, [] @app.route('/id/') def summary(id): s = Summary(db.get(id), SUBSCRIPT) return render_template('summary.html', s=s, home=home) def tofile(query, type, limit=0): fd, name = tempfile.mkstemp(suffix='.' + type) con = ase.db.connect(name, use_lock_file=False) for dct in db.select(query, limit=limit): con.write(dct, data=dct.get('data', {}), **dct.get('key_value_pairs', {})) os.close(fd) data = open(name).read() os.unlink(name) return data def download(f): @functools.wraps(f) def ff(*args, **kwargs): text, name = f(*args, **kwargs) headers = [('Content-Disposition', 'attachment; filename="{0}"'.format(name)), ] # ('Content-type', 'application/sqlite3')] return text, 200, headers return ff @app.route('/xyz/') @download def xyz(id): fd = io.BytesIO() from ase.io.xyz import write_xyz write_xyz(fd, db.get_atoms(id)) data = fd.getvalue() return data, '{0}.xyz'.format(id) @app.route('/json') @download def jsonall(): con_id = int(request.args['x']) con = connections[con_id] data = tofile(con.query, 'json', con.limit) return data, 'selection.json' @app.route('/json/') @download def json(id): data = tofile(id, 'json') return data, '{0}.json'.format(id) @app.route('/sqlite') @download def sqliteall(): con_id = int(request.args['x']) con = connections[con_id] data = tofile(con.query, 'db', con.limit) return data, 'selection.db' @app.route('/sqlite/') @download def sqlite(id): data = tofile(id, 'db') return data, '{0}.db'.format(id) @app.route('/robots.txt') def robots(): return 'User-agent: *\nDisallow: /\n', 200 def pages(page, nrows, limit): npages = (nrows + limit - 1) // limit p1 = min(5, npages) p2 = max(page - 4, p1) p3 = min(page + 5, npages) p4 = max(npages - 4, p3) pgs = list(range(p1)) if p1 < p2: pgs.append(-1) pgs += list(range(p2, p3)) if p3 < p4: pgs.append(-1) pgs += list(range(p4, npages)) pages = [(page - 1, 'previous')] for p in pgs: if p == -1: pages.append((-1, '...')) elif p == page: pages.append((-1, str(p + 1))) else: pages.append((p, str(p + 1))) nxt = min(page + 1, npages - 1) if nxt == page: nxt = -1 pages.append((nxt, 'next')) return pages python-ase-3.9.1.4567/ase/db/mysql.py0000664000175000017500000000575312553425526017364 0ustar jensjjensj00000000000000import MySQLdb from ase.db.sqlite import init_statements, index_statements from ase.db.sqlite import all_tables, SQLite3Database class Connection: def __init__(self, con): self.con = con def cursor(self): return Cursor(self.con.cursor()) def commit(self): self.con.commit() def close(self): self.con.close() class Cursor: def __init__(self, cur): self.cur = cur def fetchone(self): return self.cur.fetchone() def fetchall(self): return self.cur.fetchall() def execute(self, statement, *args): self.cur.execute(statement.replace('?', '%s'), *args) def executemany(self, statement, *args): self.cur.executemany(statement.replace('?', '%s'), *args) class MySQLDatabase(SQLite3Database): default = 'DEFAULT' def _connect(self): con = MySQLdb.connect(db='mysql', user='ase', passwd='ase') return Connection(con) def _initialize(self, con): pass def get_last_id(self, cur): cur.execute('select max(id) from systems') id = cur.fetchone()[0] return int(id) def reset(): db = 'mysql' con = MySQLdb.connect(db=db, user='root') cur = con.cursor() cur.execute("use " + db) cur.execute("show tables like 'systems'") if cur.fetchone() is not None: # order matters for drop (drop 'systems' last) for t in ['information'] + all_tables[::-1]: # MDTMP is information special? cur.execute("drop table %s.%s" % (db, t)) # avoid "Commands out of sync; you can't run this command now" # by closing the cursor after each execute cur.close() cur = con.cursor() cur.execute("drop user 'ase'@'localhost'") cur.execute("create user 'ase'@'localhost' identified by 'ase'") con.commit() # MySQL can grant privileges only for one table at a time? for t in all_tables[:] + ['information']: # MDTMP is information special? cur.execute("grant all privileges on %s.%s to 'ase'@'localhost'" % (db, t)) cur.close() cur = con.cursor() con.commit() for sql in init_statements: for a, b in [('BLOB', 'BLOB'), ('TEXT', 'VARCHAR(767)'), ('data VARCHAR(767)', 'data TEXT'), ('REAL', 'DOUBLE'), ('KEY AUTOINCREMENT', 'KEY AUTO_INCREMENT')]: sql = sql.replace(a, b) cur.execute(sql) cur.close() cur = con.cursor() for sql in index_statements: cur.execute(sql) cur.close() cur = con.cursor() con.commit() if __name__ == '__main__': # Debian # PYTHONPATH=/path/to/ase python -m ase.db.mysql # RHEL: # su -c "yum -y remove mariadb-server" # su -c "rm -rf /var/lib/mysql" # su -c "yum -y install mariadb-server" # su -c "systemctl start mariadb.service" # PYTHONPATH=/path/to/ase python -m ase.db.mysql reset() python-ase-3.9.1.4567/ase/db/table.py0000664000175000017500000001105312553425526017274 0ustar jensjjensj00000000000000from __future__ import print_function import numpy as np from ase.db.core import float_to_time_string, now all_columns = ['id', 'age', 'user', 'formula', 'calculator', 'energy', 'fmax', 'pbc', 'volume', 'charge', 'mass', 'smax', 'magmom'] def plural(n, word): if n == 1: return '1 ' + word return '%d %ss' % (n, word) def cut(txt, length): if len(txt) <= length or length == 0: return txt return txt[:length - 3] + '...' def cutlist(lst, length): if len(lst) <= length or length == 0: return lst return lst[:9] + ['... ({0} more)'.format(len(lst) - 9)] class Table: def __init__(self, connection, verbosity=1, cut=35): self.connection = connection self.verbosity = verbosity self.cut = cut self.rows = [] self.columns = None self.id = None self.right = None self.keys = None def select(self, query, columns, sort, limit, offset): self.limit = limit self.offset = offset self.rows = [Row(d, columns) for d in self.connection.select( query, verbosity=self.verbosity, limit=limit, offset=offset, sort=sort)] delete = set(range(len(columns))) for row in self.rows: for n in delete.copy(): if row.values[n] is not None: delete.remove(n) delete = sorted(delete, reverse=True) for row in self.rows: for n in delete: del row.values[n] self.columns = list(columns) for n in delete: del self.columns[n] def format(self, subscript=None): right = set() # right-adjust numbers allkeys = set() for row in self.rows: numbers = row.format(self.columns, subscript) right.update(numbers) allkeys.update(row.dct.get('key_value_pairs', {})) right.add('age') self.right = [column in right for column in self.columns] self.keys = sorted(allkeys) def write(self, query=None): self.format() L = [[len(s) for s in row.strings] for row in self.rows] L.append([len(c) for c in self.columns]) N = np.max(L, axis=0) fmt = '{0:{align}{width}}' print('|'.join(fmt.format(c, align='<>'[a], width=w) for c, a, w in zip(self.columns, self.right, N))) for row in self.rows: print('|'.join(fmt.format(c, align='<>'[a], width=w) for c, a, w in zip(row.strings, self.right, N))) if self.verbosity == 0: return nrows = len(self.rows) if self.limit and nrows == self.limit: n = self.connection.count(query) print('Rows:', n, '(showing first {0})'.format(self.limit)) else: print('Rows:', nrows) if self.keys: print('Keys:', ', '.join(cutlist(self.keys, self.cut))) def write_csv(self): print(', '.join(self.columns)) for row in self.rows: print(', '.join(str(val) for val in row.values)) class Row: def __init__(self, dct, columns): self.dct = dct self.values = None self.strings = None self.more = False self.set_columns(columns) def set_columns(self, columns): self.values = [] for c in columns: if c == 'age': value = float_to_time_string(now() - self.dct.ctime) elif c == 'pbc': value = ''.join('FT'[p] for p in self.dct.pbc) else: value = getattr(self.dct, c, None) self.values.append(value) def toggle(self): self.more = not self.more def format(self, columns, subscript=None): self.strings = [] numbers = set() for value, column in zip(self.values, columns): if column == 'formula' and subscript: value = subscript.sub(r'\1', value) elif isinstance(value, int): value = str(value) numbers.add(column) elif isinstance(value, float): numbers.add(column) value = '{0:.3f}'.format(value) elif value is None: value = '' self.strings.append(value) return numbers python-ase-3.9.1.4567/ase/db/postgresql.py0000664000175000017500000000666412553425526020424 0ustar jensjjensj00000000000000import sys import psycopg2 from ase.db.sqlite import init_statements, index_statements, VERSION from ase.db.sqlite import all_tables, SQLite3Database class Connection: def __init__(self, con): self.con = con def cursor(self): return Cursor(self.con.cursor()) def commit(self): self.con.commit() def close(self): self.con.close() class Cursor: def __init__(self, cur): self.cur = cur def fetchone(self): return self.cur.fetchone() def fetchall(self): return self.cur.fetchall() def execute(self, statement, *args): self.cur.execute(statement.replace('?', '%s'), *args) def executemany(self, statement, *args): self.cur.executemany(statement.replace('?', '%s'), *args) def parse_name(name): """Parse user:password@host:port string. Defaults are ase:ase@localhost:5432. Returns user, password, host, port. """ if '@' in name: user, host = name.split('@') else: user = 'ase' host = name if ':' in user: user, password = user.split(':') else: password = 'ase' if ':' in host: host, port = host.split(':') port = int(port) else: port = 5432 host = host or None return user, password, host, port class PostgreSQLDatabase(SQLite3Database): default = 'DEFAULT' def _connect(self): user, password, host, port = parse_name(self.filename) if host == 'localhost': host = None con = psycopg2.connect(database='postgres', user=user, password=password, host=host, port=port) return Connection(con) def _initialize(self, con): self.version = VERSION def get_last_id(self, cur): cur.execute('SELECT last_value FROM systems_id_seq') id = cur.fetchone()[0] return int(id) def reset(): con = psycopg2.connect(database='postgres', user='postgres') cur = con.cursor() cur.execute("SELECT COUNT(*) FROM pg_tables WHERE tablename='systems'") if cur.fetchone()[0] == 1: cur.execute('DROP TABLE %s CASCADE' % ', '.join(all_tables)) cur.execute('DROP TABLE information CASCADE') cur.execute('DROP ROLE ase') if len(sys.argv) == 2: pw = sys.argv[1] else: pw = 'ase' cur.execute("CREATE ROLE ase LOGIN PASSWORD %s", (pw,)) con.commit() sql = ';\n'.join(init_statements) for a, b in [('BLOB', 'BYTEA'), ('REAL', 'DOUBLE PRECISION'), ('INTEGER PRIMARY KEY AUTOINCREMENT', 'SERIAL PRIMARY KEY')]: sql = sql.replace(a, b) cur.execute(sql) cur.execute(';\n'.join(index_statements)) cur.execute('GRANT ALL PRIVILEGES ON %s TO ase' % ', '.join(all_tables + ['systems_id_seq'])) con.commit() if __name__ == '__main__': # Debian # sudo -u postgres PYTHONPATH=/path/to/ase python -m ase.db.postgresql # RHEL: # su -c "yum -y remove postgresql-server" # su -c "rm -rf /var/lib/pgsql" # su -c "yum -y install postgresql-server authd" # su -c "postgresql-setup initdb" # su -c "systemctl start auth.socket" # su -c "systemctl start postgresql.service" # su - # su - postgres # psql -d postgres -U postgres -c "create role ase login password 'ase';" # PYTHONPATH=/path/to/ase python -m ase.db.postgresql reset() python-ase-3.9.1.4567/ase/constraints.py0000664000175000017500000013105112553425527020171 0ustar jensjjensj00000000000000from math import sqrt from ase.utils.geometry import find_mic import numpy as np __all__ = ['FixCartesian', 'FixBondLength', 'FixedMode', 'FixConstraintSingle', 'FixAtoms', 'UnitCellFilter', 'FixScaled', 'StrainFilter', 'FixedPlane', 'Filter', 'FixConstraint', 'FixedLine', 'FixBondLengths', 'FixInternals', 'Hookean'] def dict2constraint(dct): if dct['name'] not in __all__: raise ValueError return globals()[dct['name']](**dct['kwargs']) def slice2enlist(s, n): """Convert a slice object into a list of (new, old) tuples.""" if isinstance(s, (list, tuple)): return enumerate(s) return enumerate(range(*s.indices(n))) class FixConstraint: """Base class for classes that fix one or more atoms in some way.""" def index_shuffle(self, atoms, 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. """ msg = ("Repeat is not compatible with your atoms' constraints." ' Use atoms.set_constraint() before calling repeat to ' 'remove your constraints.') raise NotImplementedError(msg) def adjust_momenta(self, atoms, momenta): """Adjusts momenta in identical manner to forces.""" self.adjust_forces(atoms, momenta) def copy(self): return dict2constraint(self.todict().copy()) class FixConstraintSingle(FixConstraint): """Base class for classes that fix a single atom.""" def index_shuffle(self, atoms, ind): """The atom index must be stored as self.a.""" newa = -1 # Signal error for new, old in slice2enlist(ind, len(atoms)): 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: >>> mask = [s == 'Cu' for s in atoms.get_chemical_symbols()] >>> c = FixAtoms(mask=mask) >>> 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, atoms, new): new[self.index] = atoms.positions[self.index] def adjust_forces(self, atoms, forces): forces[self.index] = 0.0 def index_shuffle(self, atoms, ind): # See docstring of superclass if self.index.dtype == bool: self.index = self.index[ind] else: index = [] for new, old in slice2enlist(ind, len(atoms)): 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 __repr__(self): if self.index.dtype == bool: return 'FixAtoms(mask=%s)' % ints2string(self.index.astype(int)) return 'FixAtoms(indices=%s)' % ints2string(self.index) def todict(self): dct = {'name': 'FixAtoms'} if self.index.dtype == bool: dct['kwargs'] = {'mask': self.index} else: dct['kwargs'] = {'indices': self.index} return dct def repeat(self, m, n): i0 = 0 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, atoms, new): for i in range(self.iterations): for constraint in self.constraints: constraint.adjust_positions(atoms, new) def adjust_forces(self, atoms, forces): for i in range(self.iterations): for constraint in self.constraints: constraint.adjust_forces(atoms, forces) def todict(self): return {'name': 'FixBondLengths', 'kwargs': {'pairs': [constraint.indices for constraint in self.constraints], 'iterations': self.iterations}} class FixBondLength(FixConstraint): """Constraint object for fixing a bond length.""" def __init__(self, a1, a2): """Fix distance between atoms with indices a1 and a2. If mic is True, follows the minimum image convention to keep constant the shortest distance between a1 and a2 in any periodic direction. atoms only needs to be supplied if mic=True. """ self.indices = [a1, a2] self.constraint_force = None def adjust_positions(self, atoms, new): p1, p2 = atoms.positions[self.indices] d, p = find_mic(np.array([p2 - p1]), atoms._cell, atoms._pbc) q1, q2 = new[self.indices] d, q = find_mic(np.array([q2 - q1]), atoms._cell, atoms._pbc) d *= 0.5 * (p - q) / q new[self.indices] = (q1 - d[0], q2 + d[0]) def adjust_forces(self, atoms, forces): d = np.subtract.reduce(atoms.positions[self.indices]) d, p = find_mic(np.array([d]), atoms._cell, atoms._pbc) d = d[0] d *= 0.5 * np.dot(np.subtract.reduce(forces[self.indices]), d) / p**2 self.constraint_force = d forces[self.indices] += (-d, d) def index_shuffle(self, atoms, ind): """Shuffle the indices of the two atoms in this constraint""" newa = [-1, -1] # Signal error for new, old in slice2enlist(ind, len(atoms)): 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 get_constraint_force(self): return self.constraint_force def __repr__(self): return 'FixBondLength(%d, %d)' % tuple(self.indices) def todict(self): return {'name': 'FixBondLength', 'kwargs': {'a1': self.indices[0], 'a2': self.indices[1]}} class FixedMode(FixConstraint): """Constrain atoms to move along directions orthogonal to a given mode only.""" def __init__(self, mode): self.mode = (np.asarray(mode) / np.sqrt((mode**2).sum())).reshape(-1) def adjust_positions(self, atoms, newpositions): newpositions = newpositions.ravel() oldpositions = atoms.positions.ravel() step = newpositions - oldpositions newpositions -= self.mode * np.dot(step, self.mode) def adjust_forces(self, atoms, forces): forces = forces.ravel() forces -= self.mode * np.dot(forces, self.mode) def index_shuffle(self, atoms, ind): eps = 1e-12 mode = self.mode.reshape(-1, 3) excluded = np.ones(len(mode), dtype=bool) excluded[ind] = False if (abs(mode[excluded]) > eps).any(): raise IndexError('All nonzero parts of mode not in slice') self.mode = mode[ind].ravel() def todict(self): return {'name': 'FixedMode', 'kwargs': {'mode': self.mode}} def __repr__(self): return 'FixedMode(%s)' % self.mode.tolist() class FixedPlane(FixConstraintSingle): """Constrain an atom index *a* to move in a given plane only. The plane is defined by its normal vector *direction*.""" def __init__(self, a, direction): self.a = a self.dir = np.asarray(direction) / sqrt(np.dot(direction, direction)) def adjust_positions(self, atoms, newpositions): step = newpositions[self.a] - atoms.positions[self.a] newpositions[self.a] -= self.dir * np.dot(step, self.dir) def adjust_forces(self, atoms, forces): forces[self.a] -= self.dir * np.dot(forces[self.a], self.dir) def todict(self): return {'name': 'FixedPlane', 'kwargs': {'a': self.a, 'direction': self.dir}} def __repr__(self): return 'FixedPlane(%d, %s)' % (self.a, self.dir.tolist()) class FixedLine(FixConstraintSingle): """Constrain an atom index *a* to move on a given line only. The line is defined by its vector *direction*.""" def __init__(self, a, direction): self.a = a self.dir = np.asarray(direction) / sqrt(np.dot(direction, direction)) def adjust_positions(self, atoms, newpositions): step = newpositions[self.a] - atoms.positions[self.a] x = np.dot(step, self.dir) newpositions[self.a] = atoms.positions[self.a] + x * self.dir def adjust_forces(self, atoms, forces): forces[self.a] = self.dir * np.dot(forces[self.a], self.dir) def __repr__(self): return 'FixedLine(%d, %s)' % (self.a, self.dir.tolist()) def todict(self): return {'name': 'FixedLine', 'kwargs': {'a': self.a, 'direction': self.dir}} class FixCartesian(FixConstraintSingle): 'Fix an atom index *a* 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, atoms, new): step = new[self.a] - atoms.positions[self.a] step *= self.mask new[self.a] = atoms.positions[self.a] + step def adjust_forces(self, atoms, forces): forces[self.a] *= self.mask def __repr__(self): return 'FixCartesian(indice=%s mask=%s)' % (self.a, self.mask) class FixScaled(FixConstraintSingle): 'Fix an atom index *a* 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, atoms, new): scaled_old = np.linalg.solve(self.cell.T, atoms.positions.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, atoms, 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 todict(self): return {'name': 'FixScaled', 'kwargs': {'a': self.a, 'cell': self.cell, 'mask': self.mask}} def __repr__(self): return 'FixScaled(%s, %d, %s)' % (repr(self.cell), self.a, repr(self.mask)) # TODO: Better interface might be to use dictionaries in place of very # nested lists/tuples class FixInternals(FixConstraint): """Constraint object for fixing multiple internal coordinates. Allows fixing bonds, angles, and dihedrals.""" def __init__(self, bonds=None, angles=None, dihedrals=None, epsilon=1.e-7): self.bonds = bonds or [] self.angles = angles or [] self.dihedrals = dihedrals or [] # Initialize these at run-time: self.n = 0 self.constraints = [] self.epsilon = epsilon self.initialized = False def initialize(self, atoms): if self.initialized: return masses = atoms.get_masses() self.n = len(self.bonds) + len(self.angles) + len(self.dihedrals) self.constraints = [] for bond in self.bonds: masses_bond = masses.take(bond[1]) self.constraints.append(self.FixBondLengthAlt(bond[0], bond[1], masses_bond)) for angle in self.angles: masses_angle = masses.take(angle[1]) self.constraints.append(self.FixAngle(angle[0], angle[1], masses_angle)) for dihedral in self.dihedrals: masses_dihedral = masses.take(dihedral[1]) self.constraints.append(self.FixDihedral(dihedral[0], dihedral[1], masses_dihedral)) self.initialized = True def todict(self): return {'name': 'FixInternals', 'kwargs': {'bonds': self.bonds, 'angles': self.angles, 'dihedrals': self.dihedrals, 'epsilon': self.epsilon}} def adjust_positions(self, atoms, new): self.initialize(atoms) for constraint in self.constraints: constraint.set_h_vectors(atoms.positions) for j in range(50): maxerr = 0.0 for constraint in self.constraints: constraint.adjust_positions(atoms.positions, new) maxerr = max(abs(constraint.sigma), maxerr) if maxerr < self.epsilon: return raise ValueError('Shake did not converge.') def adjust_forces(self, atoms, forces): """Project out translations and rotations and all other constraints""" self.initialize(atoms) positions = atoms.positions 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) # Projection 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 __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 = None 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(%s, %d, %d)' % \ (repr(self.bond), self.indices[0], self.indices[1]) 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]] 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]] 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]] r23 = newpositions[self.indices[2]] - newpositions[self.indices[1]] r34 = newpositions[self.indices[3]] - newpositions[self.indices[2]] 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]] 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]] 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 Hookean(FixConstraint): """Applies a Hookean restorative force between a pair of atoms, an atom and a point, or an atom and a plane.""" def __init__(self, a1, a2, k, rt=None): """Forces two atoms to stay close together by applying no force if they are below a threshold length, rt, and applying a Hookean restorative force when the distance between them exceeds rt. Can also be used to tether an atom to a fixed point in space or to a distance above a plane. a1 : int Index of atom 1 a2 : one of three options 1) index of atom 2 2) a fixed point in cartesian space to which to tether a1 3) a plane given as (A, B, C, D) in A x + B y + C z + D = 0. k : float Hooke's law (spring) constant to apply when distance exceeds threshold_length. Units of eV A^-2. rt : float The threshold length below which there is no force. The length is 1) between two atoms, 2) between atom and point. This argument is not supplied in case 3. Units of A. If a plane is specified, the Hooke's law force is applied if the atom is on the normal side of the plane. For instance, the plane with (A, B, C, D) = (0, 0, 1, -7) defines a plane in the xy plane with a z intercept of +7 and a normal vector pointing in the +z direction. If the atom has z > 7, then a downward force would be applied of k * (atom.z - 7). The same plane with the normal vector pointing in the -z direction would be given by (A, B, C, D) = (0, 0, -1, 7). """ if isinstance(a2, int): self._type = 'two atoms' self.indices = [a1, a2] elif len(a2) == 3: self._type = 'point' self.index = a1 self.origin = np.array(a2) elif len(a2) == 4: self._type = 'plane' self.index = a1 self.plane = a2 else: raise RuntimeError('Unknown type for a2') self.threshold = rt self.spring = k def todict(self): dct = {'name': 'Hookean'} dct['kwargs'] = {'rt': self.threshold, 'k': self.spring} if self._type == 'two atoms': dct['kwargs']['a1'] = self.indices[0] dct['kwargs']['a2'] = self.indices[1] elif self._type == 'point': dct['kwargs']['a1'] = self.index dct['kwargs']['a2'] = self.origin elif self._type == 'plane': dct['kwargs']['a1'] = self.index dct['kwargs']['a2'] = self.plane else: raise NotImplementedError('Bad type: %s' % self._type) return dct def adjust_positions(self, atoms, newpositions): pass def adjust_forces(self, atoms, forces): positions = atoms.positions if self._type == 'plane': A, B, C, D = self.plane x, y, z = positions[self.index] d = ((A * x + B * y + C * z + D) / np.sqrt(A**2 + B**2 + C**2)) if d < 0: return magnitude = self.spring * d direction = - np.array((A, B, C)) / np.linalg.norm((A, B, C)) forces[self.index] += direction * magnitude return if self._type == 'two atoms': p1, p2 = positions[self.indices] elif self._type == 'point': p1 = positions[self.index] p2 = self.origin displace = p2 - p1 bondlength = np.linalg.norm(displace) if bondlength > self.threshold: magnitude = self.spring * (bondlength - self.threshold) direction = displace / np.linalg.norm(displace) if self._type == 'two atoms': forces[self.indices[0]] += direction * magnitude forces[self.indices[1]] -= direction * magnitude else: forces[self.index] += direction * magnitude def adjust_momenta(self, positions, momenta): pass def adjust_potential_energy(self, atoms, energy): """Returns the difference to the potential energy due to an active constraint. (That is, the quantity returned is to be added to the potential energy.)""" positions = atoms.positions if self._type == 'plane': A, B, C, D = self.plane x, y, z = positions[self.index] d = ((A * x + B * y + C * z + D) / np.sqrt(A**2 + B**2 + C**2)) if d > 0: return 0.5 * self.spring * d**2 else: return 0. if self._type == 'two atoms': p1, p2 = positions[self.indices] elif self._type == 'point': p1 = positions[self.index] p2 = self.origin displace = p2 - p1 bondlength = np.linalg.norm(displace) if bondlength > self.threshold: return 0.5 * self.spring * (bondlength - self.threshold)**2 else: return 0. def index_shuffle(self, atoms, ind): # See docstring of superclass if self._type == 'two atoms': self.indices = [ind.index(self.indices[0]), ind.index(self.indices[1])] elif self._type == 'point': self.index = ind.index(self.index) elif self._type == 'plane': self.index = ind.index(self.index) def __repr__(self): if self._type == 'two atoms': return 'Hookean(%d, %d)' % tuple(self.indices) elif self._type == 'point': return 'Hookean(%d) to cartesian' % self.index else: return 'Hookean(%d) to plane' % self.index 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 = [] # Make self.info a reference to the underlying atoms' info dictionary. self.info = self.atoms.info 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 get_celldisp(self): return self.atoms.get_celldisp() def has(self, name): 'Check for existence 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)).copy() 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. - True = relax to zero - False = fixed, ignore this component You can still use constraints on the atoms, e.g. FixAtoms, to control the relaxation of the atoms. >>> # this should be equivalent to the StrainFilter >>> atoms = Atoms(...) >>> atoms.set_constraint(FixAtoms(mask=[True for atom in atoms])) >>> ucf = UnitCellFilter(atoms) You should not attach this UnitCellFilter object to a trajectory. Instead, create a trajectory for the atoms, and attach it to an optimizer like this: >>> atoms = Atoms(...) >>> ucf = UnitCellFilter(atoms) >>> qn = QuasiNewton(ucf) >>> traj = Trajectory('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() self.copy = self.atoms.copy self.arrays = self.atoms.arrays 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.9.1.4567/ase/atoms.py0000664000175000017500000016224312553425550016750 0ustar jensjjensj00000000000000# 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. """ import numbers import warnings from math import cos, sin import copy import numpy as np import ase.units as units from ase.atom import Atom from ase.data import atomic_numbers, chemical_symbols, atomic_masses from ase.utils import basestring from ase.utils.geometry import wrap_positions, find_mic 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]. celldisp: Vector Unit cell displacement vector. To visualize a displaced cell around the center of mass of a Systems of atoms. Default value = (0,0,0) pbc: one or three bool Periodic boundary conditions flags. Examples: True, False, 0, 1, (1, 1, 0), (True, False, False). Default value: False. constraint: constraint object(s) Used for applying one or more constraints during structure optimization. calculator: calculator object Used to attach a calculator for calculating energies and atomic forces. info: dict of key-value pairs Dictionary of key-value pairs with additional information about the system. The following keys may be used by ase: - 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, celldisp=None, constraint=None, calculator=None, info=None): atoms = None if 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_initial_charges() if cell is None: cell = atoms.get_cell() if celldisp is None: celldisp = atoms.get_celldisp() 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() if info is None: info = copy.deepcopy(atoms.info) 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 celldisp is None: celldisp = np.zeros(shape=(3, 1)) self.set_celldisp(celldisp) 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_masses(default(masses, None)) self.set_initial_magnetic_moments(default(magmoms, 0.0)) self.set_initial_charges(default(charges, 0.0)) if pbc is None: pbc = False self.set_pbc(pbc) self.set_momenta(default(momenta, (0.0, 0.0, 0.0))) 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 set_celldisp(self, celldisp): """Set the unit cell displacement vectors.""" celldisp = np.array(celldisp, float) self._celldisp = celldisp def get_celldisp(self): """Get the unit cell displacement vectors.""" return self._celldisp.copy() 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) if len(a) == 0 and shape is not None: a.shape = (-1,) + shape 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 get_chemical_symbols(self): """Get list of chemical symbol strings.""" return [chemical_symbols[Z] for Z in self.arrays['numbers']] def set_chemical_symbols(self, symbols): """Set chemical symbols.""" self.set_array('numbers', symbols2numbers(symbols), int, ()) def get_chemical_formula(self, mode='hill'): """Get the chemial formula as a string based on the chemical symbols. Parameters: mode: str There are three different modes available: 'all': The list of chemical symbols are contracted to at string, e.g. ['C', 'H', 'H', 'H', 'O', 'H'] becomes 'CHHHOH'. 'reduce': The same as 'all' where repeated elements are contracted to a single symbol and a number, e.g. 'CHHHOCHHH' is reduced to 'CH3OCH3'. 'hill': The list of chemical symbols are contracted to a string following the Hill notation (alphabetical order with C and H first), e.g. 'CHHHOCHHH' is reduced to 'C2H6O' and 'SOOHOHO' to 'H2O4S'. This is default. """ if len(self) == 0: return '' if mode == 'reduce': numbers = self.get_atomic_numbers() n = len(numbers) changes = np.concatenate(([0], np.arange(1, n)[numbers[1:] != numbers[:-1]])) symbols = [chemical_symbols[e] for e in numbers[changes]] counts = np.append(changes[1:], n) - changes elif mode == 'hill': numbers = self.get_atomic_numbers() elements = np.unique(numbers) symbols = np.array([chemical_symbols[e] for e in elements]) counts = np.array([(numbers == e).sum() for e in elements]) ind = symbols.argsort() symbols = symbols[ind] counts = counts[ind] if 'H' in symbols: i = np.arange(len(symbols))[symbols == 'H'] symbols = np.insert(np.delete(symbols, i), 0, symbols[i]) counts = np.insert(np.delete(counts, i), 0, counts[i]) if 'C' in symbols: i = np.arange(len(symbols))[symbols == 'C'] symbols = np.insert(np.delete(symbols, i), 0, symbols[i]) counts = np.insert(np.delete(counts, i), 0, counts[i]) elif mode == 'all': numbers = self.get_atomic_numbers() symbols = [chemical_symbols[n] for n in numbers] counts = [1] * len(numbers) else: raise ValueError("Use mode = 'all', 'reduce' or 'hill'.") formula = '' for s, c in zip(symbols, counts): formula += s if c > 1: formula += str(c) return formula def set_tags(self, tags): """Set tags for all atoms. If only one tag is supplied, it is applied to all atoms.""" if isinstance(tags, int): tags = [tags] * len(self) 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: if hasattr(constraint, 'adjust_momenta'): constraint.adjust_momenta(self, 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.') return self._calc.get_magnetic_moments(self) def get_magnetic_moment(self): """Get calculated total magnetic moment.""" if self._calc is None: raise RuntimeError('Atoms object has no calculator.') return self._calc.get_magnetic_moment(self) def set_initial_charges(self, charges=None): """Set the initial charges.""" if charges is None: self.set_array('charges', None) else: self.set_array('charges', charges, float, ()) def get_initial_charges(self): """Get array of initial charges.""" if 'charges' in self.arrays: return self.arrays['charges'].copy() else: return np.zeros(len(self)) def get_charges(self): """Get calculated charges.""" if self._calc is None: raise RuntimeError('Atoms object has no calculator.') try: return self._calc.get_charges(self) except AttributeError: raise NotImplementedError def set_positions(self, newpositions): """Set positions, honoring any constraints.""" if self.constraints: newpositions = np.array(newpositions, float) for constraint in self.constraints: constraint.adjust_positions(self, newpositions) self.set_array('positions', newpositions, shape=(3,)) def get_positions(self, wrap=False): """Get array of positions. If wrap==True, wraps atoms back into unit cell. """ if wrap: scaled = self.get_scaled_positions() return np.dot(scaled, self._cell) else: return self.arrays['positions'].copy() def get_potential_energy(self, force_consistent=False, apply_constraint=True): """Calculate potential energy. Ask the attached calculator to calculate the potential energy and apply constraints. Use *apply_constraint=False* to get the raw forces. When supported by the calculator, either the energy extrapolated to zero Kelvin or the energy consistent with the forces (the free energy) can be returned. """ if self._calc is None: raise RuntimeError('Atoms object has no calculator.') if force_consistent: energy = self._calc.get_potential_energy( self, force_consistent=force_consistent) else: energy = self._calc.get_potential_energy(self) if apply_constraint: constraints = [c for c in self.constraints if hasattr(c, 'adjust_potential_energy')] for constraint in constraints: energy += constraint.adjust_potential_energy(self, energy) return energy 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, forces) return forces def get_stress(self, voigt=True): """Calculate stress tensor. Returns an array of the six independent components of the symmetric stress tensor, in the traditional Voigt order (xx, yy, zz, yz, xz, xy) or as a 3x3 matrix. Default is Voigt order. """ if self._calc is None: raise RuntimeError('Atoms object has no calculator.') stress = self._calc.get_stress(self) shape = stress.shape if shape == (3, 3): warnings.warn('Converting 3x3 stress tensor from %s ' % self._calc.__class__.__name__ + 'calculator to the required Voigt form.') stress = np.array([stress[0, 0], stress[1, 1], stress[2, 2], stress[1, 2], stress[0, 2], stress[0, 1]]) else: assert shape == (6,) if voigt: return stress else: xx, yy, zz, yz, xz, xy = stress return np.array([(xx, xy, xz), (xy, yy, yz), (xz, yz, zz)]) 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.') return self._calc.get_dipole_moment(self) def copy(self): """Return a 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_formula('reduce') else: symbols = self.get_chemical_formula('hill') 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 if name == 'masses': a2 = other.get_masses() else: 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()[:n1] 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, numbers.Integral): 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(self, 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() or isinstance(i, list))): 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=(0, 1, 2)): """Center atoms in unit cell. Centers the atoms in the unit cell, so there is the same amount of vacuum on all sides. vacuum: float (default: None) If specified adjust the amount of vacuum when centering. If vacuum=10.0 there will thus be 10 Angstrom of vacuum on each side. axis: int or sequence of ints Axis or axes to act on. Default: Act on all axes. """ # 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 isinstance(axis, int): axes = (axis,) 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.get_masses() 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 based on a vector and an angle, or two vectors. Parameters: v: Vector to rotate the atoms around. Vectors can be given as strings: 'x', '-x', 'y', ... . a = None: Angle that the atoms is rotated around the vecor 'v'. If an angle is not specified, the length of 'v' is used as the angle (default). The angle can also be a vector and then 'v' is rotated into 'a'. center = (0, 0, 0): The center is kept fixed under the rotation. Use 'COM' to fix the center of mass, 'COP' to fix the center of positions or 'COU' to fix the center of cell. rotate_cell = False: If true the cell is also rotated. Examples: Rotate 90 degrees around the z-axis, so that the x-axis is rotated into the y-axis: >>> a = pi / 2 >>> atoms.rotate('z', a) >>> atoms.rotate((0, 0, 1), a) >>> atoms.rotate('-z', -a) >>> atoms.rotate((0, 0, a)) >>> atoms.rotate('x', 'y') """ 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 elif s > 0: v /= s if isinstance(center, str): if center.lower() == 'com': center = self.get_center_of_mass() elif center.lower() == 'cop': center = self.get_positions().mean(axis=0) elif center.lower() == 'cou': center = self.get_cell().sum(axis=0) / 2 else: raise ValueError('Cannot interpret center') else: center = np.array(center) 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, 'COP' to select center of positions or 'COU' to select center of cell. phi : The 1st rotation angle around the z axis. theta : Rotation around the x axis. psi : 2nd rotation around the z axis. """ if isinstance(center, str): if center.lower() == 'com': center = self.get_center_of_mass() elif center.lower() == 'cop': center = self.get_positions().mean(axis=0) elif center.lower() == 'cou': center = self.get_cell().sum(axis=0) / 2 else: raise ValueError('Cannot interpret center') 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].position j += 1 def set_dihedral(self, list, angle, mask=None, indices=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. Alternatively to the mask, the indices of the atoms to be rotated can be supplied. 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 and indices is None: mask = np.zeros(len(self)) mask[list[3]] = 1 elif indices: mask = [index in indices for index in range(len(self))] # 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[1]->list[0] 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 = angle - current # 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, vector=False): """Return distance between two atoms. Use mic=True to use the Minimum Image Convention. vector=True gives the distance vector (from a0 to a1). """ R = self.arrays['positions'] D = np.array([R[a1] - R[a0]]) if mic: D, D_len = find_mic(D, self._cell, self._pbc) else: D_len = np.array([np.sqrt((D**2).sum())]) if vector: return D[0] return D_len[0] def get_distances(self, a, indices, mic=False, vector=False): """Return distances of atom No.i with a list of atoms. Use mic=True to use the Minimum Image Convention. vector=True gives the distance vector (from a to self[indices]). """ R = self.arrays['positions'] D = R[indices] - R[a] if mic: D, D_len = find_mic(D, self._cell, self._pbc) else: D_len = np.sqrt((D**2).sum(1)) if vector: return D return D_len def get_all_distances(self, mic=False): """Return distances of all of the atoms with all of the atoms. Use mic=True to use the Minimum Image Convention. """ L = len(self) R = self.arrays['positions'] D = [] for i in range(L - 1): D.append(R[i + 1:] - R[i]) D = np.concatenate(D) if mic: D, D_len = find_mic(D, self._cell, self._pbc) else: D_len = np.sqrt((D**2).sum(1)) results = np.zeros((L, L), dtype=float) start = 0 for i in range(L - 1): results[i, i + 1:] = D_len[start:start + L - i - 1] start += L - i - 1 return results + results.T def set_distance(self, a0, a1, distance, fix=0.5, mic=False): """Set the distance between two atoms. Set the distance between atoms *a0* and *a1* to *distance*. By default, the center of the two atoms will be fixed. Use *fix=0* to fix the first atom, *fix=1* to fix the second atom and *fix=0.5* (default) to fix the center of the bond.""" R = self.arrays['positions'] D = np.array([R[a1] - R[a0]]) if mic: D, D_len = find_mic(D, self._cell, self._pbc) else: D_len = np.array([np.sqrt((D**2).sum())]) x = 1.0 - distance / D_len[0] R[a0] += (x * fix) * D[0] R[a1] -= (x * (1.0 - fix)) * D[0] def get_scaled_positions(self, wrap=True): """Get positions relative to unit cell. If wrap is True, 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.""" fractional = np.linalg.solve(self.cell.T, self.positions.T).T if wrap: for i, periodic in enumerate(self.pbc): if periodic: # Yes, we need to do it twice. # See the scaled_positions.py test. fractional[:, i] %= 1.0 fractional[:, i] %= 1.0 return fractional def set_scaled_positions(self, scaled): """Set positions relative to unit cell.""" self.arrays['positions'][:] = np.dot(scaled, self._cell) def wrap(self, center=(0.5, 0.5, 0.5), pbc=None, eps=1e-7): """Wrap positions to unit cell. Parameters: center: three float The positons in fractional coordinates that the new positions will be nearest possible to. pbc: one or 3 bool For each axis in the unit cell decides whether the positions will be moved along this axis. By default, the boundary conditions of the Atoms object will be used. eps: float Small number to prevent slightly negative coordinates from beeing wrapped. See also the :func:`ase.utils.geometry.wrap_positions` function. Example: >>> a = Atoms('H', ... [[-0.1, 1.01, -0.5]], ... cell=[[1, 0, 0], [0, 1, 0], [0, 0, 4]], ... pbc=[1, 1, 0]) >>> a.wrap() >>> a.positions array([[ 0.9 , 0.01, -0.5 ]]) """ if pbc is None: pbc = self.pbc self.positions[:] = wrap_positions(self.positions, self.cell, pbc, center, eps) def get_temperature(self): """Get the temperature in Kelvin.""" ekin = self.get_kinetic_energy() / len(self) return ekin / (1.5 * units.kB) 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): """Check if two atoms objects are not equal. Any differences in positions, atomic numbers, unit cell or periodic boundary condtions make atoms objects not equal. """ 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 write(self, filename, format=None, **kwargs): """Write atoms object to a file. see ase.io.write for formats. kwargs are passed to ase.io.write. """ from ase.io import write write(filename, self, format, **kwargs) def edit(self): """Modify atoms interactively through ase-gui viewer. Conflicts leading to undesirable behaviour might arise when matplotlib has been pre-imported with certain incompatible backends and while trying to use the plot feature inside the interactive ag. To circumvent, please set matplotlib.use('gtk') before calling this method. """ 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, basestring): 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.9.1.4567/ase/calculators/0000775000175000017500000000000012553427753017566 5ustar jensjjensj00000000000000python-ase-3.9.1.4567/ase/calculators/elk.py0000664000175000017500000004075512553425527020723 0ustar jensjjensj00000000000000import os import numpy as np from ase.units import Bohr, Hartree from ase.io.elk import read_elk from ase.calculators.calculator import FileIOCalculator, Parameters, kpts2mp, \ ReadError elk_parameters = { 'swidth': Hartree, } class ELK(FileIOCalculator): command = 'elk > elk.out' implemented_properties = ['energy', 'forces'] def __init__(self, restart=None, ignore_bad_restart_file=False, label=os.curdir, atoms=None, **kwargs): """Construct ELK calculator. The keyword arguments (kwargs) can be one of the ASE standard keywords: 'xc', 'kpts' and 'smearing' or any of ELK' native keywords. """ FileIOCalculator.__init__(self, restart, ignore_bad_restart_file, label, atoms, **kwargs) def set_label(self, label): self.label = label self.directory = label self.prefix = '' self.out = os.path.join(label, 'INFO.OUT') def check_state(self, atoms): system_changes = FileIOCalculator.check_state(self, atoms) # Ignore boundary conditions (ELK always uses them): if 'pbc' in system_changes: system_changes.remove('pbc') return system_changes def set(self, **kwargs): changed_parameters = FileIOCalculator.set(self, **kwargs) if changed_parameters: self.reset() def write_input(self, atoms, properties=None, system_changes=None): FileIOCalculator.write_input(self, atoms, properties, system_changes) self.initialize(atoms) self.parameters.write(os.path.join(self.directory, 'parameters.ase')) if 'xctype' in self.parameters: if 'xc' in self.parameters: raise RuntimeError("You can't use both 'xctype' and 'xc'!") if self.parameters.get('autokpt'): if 'kpts' in self.parameters: raise RuntimeError("You can't use both 'autokpt' and 'kpts'!") if 'ngridk' in self.parameters: raise RuntimeError("You can't use both 'autokpt' and 'ngridk'!") if 'ngridk' in self.parameters: if 'kpts' in self.parameters: raise RuntimeError("You can't use both 'ngridk' and 'kpts'!") if self.parameters.get('autoswidth'): if 'smearing' in self.parameters: raise RuntimeError("You can't use both 'autoswidth' and 'smearing'!") if 'swidth' in self.parameters: raise RuntimeError("You can't use both 'autoswidth' and 'swidth'!") fd = open(os.path.join(self.directory, 'elk.in'), 'w') # handle custom specifications of rmt # (absolute or relative to default) in Bohr # rmt = {'H': 0.7, 'O': -0.2, ...} if self.parameters.get('rmt', None) is not None: self.rmt = self.parameters['rmt'].copy() assert len(self.rmt.keys()) == len(list(set(self.rmt.keys()))), 'redundant rmt definitions' self.parameters.pop('rmt') # this is not an elk keyword! else: self.rmt = None inp = {} inp.update(self.parameters) if 'xc' in self.parameters: xctype = {'LDA': 3, # PW92 'PBE': 20, 'REVPBE': 21, 'PBESOL': 22, 'WC06': 26, 'AM05': 30, 'mBJLDA': (100, 208, 12)}[self.parameters.xc] inp['xctype'] = xctype del inp['xc'] if 'kpts' in self.parameters: mp = kpts2mp(atoms, self.parameters.kpts) inp['ngridk'] = tuple(mp) vkloff = [] # is this below correct? for nk in mp: if nk % 2 == 0: # shift kpoint away from gamma point vkloff.append(0.5) else: vkloff.append(0) inp['vkloff'] = vkloff del inp['kpts'] if 'smearing' in self.parameters: name = self.parameters.smearing[0].lower() if name == 'methfessel-paxton': stype = self.parameters.smearing[2] else: stype = {'gaussian': 0, 'fermi-dirac': 3, }[name] inp['stype'] = stype inp['swidth'] = self.parameters.smearing[1] del inp['smearing'] # convert keys to ELK units for key, value in inp.items(): if key in elk_parameters: inp[key] /= elk_parameters[key] # write all keys for key, value in inp.items(): fd.write('%s\n' % key) if isinstance(value, bool): fd.write('.%s.\n\n' % ('false', 'true')[value]) elif isinstance(value, (int, float)): fd.write('%s\n\n' % value) else: fd.write('%s\n\n' % ' '.join([str(x) for x in value])) # cell fd.write('avec\n') for vec in atoms.cell: fd.write('%.14f %.14f %.14f\n' % tuple(vec / Bohr)) fd.write('\n') # atoms species = {} symbols = [] for a, (symbol, m) in enumerate( zip(atoms.get_chemical_symbols(), atoms.get_initial_magnetic_moments())): if symbol in species: species[symbol].append((a, m)) else: species[symbol] = [(a, m)] symbols.append(symbol) fd.write('atoms\n%d\n' % len(species)) #scaled = atoms.get_scaled_positions(wrap=False) scaled = np.linalg.solve(atoms.cell.T, atoms.positions.T).T for symbol in symbols: fd.write("'%s.in' : spfname\n" % symbol) fd.write('%d\n' % len(species[symbol])) for a, m in species[symbol]: fd.write('%.14f %.14f %.14f 0.0 0.0 %.14f\n' % (tuple(scaled[a])+ (m,))) # species species_path = self.parameters.get('species_dir') if species_path is None: species_path = os.environ.get('ELK_SPECIES_PATH') if species_path is None: raise RuntimeError( 'Missing species directory! Use species_dir ' + 'parameter or set $ELK_SPECIES_PATH environment variable.') # custom species definitions if self.rmt is not None: fd.write("\n") sfile = os.path.join(os.environ['ELK_SPECIES_PATH'], 'elk.in') assert os.path.exists(sfile) slines = open(sfile, 'r').readlines() # remove unused species for s in self.rmt.keys(): if s not in species.keys(): self.rmt.pop(s) # add undefined species with defaults for s in species.keys(): if s not in self.rmt.keys(): # use default rmt for undefined species self.rmt.update({s: 0.0}) # write custom species into elk.in skeys = list(set(self.rmt.keys())) # unique skeys.sort() for s in skeys: found = False for n, line in enumerate(slines): if line.find("'" + s + "'") > -1: begline = n - 1 for n, line in enumerate(slines[begline:]): if not line.strip(): # first empty line endline = n found = True break assert found fd.write("species\n") # set rmt on third line rmt = self.rmt[s] assert isinstance(rmt, (float,int)) if rmt <= 0.0: # relative # split needed because H is defined with comments newrmt = float(slines[begline + 3].split()[0].strip()) + rmt else: newrmt = rmt slines[begline + 3] = '%6s\n' % str(newrmt) for l in slines[begline: begline + endline]: fd.write('%s' % l) fd.write("\n") else: # use default species # if sppath is present in elk.in it overwrites species blocks! fd.write("sppath\n'%s'\n\n" % os.environ['ELK_SPECIES_PATH']) def read(self, label): FileIOCalculator.read(self, label) totenergy = os.path.join(self.directory, 'TOTENERGY.OUT') eigval = os.path.join(self.directory, 'EIGVAL.OUT') kpoints = os.path.join(self.directory, 'KPOINTS.OUT') for filename in [totenergy, eigval, kpoints, self.out]: if not os.path.isfile(filename): raise ReadError # read state from elk.in because *.OUT do not provide enough digits! self.atoms = read_elk(os.path.join(self.directory, 'elk.in')) self.parameters = Parameters.read(os.path.join(self.directory, 'parameters.ase')) self.initialize(self.atoms) self.read_results() def read_results(self): converged = self.read_convergence() if not converged: raise RuntimeError('ELK did not converge! Check ' + self.out) self.read_energy() if self.parameters.get('tforce'): self.read_forces() self.width = self.read_electronic_temperature() self.nbands = self.read_number_of_bands() self.nelect = self.read_number_of_electrons() self.niter = self.read_number_of_iterations() self.magnetic_moment = self.read_magnetic_moment() def initialize(self, atoms): if 'spinpol' not in self.parameters: # honor elk.in settings self.spinpol = atoms.get_initial_magnetic_moments().any() else: self.spinpol = self.parameters['spinpol'] def get_forces(self, atoms): if not self.parameters.get('tforce'): raise NotImplementedError return FileIOCalculator.get_forces(self, atoms) def read_energy(self): fd = open(os.path.join(self.directory, 'TOTENERGY.OUT'), 'r') e = float(fd.readlines()[-1]) * Hartree self.results['free_energy'] = e self.results['energy'] = e def read_forces(self): lines = open(self.out, 'r').readlines() forces = np.zeros([len(self.atoms), 3]) forces = [] atomnum = 0 for line in lines: if line.rfind('total force') > -1: forces.append(np.array([float(f) for f in line.split(':')[1].split()])) atomnum =+ 1 self.results['forces'] = np.array(forces) * Hartree / Bohr def read_convergence(self): converged = False text = open(self.out).read().lower() if ('convergence targets achieved' in text and 'reached self-consistent loops maximum' not in text): converged = True return converged # more methods def get_electronic_temperature(self): return self.width*Hartree def get_number_of_bands(self): return self.nbands def get_number_of_electrons(self): return self.nelect def get_number_of_iterations(self): return self.niter def get_number_of_spins(self): return 1 + int(self.spinpol) def get_magnetic_moment(self, atoms=None): return self.magnetic_moment def get_magnetic_moments(self, atoms): # not implemented yet, so # 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_spin_polarized(self): return self.spinpol def get_eigenvalues(self, kpt=0, spin=0): return self.read_eigenvalues(kpt, spin, 'eigenvalues') def get_occupation_numbers(self, kpt=0, spin=0): return self.read_eigenvalues(kpt, spin, 'occupations') def get_ibz_k_points(self): return self.read_kpts(mode='ibz_k_points') def get_k_point_weights(self): return self.read_kpts(mode='k_point_weights') def get_fermi_level(self): return self.read_fermi() def read_kpts(self, mode='ibz_k_points'): """ Returns list of kpts weights or kpts coordinates. """ values = [] assert mode in ['ibz_k_points' , 'k_point_weights'], 'mode not in [\'ibz_k_points\' , \'k_point_weights\']' kpoints = os.path.join(self.directory, 'KPOINTS.OUT') lines = open(kpoints).readlines() kpts = None for line in lines: if line.rfind(': nkpt') > -1: kpts = int(line.split(':')[0].strip()) break assert not kpts is None text = lines[1:] # remove first line values = [] for line in text: if mode == 'ibz_k_points': b = [float(c.strip()) for c in line.split()[1:4]] else: b = float(line.split()[-2]) values.append(b) if len(values) == 0: values = None return np.array(values) def read_number_of_bands(self): nbands = None eigval = os.path.join(self.directory, 'EIGVAL.OUT') lines = open(eigval).readlines() for line in lines: if line.rfind(': nstsv') > -1: nbands = int(line.split(':')[0].strip()) break if self.get_spin_polarized(): nbands = nbands / 2 return nbands def read_number_of_electrons(self): nelec = None text = open(self.out).read().lower() # Total electronic charge for line in iter(text.split('\n')): if line.rfind('total electronic charge :') > -1: nelec = float(line.split(':')[1].strip()) break return nelec def read_number_of_iterations(self): niter = None lines = open(self.out).readlines() for line in lines: if line.rfind(' Loop number : ') > -1: niter = int(line.split(':')[1].split()[0].strip()) # last iter return niter def read_magnetic_moment(self): magmom = None lines = open(self.out).readlines() for line in lines: if line.rfind('total moment :') > -1: magmom = float(line.split(':')[1].strip()) # last iter return magmom def read_electronic_temperature(self): width = None text = open(self.out).read().lower() for line in iter(text.split('\n')): if line.rfind('smearing width :') > -1: width = float(line.split(':')[1].strip()) break return width def read_eigenvalues(self, kpt=0, spin=0, mode='eigenvalues'): """ Returns list of last eigenvalues, occupations for given kpt and spin. """ values = [] assert mode in ['eigenvalues' , 'occupations'], 'mode not in [\'eigenvalues\' , \'occupations\']' eigval = os.path.join(self.directory, 'EIGVAL.OUT') lines = open(eigval).readlines() nstsv = None for line in lines: if line.rfind(': nstsv') > -1: nstsv = int(line.split(':')[0].strip()) break assert not nstsv is None kpts = None for line in lines: if line.rfind(': nkpt') > -1: kpts = int(line.split(':')[0].strip()) break assert not kpts is None text = lines[3:] # remove first 3 lines # find the requested k-point beg = 2 + (nstsv + 4) * kpt end = beg + nstsv if self.get_spin_polarized(): # elk prints spin-up and spin-down together if spin == 0: beg = beg end = beg + nstsv / 2 else: beg = beg + nstsv / 2 end = end values = [] for line in text[beg:end]: b = [float(c.strip()) for c in line.split()[1:]] values.append(b) if mode == 'eigenvalues': values = [Hartree*v[0] for v in values] else: values = [v[1] for v in values] if len(values) == 0: values = None return np.array(values) def read_fermi(self): """Method that reads Fermi energy in Hartree from the output file and returns it in eV""" E_f=None text = open(self.out).read().lower() for line in iter(text.split('\n')): if line.rfind('fermi :') > -1: E_f = float(line.split(':')[1].strip()) E_f = E_f*Hartree return E_f python-ase-3.9.1.4567/ase/calculators/tip3p.py0000664000175000017500000001350512553425526021177 0ustar jensjjensj00000000000000"""TIP3P potential, constraints and dynamics.""" from math import pi, sin, cos import numpy as np import ase.units as units from ase.parallel import world from ase.md.md import MolecularDynamics qH = 0.417 sigma0 = 3.15061 epsilon0 = 0.1521 * units.kcal / units.mol rOH = 0.9572 thetaHOH = 104.52 / 180 * pi class TIP3P: def __init__(self, rc=9.0, width=1.0): self.energy = None self.forces = None self.rc1 = rc - width self.rc2 = rc def get_spin_polarized(self): return 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.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_potential_energy(self, atoms): self.update(atoms) return self.energy def get_forces(self, atoms): self.update(atoms) return self.forces.copy() def get_stress(self, atoms): raise NotImplementedError def calculate(self, atoms): self.positions = atoms.get_positions().copy() self.cell = atoms.get_cell().copy() self.pbc = atoms.get_pbc().copy() natoms = len(atoms) nH2O = natoms // 3 assert self.pbc.all() C = self.cell.diagonal() assert not (self.cell - np.diag(C)).any() assert (C >= 2 * self.rc2).all() self.numbers = atoms.get_atomic_numbers() Z = self.numbers.reshape((-1, 3)) assert (Z[:, 1:] == 1).all() and (Z[:, 0] == 8).all() R = self.positions.reshape((nH2O, 3, 3)) RO = R[:, 0] self.energy = 0.0 self.forces = np.zeros((natoms, 3)) if world.size == 1: mya = list(range(nH2O - 1)) else: rank = world.rank size = world.size assert nH2O // (2 * size) == 0 mynH2O = nH2O // 2 // size mya = (list(range(rank * n, (rank + 1) * n)) + list(range((size - rank - 1) * n, (size - rank) * n))) q = np.empty(3) q[:] = qH * (units.Hartree * units.Bohr)**0.5 q[0] *= -2 for a in mya: DOO = (RO[a + 1:] - RO[a] + 0.5 * C) % C - 0.5 * C dOO = (DOO**2).sum(axis=1)**0.5 x1 = dOO > self.rc1 x2 = dOO < self.rc2 f = np.zeros(nH2O - a - 1) f[x2] = 1.0 dfdd = np.zeros(nH2O - a - 1) x12 = np.logical_and(x1, x2) d = (dOO[x12] - self.rc1) / (self.rc2 - self.rc1) f[x12] -= d**2 * (3.0 - 2.0 * d) dfdd[x12] -= 6.0 / (self.rc2 - self.rc1) * d * (1.0 - d) y = (sigma0 / dOO)**6 y2 = y**2 e = 4 * epsilon0 * (y2 - y) self.energy += np.dot(e, f) dedd = 24 * epsilon0 * (2 * y2 - y) / dOO * f - e * dfdd F = (dedd / dOO)[:, np.newaxis] * DOO self.forces[(a + 1) * 3::3] += F self.forces[a * 3] -= F.sum(axis=0) for i in range(3): D = (R[a + 1:] - R[a, i] + 0.5 * C) % C - 0.5 * C d = (D**2).sum(axis=2)**0.5 e = q[i] * q / d self.energy += np.dot(f, e).sum() F = (e / d**2 * f[:, np.newaxis])[:, :, np.newaxis] * D F[:, 0] -= (e.sum(axis=1) * dfdd / dOO)[:, np.newaxis] * DOO self.forces[(a + 1) * 3:] += F.reshape((-1, 3)) self.forces[a * 3 + i] -= F.sum(axis=0).sum(axis=0) self.energy = world.sum(self.energy) world.sum(self.forces) class H2OConstraint: """Constraint object for a rigid H2O molecule.""" def __init__(self, r=rOH, theta=thetaHOH, iterations=23, masses=None): self.r = r self.theta = theta self.iterations = iterations self.m = masses def set_masses(self, masses): self.m = masses def adjust_positions(self, old, new): bonds = [(0, 1, self.r), (0, 2, self.r)] if self.theta: bonds.append((1, 2, sin(self.theta / 2) * self.r * 2)) for iter in range(self.iterations): for i, j, r in bonds: D = old[i::3] - old[j::3] m1 = self.m[i] m2 = self.m[j] a = new[i::3] b = new[j::3] B = a - b x = (D**2).sum(axis=1) y = (D * B).sum(axis=1) z = (B**2).sum(axis=1) - r**2 k = m1 * m2 / (m1 + m2) * ((y**2 - x * z)**0.5 - y) / x k.shape = (-1, 1) a += k / m1 * D b -= k / m2 * D def adjust_forces(self, positions, forces): pass def copy(self): return H2OConstraint(self.r, self.theta, self.iterations, self.m) class Verlet(MolecularDynamics): def step(self, f): atoms = self.atoms m = atoms.get_masses()[:, np.newaxis] v = self.atoms.get_velocities() r0 = atoms.get_positions() r = r0 + self.dt * v + self.dt**2 * f / m atoms.set_positions(r) r = atoms.get_positions() v = (r - r0) / self.dt self.atoms.set_velocities(v) return atoms.get_forces() python-ase-3.9.1.4567/ase/calculators/__init__.py0000664000175000017500000000010012553425526021662 0ustar jensjjensj00000000000000"""Interfaces to different ASE compatible force-calculators.""" python-ase-3.9.1.4567/ase/calculators/lj.py0000664000175000017500000000445412553425527020551 0ustar jensjjensj00000000000000from __future__ import division import numpy as np from ase.calculators.neighborlist import NeighborList from ase.calculators.calculator import Calculator, all_changes class LennardJones(Calculator): implemented_properties = ['energy', 'forces', 'stress'] default_parameters = {'epsilon': 1.0, 'sigma': 1.0, 'rc': None} nolabel = True def __init__(self, **kwargs): Calculator.__init__(self, **kwargs) def calculate(self, atoms=None, properties=['energy'], system_changes=all_changes): Calculator.calculate(self, atoms, properties, system_changes) natoms = len(self.atoms) sigma = self.parameters.sigma epsilon = self.parameters.epsilon rc = self.parameters.rc if rc is None: rc = 3 * sigma if 'numbers' in system_changes: self.nl = NeighborList([rc / 2] * natoms, self_interaction=False) self.nl.update(self.atoms) positions = self.atoms.positions cell = self.atoms.cell e0 = 4 * epsilon * ((sigma / rc)**12 - (sigma / rc)**6) energy = 0.0 forces = np.zeros((natoms, 3)) stress = np.zeros((3, 3)) for a1 in range(natoms): neighbors, offsets = self.nl.get_neighbors(a1) cells = np.dot(offsets, cell) d = positions[neighbors] + cells - positions[a1] r2 = (d**2).sum(1) c6 = (sigma**2 / r2)**3 c6[r2 > rc**2] = 0.0 energy -= e0 * (c6 != 0.0).sum() c12 = c6**2 energy += 4 * epsilon * (c12 - c6).sum() f = (24 * epsilon * (2 * c12 - c6) / r2)[:, np.newaxis] * d #print d #print r2**.5 #print offsets #print f #print neighbors forces[a1] -= f.sum(axis=0) for a2, f2 in zip(neighbors, f): forces[a2] += f2 stress += np.dot(f.T, d) #stress = np.dot(stress, cell) stress += stress.T.copy() stress *= -0.5 / self.atoms.get_volume() self.results['energy'] = energy self.results['forces'] = forces self.results['stress'] = stress.flat[[0, 4, 8, 5, 2, 1]] python-ase-3.9.1.4567/ase/calculators/gromacs.py0000664000175000017500000004237212553425526021577 0ustar jensjjensj00000000000000"""This module defines an ASE interface to GROMACS. http://www.gromacs.org/ It is VERY SLOW compared to standard Gromacs (due to slow formatted io required here). Mainly intended to be the MM part in the ase QM/MM Markus.Kaukonen@iki.fi To be done: 1) change the documentation for the new file-io-calculator (test works now) 2) change gromacs program names -now: hard coded -future: set as dictionary in params_runs """ import os from glob import glob import numpy as np from ase.calculators.calculator import FileIOCalculator, all_changes def do_clean(name='#*'): """ remove files matching wildcards """ myfiles = glob(name) for myfile in myfiles: try: os.remove(myfile) except OSError: pass class Gromacs(FileIOCalculator): """Class for doing GROMACS calculations. Before running a gromacs calculation you must prepare the input files separately (pdb2gmx and grompp for instance.) Input parameters for gromacs runs (the .mdp file) are given in self.params and can be set when initializing the calculator or by method set_own. for example:: CALC_MM_RELAX = Gromacs() CALC_MM_RELAX.set_own_params('integrator', 'steep', 'use steepest descent') Run command line arguments for gromacs related programs: pdb2gmx, grompp, mdrun, g_energy, g_traj. These can be given as:: CALC_MM_RELAX = Gromacs() CALC_MM_RELAX.set_own_params_runs('force_field', 'oplsaa') """ implemented_properties = ['energy', 'forces'] command = 'mdrun < PREFIX.files > PREFIX.log' default_parameters = dict( define='-DFLEXIBLE', integrator='cg', nsteps='10000', nstfout='10', nstlog='10', nstenergy='10', nstlist='10', ns_type='grid', pbc='xyz', rlist='1.15', coulombtype='PME-Switch', rcoulomb='0.8', vdwtype='shift', rvdw='0.8', rvdw_switch='0.75', DispCorr='Ener') def __init__(self, restart=None, ignore_bad_restart_file=False, label='gromacs', atoms=None, do_qmmm=False, freeze_qm=False, clean=True, water_model='tip3p', force_field='oplsaa', **kwargs): """Construct GROMACS-calculator object. Parameters ========== label: str Prefix to use for filenames (label.in, label.txt, ...). Default is 'gromacs'. do_qmmm : bool Is gromacs used as mm calculator for a qm/mm calculation freeze_qm : bool In qm/mm are the qm atoms kept fixed at their initial positions clean : bool Remove gromacs backup files and old gormacs.* files water_model: str Water model to be used in gromacs runs (see gromacs manual) force_field: str Force field to be used in gromacs runs """ self.do_qmmm = do_qmmm self.freeze_qm = freeze_qm self.water_model = water_model self.force_field = force_field self.clean = clean self.params_doc = {} # add comments for gromacs input file self.params_doc['define'] = \ 'flexible/ rigid water' self.params_doc['integrator'] = \ 'md: molecular dynamics(Leapfrog), \n' + \ '; md-vv: molecular dynamics(Velocity Verlet), \n' + \ '; steep: steepest descent minimization, \n' + \ '; cg: conjugate cradient minimization \n' self.positions = None self.atoms = None # storage for energy and forces #self.energy = None #self.forces = None FileIOCalculator.__init__(self, restart, ignore_bad_restart_file, label, atoms, **kwargs) self.set(**kwargs) # default values for runtime parameters # can be changed by self.set_own_params_runs('key', 'value') self.params_runs = {} self.params_runs['index_filename'] = 'index.ndx' self.params_runs['init_structure'] = self.label + '.pdb' self.params_runs['water'] = self.water_model self.params_runs['force_field'] = self.force_field self.params_runs['extra_mdrun_parameters'] = ' -nt 1 ' self.params_runs['extra_pdb2gmx_parameters'] = ' ' self.params_runs['extra_grompp_parameters'] = ' ' self.params_runs['extra_editconf_parameters'] = ' ' self.params_runs['extra_genbox_parameters'] = ' ' # these below are required by qm/mm self.topology_filename = self.label + '.top' self.name = 'Gromacs' # clean up gromacs backups if self.clean: do_clean('gromacs.???') # write input files for gromacs program g_energy self.write_g_energy_files() # a possible prefix for gromacs programs if 'GMXCMD_PREF' in os.environ: self.prefix = os.environ['GMXCMD_PREF'] else: self.prefix = '' # a possible postfix for gromacs programs if 'GMXCMD_POST' in os.environ: self.postfix = os.environ['GMXCMD_POST'] else: self.postfix = '' if self.do_qmmm: self.parameters['integrator'] = 'md' self.parameters['nsteps'] = '0' def generate_g96file(self): """ from current coordinates (self.structure_file) write a structure file in .g96 format """ from ase.io.gromos import write_gromos # generate structure file in g96 format write_gromos(self.label + '.g96', self.atoms) def run_editconf(self): """ run gromacs program editconf, typically to set a simulation box writing to the input structure""" command = 'editconf' + ' ' os.system(command + ' -f ' + self.label + '.g96' + ' -o ' + self.label + '.g96' + ' ' + self.params_runs.get('extra_editconf_parameters') + ' > /dev/null 2>&1') def run_genbox(self): """Run gromacs program genbox, typically to solvate the system writing to the input structure as extra parameter you need to define the file containing the solvent for instance:: CALC_MM_RELAX = Gromacs() CALC_MM_RELAX.set_own_params_runs( 'extra_genbox_parameters', '-cs spc216.gro') """ command = 'genbox' + ' ' os.system(command + \ ' -cp ' + self.label + '.g96' + \ ' -o ' + self.label + '.g96' + \ ' -p ' + self.label + '.top' + \ ' ' + self.params_runs.get('extra_genbox_parameters') +\ ' > /dev/null 2>&1') def run(self): """ runs a gromacs-mdrun with the current atom-configuration """ from ase.io.gromos import read_gromos # clean up gromacs backups if self.clean: do_clean('#*') command = 'mdrun' if self.do_qmmm: os.system(command \ + ' -s ' + self.label + '.tpr' \ + ' -o ' + self.label + '.trr ' \ + ' -e ' + self.label + '.edr ' \ + ' -g ' + self.label + '.log -ffout ' \ + ' -rerun ' + self.label + '.g96 ' \ + self.params_runs.get('extra_mdrun_parameters') \ + ' > mm.log 2>&1') else: os.system(command \ + ' -s ' + self.label + '.tpr ' \ + ' -o ' + self.label + '.trr ' \ + ' -e ' + self.label + '.edr ' \ + ' -g ' + self.label + '.log -ffout ' \ + ' -c ' + self.label + '.g96 ' \ + self.params_runs.get('extra_mdrun_parameters') \ + ' > MM.log 2>&1') atoms = read_gromos(self.label + '.g96') self.atoms = atoms.copy() def generate_topology_and_g96file(self): """ from coordinates (self.label.+'pdb') and gromacs run input file (self.label + '.mdp) generate topology (self.label+'top') and structure file in .g96 format (self.label + '.g96') """ from ase.io.gromos import read_gromos #generate structure and topology files # In case of predefinded topology file this is not done command = 'pdb2gmx' + ' ' os.system(command + \ ' -f ' + self.params_runs.get('init_structure') + \ ' -o ' + self.label + '.g96' + \ ' -p ' + self.label + '.top' + \ ' -ff ' + self.params_runs.get('force_field') + \ ' -water ' + self.params_runs.get('water') + \ ' ' + \ self.params_runs.get('extra_pdb2gmx_parameters') +\ ' > /dev/null 2>&1') # ' > debug.log 2>&1') # print command + \ # ' -f ' + self.params_runs.get('init_structure') + \ # ' -o ' + self.label+'.g96' + \ # ' -p ' + self.label+'.top' + \ # ' -ff ' + self.params_runs.get('force_field') + \ # ' -water ' + self.params_runs.get('water') + \ # ' ' + self.params_runs.get('extra_pdb2gmx_parameters') +\ # ' > /dev/null 2>&1' atoms = read_gromos(self.label + '.g96') self.atoms = atoms.copy() def generate_gromacs_run_file(self): """ Generates input file for a gromacs mdrun based on structure file and topology file resulting file is self.label + '.tpr """ #generate gromacs run input file (gromacs.tpr) try: os.remove(self.label + '.tpr') except: pass command = 'grompp ' os.system(command + \ ' -f ' + self.label + '.mdp' + \ ' -c ' + self.label + '.g96' + \ ' -p ' + self.label + '.top' + \ ' -o ' + self.label + '.tpr -maxwarn 100' + \ ' ' + self.params_runs.get('extra_grompp_parameters') +\ ' > /dev/null 2>&1') # print command + \ # ' -f ' + self.label + '.mdp' + \ # ' -c ' + self.label + '.g96' + \ # ' -p ' + self.label + '.top' + \ # ' -o ' + self.label + '.tpr -maxwarn 100' + \ # ' ' + self.params_runs.get('extra_grompp_parameters') +\ # ' > /dev/null 2>&1' def write_g_energy_files(self): """write input files for gromacs force and energy calculations for gromacs program g_energy""" filename = 'inputGenergy.txt' output = open(filename, 'w') output.write('Potential \n') output.write(' \n') output.write(' \n') output.close() filename = 'inputGtraj.txt' output = open(filename, 'w') output.write('System \n') output.write(' \n') output.write(' \n') output.close() def set_own_params(self, key, value, docstring=""): """Set own gromacs parameter with doc strings.""" self.parameters[key] = value self.params_doc[key] = docstring def set_own_params_runs(self, key, value): """Set own gromacs parameter for program parameters Add spaces to avoid errors """ self.params_runs[key] = ' ' + value + ' ' def set(self, **kwargs): changed_parameters = FileIOCalculator.set(self, **kwargs) if changed_parameters: self.reset() def write_input(self, atoms=None, properties=None, system_changes=None): """Write input parameters to input file.""" FileIOCalculator.write_input(self, atoms, properties, system_changes) #print self.parameters myfile = open(self.label + '.mdp', 'w') for key, val in self.parameters.items(): if val is not None: if (self.params_doc.get(key) == None): docstring = '' else: docstring = self.params_doc[key] myfile.write('%-35s = %s ; %s\n' \ % (key, val, ';' + docstring)) myfile.close() if self.freeze_qm: self.add_freeze_group() def update(self, atoms): """ set atoms and do the calculation """ from ase.io.gromos import write_gromos # performs an update of the atoms self.atoms = atoms.copy() #must be g96 format for accuracy, alternatively binary formats write_gromos(self.label + '.g96', atoms) # does run to get forces and energies self.calculate() def calculate(self, atoms=None, properties=['energy', 'forces'], system_changes=all_changes): """ runs a gromacs-mdrun and gets energy and forces rest below is to make gromacs calculator compactible with ase-Calculator class atoms: Atoms object Contains positions, unit-cell, ... properties: list of str List of what needs to be calculated. Can be any combination of 'energy', 'forces' system_changes: list of str List of what has changed since last calculation. Can be any combination of these five: 'positions', 'numbers', 'cell', 'pbc', 'initial_charges' and 'initial_magmoms'. """ from ase import units self.run() if self.clean: do_clean('#*') # get energy try: os.remove('tmp_ene.del') except: pass command = 'g_energy' + ' ' os.system(command + \ ' -f ' + self.label + '.edr -dp ' + \ ' -o ' + self.label + \ 'Energy.xvg < inputGenergy.txt' + \ ' > /dev/null 2>&1') os.system('tail -n 1 ' + self.label + \ 'Energy.xvg > tmp_ene.del') line = open('tmp_ene.del', 'r').readline() energy = float(line.split()[1]) #We go for ASE units ! #self.energy = energy * units.kJ / units.mol self.results['energy'] = energy * units.kJ / units.mol # energies are about 100 times bigger in Gromacs units # when compared to ase units #get forces try: os.remove('tmp_force.del') except: pass #os.system('gmxdump_d -f gromacs.trr > tmp_force.del 2>/dev/null') command = 'g_traj' + ' ' os.system(command +\ ' -f ' + self.label + '.trr -s ' \ + self.label + '.tpr -of ' \ + ' -fp ' + self.label \ + 'Force.xvg < inputGtraj.txt ' \ + ' > /dev/null 2>&1') lines = open(self.label + 'Force.xvg', 'r').readlines() forces = [] forces.append( np.array([float(f) for f in lines[-1].split()[1:]])) #We go for ASE units !gromacsForce.xvg #self.forces = np.array(forces)/ units.nm * units.kJ / units.mol #self.forces = np.reshape(self.forces, (-1, 3)) tmp_forces = np.array(forces) / units.nm * units.kJ / units.mol tmp_forces = np.reshape(tmp_forces, (-1, 3)) self.results['forces'] = tmp_forces #self.forces = np.array(forces) def add_freeze_group(self): """ Add freeze group (all qm atoms) to the gromacs index file and modify the 'self.base_filename'.mdp file to adopt for freeze group. The qm regions are read from the file index.ndx This is usefull if one makes many moves in MM and then only a few with both qm and mm moving. qse-qm/mm indexing starts from 0 gromacs indexing starts from 1 """ from ase.calculators.ase_qmmm_manyqm import get_qm_atoms index_filename = self.params_runs.get('index_filename') qms = get_qm_atoms(index_filename) infile = open(index_filename, 'r') lines = infile.readlines() infile.close() outfile = open(index_filename, 'w') found = False for line in lines: if ('freezeGroupQM' in line): found = True outfile.write(line) if not found: outfile.write('[ freezeGroupQM ] \n') for myqm in qms: for qmindex in myqm: outfile.write(str(qmindex + 1) + ' ') outfile.write('\n') outfile.close() infile = open(self.label + '.mdp', 'r') lines = infile.readlines() infile.close() outfile = open(self.label + '.mdp', 'w') for line in lines: outfile.write(line) outfile.write('freezegrps = freezeGroupQM \n') outfile.write('freezedim = Y Y Y \n') outfile.close() return def get_command(self): """Return command string for gromacs mdrun. """ command = None if 'GMXCMD' in os.environ: command = self.prefix + os.environ['GMXCMD'] + self.postfix return command python-ase-3.9.1.4567/ase/calculators/general.py0000664000175000017500000000335012553425527021553 0ustar jensjjensj00000000000000 class Calculator: def __init__(self): return def set_atoms(self, atoms): self.atoms = atoms.copy() def get_atoms(self): atoms = self.atoms.copy() atoms.set_calculator(self) return atoms def get_name(self): """Return the name of the calculator (string). """ return self.name def get_version(self): """Return the version of the calculator (string). """ raise NotImplementedError def get_potential_energy(self, atoms, force_consistent=False): self.update(atoms) if force_consistent: return self.energy_free else: return self.energy_zero def get_forces(self, atoms): self.update(atoms) return self.forces def get_stress(self, atoms): self.update(atoms) if self.stress is not None: return self.stress else: raise NotImplementedError def initialize(self, atoms): """Prepare the input files required to start the program (calculator). """ raise NotImplementedError def read(self, atoms): self.positions = atoms.get_positions() self.energy_free, self.energy_zero = self.read_energy() self.forces = self.read_forces(atoms) self.dipole = self.read_dipole() self.fermi = self.read_fermi() self.atoms = atoms.copy() try: self.nbands = self.read_nbands() except NotImplementedError: do_nothing = True except AttributeError: do_nothing = True try: self.stress = self.read_stress() except NotImplementedError: self.stress = None do_nothing = True return python-ase-3.9.1.4567/ase/calculators/interfacechecker.py0000664000175000017500000001414712553425550023425 0ustar jensjjensj00000000000000from __future__ import print_function import traceback import numpy as np from ase import Atoms # This module the InterfaceTester class which tests the extent to # which an object behaves like an ASE calculator. # # It runs the ASE interface methods and performs a few very basic checks # on the returned objects, then writes a list of errors. # # Future improvements: Check that arrays are padded correctly, verify # more information about shapes, maybe do some complicated state # changes and check that the calculator behaves properly. class Args: # This class is just syntantical sugar to pass args and kwargs # easily when testing many methods after one another. def __init__(self, *args, **kwargs): self.args = args self.kwargs = kwargs def unpack(self): return self.args, self.kwargs args = Args class InterfaceChecker: def __init__(self, obj): self.obj = obj self.returnvalues = {} self.errors = [] def _check(self, methname, args=args(), rtype=None): args, kwargs = args.unpack() class Error: def __init__(self, code, error): self.code = code self.error = error self.methname = methname self.txt = traceback.format_exc() self.callstring = None try: meth = getattr(self.obj, methname) except AttributeError as err: return Error('MISSING', err) try: value = meth(*args, **kwargs) except NotImplementedError as err: return Error('not implemented', err) except StandardError as err: return Error(err.__class__.__name__, err) else: self.returnvalues[methname] = value if rtype is not None: if not isinstance(value, rtype): return Error('TYPE', TypeError('got %s but expected %s' % (type(value), rtype))) return None def check(self, methname, args=args(), rtype=None): pargs, kwargs = args.unpack() def get_string_repr(obj): if isinstance(obj, Atoms): return '' else: return repr(obj) pargsstrs = [get_string_repr(obj) for obj in pargs] kwargsstrs = ['%s=%s' % (key, get_string_repr(kwargs[key])) for key in sorted(kwargs)] pargskwargsstr = ', '.join(pargsstrs + kwargsstrs) err = self._check(methname, args, rtype) callstring = '%s(%s)' % (methname, pargskwargsstr) if err is None: status = 'ok' else: status = err.code err.callstring = callstring self.errors.append(err) print('%16s : %s' % (status, callstring)) def check_interface(calc): tester = InterfaceChecker(calc) c = tester.check system = calc.get_atoms() # Methods specified by ase.calculators.interface.Calculator c('get_atoms', rtype=Atoms) c('get_potential_energy', rtype=float) c('get_potential_energy', args(atoms=system), rtype=float) c('get_potential_energy', args(atoms=system, force_consistent=True), rtype=float) c('get_forces', args(system), np.ndarray) c('get_stress', args(system), np.ndarray) c('calculation_required', args(system, []), rtype=bool) # Methods specified by ase.calculators.interface.DFTCalculator c('get_number_of_bands', rtype=int) c('get_xc_functional', rtype=str) c('get_bz_k_points', rtype=np.ndarray) c('get_number_of_spins', rtype=int) c('get_spin_polarized', rtype=bool) c('get_ibz_k_points', rtype=np.ndarray) c('get_k_point_weights', rtype=np.ndarray) c('get_pseudo_density', rtype=np.ndarray) for meth in ['get_pseudo_density', 'get_effective_potential']: c(meth, args(spin=None, pad=False), rtype=np.ndarray) c(meth, args(spin=None, pad=True), rtype=np.ndarray) c(meth, args(spin=0, pad=False), rtype=np.ndarray) spinpol = tester.returnvalues.get('get_spin_polarized') if spinpol: c(meth, args(spin=1, pad=True), rtype=np.ndarray) nbands = tester.returnvalues.get('get_number_of_bands') if nbands is not None and isinstance(nbands, int) and nbands > 0: c('get_pseudo_wave_function', args(band=nbands - 1), rtype=np.ndarray) c('get_pseudo_wave_function', args(band=nbands - 1, kpt=0, spin=0, broadcast=False, pad=False), rtype=np.ndarray) c('get_eigenvalues', args(kpt=0, spin=0), rtype=np.ndarray) c('get_occupation_numbers', args(kpt=0, spin=0), rtype=np.ndarray) c('get_fermi_level', rtype=float) #c('initial_wanner', ........) what the heck? #c('get_wannier_localization_matrix', ...) No. c('get_magnetic_moment', args(atoms=system), rtype=float) #c('get_number_of_grid_points', rtype=tuple) # Hmmmm. Not for now... # Optional methods sometimes invoked by ase.atoms.Atoms c('get_magnetic_moments', rtype=np.ndarray) c('get_charges', rtype=np.ndarray) c('get_potential_energies', rtype=np.ndarray) c('get_stresses', rtype=np.ndarray) c('get_dipole_moment', rtype=np.ndarray) real_errs = [err for err in tester.errors if not isinstance(err.error, NotImplementedError)] if len(real_errs) > 0: print() print('Errors') print('======') for err in tester.errors: print('%s: %s' % (err.code, err.callstring)) print(err.txt) print() def main_gpaw(): from gpaw import GPAW from ase.structure import molecule system = molecule('H2') system.center(vacuum=1.5) system.pbc = 1 calc = GPAW(h=0.3, mode='lcao', txt=None) system.set_calculator(calc) system.get_potential_energy() check_interface(calc) def main_octopus(): from octopus import Octopus from ase.structure import molecule system = molecule('H2') system.center(vacuum=1.5) system.pbc = 1 calc = Octopus() system.set_calculator(calc) system.get_potential_energy() check_interface(calc) if __name__ == '__main__': main_gpaw() python-ase-3.9.1.4567/ase/calculators/eam.py0000664000175000017500000007316512553425526020712 0ustar jensjjensj00000000000000"""Calculator for the Embedded Atom Method Potential""" # eam.py # Embedded Atom Method Potential # These routines integrate with the ASE simulation environment # Paul White (Oct 2012) # UNCLASSIFIED # License: See accompanying license files for details import os import numpy as np from ase.test import NotAvailable from ase.calculators.neighborlist import NeighborList from ase.calculators.calculator import Calculator, all_changes from scipy.interpolate import InterpolatedUnivariateSpline as spline class EAM(Calculator): r""" EAM Interface Documentation Introduction ============ The Embedded Atom Method (EAM) [1]_ is a classical potential which is good for modelling metals, particularly fcc materials. Because it is an equiaxial potential the EAM does not model directional bonds well. However, the Angular Dependent Potential (ADP) [2]_ which is an extended version of EAM is able to model directional bonds and is also included in the EAM calculator. Generally all that is required to use this calculator is to supply a potential file or as a set of functions that describe the potential. The files containing the potentials for this calculator are not included but many suitable potentials can be downloaded from The Interatomic Potentials Repository Project at http://www.ctcms.nist.gov/potentials/ Theory ====== A single element EAM potential is defined by three functions: the embedded energy, electron density and the pair potential. A two element alloy contains the individual three functions for each element plus cross pair interactions. The ADP potential has two additional sets of data to define the dipole and quadrupole directional terms for each alloy and their cross interactions. The total energy `E_{\rm tot}` of an arbitrary arrangement of atoms is given by the EAM potential as .. math:: E_\text{tot} = \sum_i F(\bar\rho_i) + \frac{1}{2}\sum_{i\ne j} \phi(r_{ij}) and .. math:: \bar\rho_i = \sum_j \rho(r_{ij}) where `F` is an embedding function, namely the energy to embed an atom `i` in the combined electron density `\bar\rho_i` which is contributed from each of its neighbouring atoms `j` by an amount `\rho(r_{ij})`, `\phi(r_{ij})` is the pair potential function representing the energy in bond `ij` which is due to the short-range electro-static interaction between atoms, and `r_{ij}` is the distance between an atom and its neighbour for that bond. The ADP potential is defined as .. math:: E_\text{tot} = \sum_i F(\bar\rho_i) + \frac{1}{2}\sum_{i\ne j} \phi(r_{ij}) + \frac{1}{2} \sum_{i,\alpha} (\mu_i^\alpha)^2 + \frac{1}{2} \sum_{i,\alpha,\beta} (\lambda_i^{\alpha\beta})^2 - \frac{1}{6} \sum_i \nu_i^2 where `\mu_i^\alpha` is the dipole vector, `\lambda_i^{\alpha\beta}` is the quadrupole tensor and `\nu_i` is the trace of `\lambda_i^{\alpha\beta}`. Running the Calculator ====================== EAM calculates the cohesive atom energy and forces. Internally the potential functions are defined by splines which may be directly supplied or created by reading the spline points from a data file from which a spline function is created. The LAMMPS compatible ``.alloy`` and ``.adp`` formats are supported. The LAMMPS ``.eam`` format is slightly different from the ``.alloy`` format and is currently not supported. For example:: from ase.calculators.eam import EAM mishin = EAM(potential='Al99.eam.alloy') mishin.write_potential('new.eam.alloy') mishin.plot() slab.set_calculator(mishin) slab.get_potential_energy() slab.get_forces() The breakdown of energy contribution from the indvidual components are stored in the calculator instance ``.results['energy_components']`` Arguments ========= ========================= ==================================================== Keyword Description ========================= ==================================================== ``potential`` file of potential in ``.alloy`` or ``.adp`` format (This is generally all you need to supply) ``elements[N]`` array of N element abbreviations ``embedded_energy[N]`` arrays of embedded energy functions ``electron_density[N]`` arrays of electron density functions ``phi[N,N]`` arrays of pair potential functions ``d_embedded_energy[N]`` arrays of derivative embedded energy functions ``d_electron_density[N]`` arrays of derivative electron density functions ``d_phi[N,N]`` arrays of derivative pair potentials functions ``d[N,N], q[N,N]`` ADP dipole and quadrupole function ``d_d[N,N], d_q[N,N]`` ADP dipole and quadrupole derivative functions ``skin`` skin distance passed to NeighborList(). If no atom has moved more than the skin-distance since the last call to the ``update()`` method then the neighbor list can be reused. Defaults to 1.0. ``form`` the form of the potential ``alloy`` or ``adp``. This will be determined from the file suffix or must be set if using equations ========================= ==================================================== Additional parameters for writing potential files ================================================= The following parameters are only required for writing a potential in ``.alloy`` or ``.adp`` format file. ========================= ==================================================== Keyword Description ========================= ==================================================== ``header`` Three line text header. Default is standard message. ``Z[N]`` Array of atomic number of each element ``mass[N]`` Atomic mass of each element ``a[N]`` Array of lattice parameters for each element ``lattice[N]`` Lattice type ``nrho`` No. of rho samples along embedded energy curve ``drho`` Increment for sampling density ``nr`` No. of radial points along density and pair potential curves ``dr`` Increment for sampling radius ========================= ==================================================== Special features ================ ``.plot()`` Plots the individual functions. This may be called from multiple EAM potentials to compare the shape of the individual curves. This function requires the installation of the Matplotlib libraries. Notes/Issues ============= * Although currently not fast, this calculator can be good for trying small calculations or for creating new potentials by matching baseline data such as from DFT results. The format for these potentials is compatible with LAMMPS_ and so can be used either directly by LAMMPS or with the ASE LAMMPS calculator interface. * Supported formats are the LAMMPS_ ``.alloy`` and ``.adp``. The ``.eam`` format is currently not supported. The form of the potential will be determined from the file suffix. * Any supplied values will override values read from the file. * The derivative functions, if supplied, are only used to calculate forces. * There is a bug in early versions of scipy that will cause eam.py to crash when trying to evaluate splines of a potential with one neighbor such as caused by evaluating a dimer. .. _LAMMPS: http://lammps.sandia.gov/ .. [1] M.S. Daw and M.I. Baskes, Phys. Rev. Letters 50 (1983) 1285. .. [2] Y. Mishin, M.J. Mehl, and D.A. Papaconstantopoulos, Acta Materialia 53 2005 4029--4041. End EAM Interface Documentation """ implemented_properties = ['energy', 'forces'] default_parameters = dict( skin=1.0, potential=None, header=[b'EAM/ADP potential file\n', b'Generated from eam.py\n', b'blank\n']) def __init__(self, restart=None, ignore_bad_restart_file=False, label=os.curdir, atoms=None, **kwargs): if 'potential' in kwargs: self.read_potential(kwargs['potential']) Calculator.__init__(self, restart, ignore_bad_restart_file, label, atoms, **kwargs) valid_args = ('potential', 'elements', 'header', 'drho', 'dr', 'cutoff', 'atomic_number', 'mass', 'a', 'lattice', 'embedded_energy', 'electron_density', 'phi', # derivatives 'd_embedded_energy', 'd_electron_density', 'd_phi', 'd', 'q', 'd_d', 'd_q', # adp terms 'skin', 'form', 'Z', 'nr', 'nrho', 'mass') # set any additional keyword arguments for arg, val in self.parameters.items(): if arg in valid_args: setattr(self, arg, val) else: raise RuntimeError('unknown keyword arg "%s" : not in %s' % (arg, valid_args)) def set_form(self, fileobj): """set the form variable based on the file name suffix""" extension = os.path.splitext(fileobj)[1] if extension == '.eam': self.form = 'eam' raise NotImplementedError elif extension == '.alloy': self.form = 'alloy' elif extension == '.adp': self.form = 'adp' else: raise RuntimeError('unknown file extension type: %s' % extension) def read_potential(self, fileobj): """Reads a LAMMPS EAM file in alloy or adp format and creates the interpolation functions from the data """ if isinstance(fileobj, str): f = open(fileobj) self.set_form(fileobj) else: f = fileobj lines = f.readlines() self.header = lines[:3] i = 3 # make the data one long line so as not to care how its formatted data = [] for line in lines[i:]: data.extend(line.split()) self.Nelements = int(data[0]) d = 1 self.elements = data[d:d + self.Nelements] d += self.Nelements self.nrho = int(data[d]) self.drho = float(data[d + 1]) self.nr = int(data[d + 2]) self.dr = float(data[d + 3]) self.cutoff = float(data[d + 4]) self.embedded_data = np.zeros([self.Nelements, self.nrho]) self.density_data = np.zeros([self.Nelements, self.nr]) self.Z = np.zeros([self.Nelements], dtype=int) self.mass = np.zeros([self.Nelements]) self.a = np.zeros([self.Nelements]) self.lattice = [] d += 5 # reads in the part of the eam file for each element for elem in range(self.Nelements): self.Z[elem] = int(data[d]) self.mass[elem] = float(data[d + 1]) self.a[elem] = float(data[d + 2]) self.lattice.append(data[d + 3]) d += 4 self.embedded_data[elem] = np.float_(data[d:(d + self.nrho)]) d += self.nrho self.density_data[elem] = np.float_(data[d:(d + self.nr)]) d += self.nr # reads in the r*phi data for each interaction between elements self.rphi_data = np.zeros([self.Nelements, self.Nelements, self.nr]) for i in range(self.Nelements): for j in range(i + 1): self.rphi_data[j, i] = np.float_(data[d:(d + self.nr)]) d += self.nr self.r = np.arange(0, self.nr) * self.dr self.rho = np.arange(0, self.nrho) * self.drho self.set_splines() if (self.form == 'adp'): self.read_adp_data(data, d) self.set_adp_splines() def set_splines(self): # this section turns the file data into three functions (and # derivative functions) that define the potential self.embedded_energy = np.empty(self.Nelements, object) self.electron_density = np.empty(self.Nelements, object) self.d_embedded_energy = np.empty(self.Nelements, object) self.d_electron_density = np.empty(self.Nelements, object) for i in range(self.Nelements): self.embedded_energy[i] = spline(self.rho, self.embedded_data[i], k=3) self.electron_density[i] = spline(self.r, self.density_data[i], k=3) self.d_embedded_energy[i] = self.deriv(self.embedded_energy[i]) self.d_electron_density[i] = self.deriv(self.electron_density[i]) self.phi = np.empty([self.Nelements, self.Nelements], object) self.d_phi = np.empty([self.Nelements, self.Nelements], object) # ignore the first point of the phi data because it is forced # to go through zero due to the r*phi format in alloy and adp for i in range(self.Nelements): for j in range(i, self.Nelements): if self.form == 'eam': # not stored as rphi # should we ignore the first point for eam ? raise RuntimeError('.eam format not yet supported') self.phi[i, j] = spline( self.r[1:], self.rphi_data[i, j][1:], k=3) else: self.phi[i, j] = spline( self.r[1:], self.rphi_data[i, j][1:] / self.r[1:], k=3) self.d_phi[i, j] = self.deriv(self.phi[i, j]) if j != i: self.phi[j, i] = self.phi[i, j] self.d_phi[j, i] = self.d_phi[i, j] def set_adp_splines(self): self.d = np.empty([self.Nelements, self.Nelements], object) self.d_d = np.empty([self.Nelements, self.Nelements], object) self.q = np.empty([self.Nelements, self.Nelements], object) self.d_q = np.empty([self.Nelements, self.Nelements], object) for i in range(self.Nelements): for j in range(i, self.Nelements): self.d[i, j] = spline(self.r[1:], self.d_data[i, j][1:], k=3) self.d_d[i, j] = self.deriv(self.d[i, j]) self.q[i, j] = spline(self.r[1:], self.q_data[i, j][1:], k=3) self.d_q[i, j] = self.deriv(self.q[i, j]) # make symmetrical if j != i: self.d[j, i] = self.d[i, j] self.d_d[j, i] = self.d_d[i, j] self.q[j, i] = self.q[i, j] self.d_q[j, i] = self.d_q[i, j] def read_adp_data(self, data, d): """read in the extra adp data from the potential file""" self.d_data = np.zeros([self.Nelements, self.Nelements, self.nr]) # should be non symetrical combinations of 2 for i in range(self.Nelements): for j in range(i + 1): self.d_data[j, i] = data[d:d + self.nr] d += self.nr self.q_data = np.zeros([self.Nelements, self.Nelements, self.nr]) # should be non symetrical combinations of 2 for i in range(self.Nelements): for j in range(i + 1): self.q_data[j, i] = data[d:d + self.nr] d += self.nr def write_potential(self, filename, nc=1, numformat='%.8e'): """Writes out the potential in the format given by the form variable to 'filename' with a data format that is nc columns wide. Note: array lengths need to be an exact multiple of nc """ f = open(filename, 'wb') assert self.nr % nc == 0 assert self.nrho % nc == 0 for line in self.header: f.write(line) f.write('{0} '.format(self.Nelements).encode()) f.write(' '.join(self.elements).encode() + b'\n') f.write(('%d %f %d %f %f \n' % (self.nrho, self.drho, self.nr, self.dr, self.cutoff)).encode()) # start of each section for each element # rs = np.linspace(0, self.nr * self.dr, self.nr) # rhos = np.linspace(0, self.nrho * self.drho, self.nrho) rs = np.arange(0, self.nr) * self.dr rhos = np.arange(0, self.nrho) * self.drho for i in range(self.Nelements): f.write(('%d %f %f %s\n' % (self.Z[i], self.mass[i], self.a[i], str(self.lattice[i]))).encode()) np.savetxt(f, self.embedded_energy[i](rhos).reshape(self.nrho // nc, nc), fmt=nc * [numformat]) np.savetxt(f, self.electron_density[i](rs).reshape(self.nr // nc, nc), fmt=nc * [numformat]) # write out the pair potentials in Lammps DYNAMO setfl format # as r*phi for alloy format for i in range(self.Nelements): for j in range(i, self.Nelements): np.savetxt(f, (rs * self.phi[i, j](rs)).reshape(self.nr // nc, nc), fmt=nc * [numformat]) if self.form == 'adp': # these are the u(r) or dipole values for i in range(self.Nelements): for j in range(i + 1): np.savetxt(f, self.d_data[i, j]) # these are the w(r) or quadrupole values for i in range(self.Nelements): for j in range(i + 1): np.savetxt(f, self.q_data[i, j]) f.close() def update(self, atoms): # check all the elements are available in the potential self.Nelements = len(self.elements) elements = np.unique(atoms.get_chemical_symbols()) unavailable = np.logical_not( np.array([item in self.elements for item in elements])) if np.any(unavailable): raise RuntimeError('These elements are not in the potential: %s' % elements[unavailable]) # cutoffs need to be a vector for NeighborList cutoffs = self.cutoff * np.ones(len(atoms)) # convert the elements to an index of the position # in the eam format self.index = np.array([self.elements.index(el) for el in atoms.get_chemical_symbols()]) self.pbc = atoms.get_pbc() # since we need the contribution of all neighbors to the # local electron density we cannot just calculate and use # one way neighbors self.neighbors = NeighborList(cutoffs, skin=self.parameters.skin, self_interaction=False, bothways=True) self.neighbors.update(atoms) def calculate(self, atoms=None, properties=['energy'], system_changes=all_changes): """EAM Calculator atoms: Atoms object Contains positions, unit-cell, ... properties: list of str List of what needs to be calculated. Can be any combination of 'energy', 'forces' system_changes: list of str List of what has changed since last calculation. Can be any combination of these five: 'positions', 'numbers', 'cell', 'pbc', 'initial_charges' and 'initial_magmoms'. """ Calculator.calculate(self, atoms, properties, system_changes) # we shouldn't really recalc if charges or magmos change if len(system_changes) > 0: # something wrong with this way self.update(self.atoms) self.calculate_energy(self.atoms) if 'forces' in properties: self.calculate_forces(self.atoms) # check we have all the properties requested for property in properties: if property not in self.results: if property is 'energy': self.calculate_energy(self.atoms) if property is 'forces': self.calculate_forces(self.atoms) # we need to remember the previous state of parameters # if 'potential' in parameter_changes and potential != None: # self.read_potential(potential) def calculate_energy(self, atoms): """Calculate the energy the energy is made up of the ionic or pair interaction and the embedding energy of each atom into the electron cloud generated by its neighbors """ pair_energy = 0.0 embedding_energy = 0.0 mu_energy = 0.0 lam_energy = 0.0 trace_energy = 0.0 self.total_density = np.zeros(len(atoms)) if (self.form == 'adp'): self.mu = np.zeros([len(atoms), 3]) self.lam = np.zeros([len(atoms), 3, 3]) for i in range(len(atoms)): # this is the atom to be embedded neighbors, offsets = self.neighbors.get_neighbors(i) offset = np.dot(offsets, atoms.get_cell()) rvec = (atoms.positions[neighbors] + offset - atoms.positions[i]) # calculate the distance to the nearest neighbors r = np.sqrt(np.sum(np.square(rvec), axis=1)) # fast # r = np.apply_along_axis(np.linalg.norm, 1, rvec) # sloow nearest = np.arange(len(r))[r <= self.cutoff] for j_index in range(self.Nelements): use = self.index[neighbors[nearest]] == j_index if not use.any(): continue pair_energy += np.sum(self.phi[self.index[i], j_index]( r[nearest][use])) / 2. density = np.sum( self.electron_density[j_index](r[nearest][use])) self.total_density[i] += density if self.form == 'adp': self.mu[i] += self.adp_dipole( r[nearest][use], rvec[nearest][use], self.d[self.index[i], j_index]) self.lam[i] += self.adp_quadrupole( r[nearest][use], rvec[nearest][use], self.q[self.index[i], j_index]) # add in the electron embedding energy embedding_energy += self.embedded_energy[self.index[i]]( self.total_density[i]) components = dict(pair=pair_energy, embedding=embedding_energy) if self.form == 'adp': mu_energy += np.sum(self.mu ** 2) / 2. lam_energy += np.sum(self.lam ** 2) / 2. for i in range(len(atoms)): # this is the atom to be embedded trace_energy -= np.sum(self.lam[i].trace() ** 2) / 6. adp_result = dict(adp_mu=mu_energy, adp_lam=lam_energy, adp_trace=trace_energy) components.update(adp_result) self.positions = atoms.positions.copy() self.cell = atoms.get_cell().copy() energy = 0.0 for i in components.keys(): energy += components[i] self.energy_free = energy self.energy_zero = energy self.results['energy_components'] = components self.results['energy'] = energy def calculate_forces(self, atoms): # calculate the forces based on derivatives of the three EAM functions self.update(atoms) self.results['forces'] = np.zeros((len(atoms), 3)) for i in range(len(atoms)): # this is the atom to be embedded neighbors, offsets = self.neighbors.get_neighbors(i) offset = np.dot(offsets, atoms.get_cell()) # create a vector of relative positions of neighbors rvec = atoms.positions[neighbors] + offset - atoms.positions[i] r = np.sqrt(np.sum(np.square(rvec), axis=1)) nearest = np.arange(len(r))[r < self.cutoff] d_embedded_energy_i = self.d_embedded_energy[ self.index[i]](self.total_density[i]) urvec = rvec.copy() # unit directional vector for j in np.arange(len(neighbors)): urvec[j] = urvec[j] / r[j] for j_index in range(self.Nelements): use = self.index[neighbors[nearest]] == j_index if not use.any(): continue rnuse = r[nearest][use] density_j = self.total_density[neighbors[nearest][use]] scale = (self.d_phi[self.index[i], j_index](rnuse) + (d_embedded_energy_i * self.d_electron_density[j_index](rnuse)) + (self.d_embedded_energy[j_index](density_j) * self.d_electron_density[self.index[i]](rnuse))) self.results['forces'][i] += np.dot(scale, urvec[nearest][use]) if (self.form == 'adp'): adp_forces = self.angular_forces( self.mu[i], self.mu[neighbors[nearest][use]], self.lam[i], self.lam[neighbors[nearest][use]], rnuse, rvec[nearest][use], self.index[i], j_index) self.results['forces'][i] += adp_forces def angular_forces(self, mu_i, mu, lam_i, lam, r, rvec, form1, form2): # calculate the extra components for the adp forces # rvec are the relative positions to atom i psi = np.zeros(mu.shape) for gamma in range(3): term1 = (mu_i[gamma] - mu[:, gamma]) * self.d[form1][form2](r) term2 = np.sum((mu_i - mu) * self.d_d[form1][form2](r)[:, np.newaxis] * (rvec * rvec[:, gamma][:, np.newaxis] / r[:, np.newaxis]), axis=1) term3 = 2 * np.sum((lam_i[:, gamma] + lam[:, :, gamma]) * rvec * self.q[form1][form2](r)[:, np.newaxis], axis=1) term4 = 0.0 for alpha in range(3): for beta in range(3): rs = rvec[:, alpha] * rvec[:, beta] * rvec[:, gamma] term4 += ((lam_i[alpha, beta] + lam[:, alpha, beta]) * self.d_q[form1][form2](r) * rs) / r term5 = ((lam_i.trace() + lam.trace(axis1=1, axis2=2)) * (self.d_q[form1][form2](r) * r + 2 * self.q[form1][form2](r)) * rvec[:, gamma]) / 3. # the minus for term5 is a correction on the adp # formulation given in the 2005 Mishin Paper and is posted # on the NIST website with the AlH potential psi[:, gamma] = term1 + term2 + term3 + term4 - term5 return np.sum(psi, axis=0) def adp_dipole(self, r, rvec, d): # calculate the dipole contribution mu = np.sum((rvec * d(r)[:, np.newaxis]), axis=0) return mu # sign to agree with lammps def adp_quadrupole(self, r, rvec, q): # slow way of calculating the quadrupole contribution r = np.sqrt(np.sum(rvec ** 2, axis=1)) lam = np.zeros([rvec.shape[0], 3, 3]) qr = q(r) for alpha in range(3): for beta in range(3): lam[:, alpha, beta] += qr * rvec[:, alpha] * rvec[:, beta] return np.sum(lam, axis=0) def deriv(self, spline): """Wrapper for extracting the derivative from a spline""" def d_spline(aspline): return spline(aspline, 1) return d_spline def plot(self, name=''): """Plot the individual curves""" try: import matplotlib.pyplot as plt except ImportError: raise NotAvailable('This needs matplotlib module.') if self.form == 'eam' or self.form == 'alloy': nrow = 2 elif self.form == 'adp': nrow = 3 else: raise RuntimeError('Unknown form of potential: %s' % self.form) if hasattr(self, 'r'): r = self.r else: r = np.linspace(0, self.cutoff, 50) if hasattr(self, 'rho'): rho = self.rho else: rho = np.linspace(0, 10.0, 50) plt.subplot(nrow, 2, 1) self.elem_subplot(rho, self.embedded_energy, r'$\rho$', r'Embedding Energy $F(\bar\rho)$', name, plt) plt.subplot(nrow, 2, 2) self.elem_subplot(r, self.electron_density, r'$r$', r'Electron Density $\rho(r)$', name, plt) plt.subplot(nrow, 2, 3) self.multielem_subplot(r, self.phi, r'$r$', r'Pair Potential $\phi(r)$', name, plt) plt.ylim(-1.0, 1.0) # need reasonable values if self.form == 'adp': plt.subplot(nrow, 2, 5) self.multielem_subplot(r, self.d, r'$r$', r'Dipole Energy', name, plt) plt.subplot(nrow, 2, 6) self.multielem_subplot(r, self.q, r'$r$', r'Quadrupole Energy', name, plt) plt.plot() def elem_subplot(self, curvex, curvey, xlabel, ylabel, name, plt): plt.xlabel(xlabel) plt.ylabel(ylabel) for i in np.arange(self.Nelements): label = name + ' ' + self.elements[i] plt.plot(curvex, curvey[i](curvex), label=label) plt.legend() def multielem_subplot(self, curvex, curvey, xlabel, ylabel, name, plt): plt.xlabel(xlabel) plt.ylabel(ylabel) for i in np.arange(self.Nelements): for j in np.arange(i + 1): label = name + ' ' + self.elements[i] + '-' + self.elements[j] plt.plot(curvex, curvey[i, j](curvex), label=label) plt.legend() python-ase-3.9.1.4567/ase/calculators/dacapo.py0000664000175000017500000001552312553425527021372 0ustar jensjjensj00000000000000import numpy as np from ase.old import OldASEListOfAtomsWrapper try: import Numeric as num except ImportError: pass def np2num(a, typecode=None): if num.__version__ > '23.8': return num.array(a, typecode) if typecode is None: typecode = num.Float b = num.fromstring(a.tostring(), typecode) b.shape = a.shape return b def restart(filename, **kwargs): calc = Dacapo(filename, **kwargs) atoms = calc.get_atoms() return atoms, calc class Dacapo: def __init__(self, filename=None, stay_alive=False, stress=False, **kwargs): self.kwargs = kwargs self.stay_alive = stay_alive self.stress = stress if filename is not None: from Dacapo import Dacapo self.loa = Dacapo.ReadAtoms(filename, **kwargs) self.calc = self.loa.GetCalculator() else: self.loa = None self.calc = None self.pps = [] def set_pp(self, Z, path): self.pps.append((Z, path)) def set_txt(self, txt): if self.calc is None: self.kwargs['txtout'] = txt else: self.calc.SetTxtFile(txt) def set_nc(self, nc): if self.calc is None: self.kwargs['out'] = nc else: self.calc.SetNetCDFFile(nc) def update(self, atoms): from Dacapo import Dacapo if self.calc is None: if 'nbands' not in self.kwargs: n = sum([valence[atom.symbol] for atom in atoms]) self.kwargs['nbands'] = int(n * 0.65) + 4 magmoms = atoms.get_initial_magnetic_moments() if magmoms.any(): self.kwargs['spinpol'] = True self.calc = Dacapo(**self.kwargs) if self.stay_alive: self.calc.StayAliveOn() else: self.calc.StayAliveOff() if self.stress: self.calc.CalculateStress() for Z, path in self.pps: self.calc.SetPseudoPotential(Z, path) if self.loa is None: from ASE import Atom, ListOfAtoms numbers = atoms.get_atomic_numbers() positions = atoms.get_positions() magmoms = atoms.get_initial_magnetic_moments() self.loa = ListOfAtoms([Atom(Z=numbers[a], position=positions[a], magmom=magmoms[a]) for a in range(len(atoms))], cell=np2num(atoms.get_cell()), periodic=tuple(atoms.get_pbc())) self.loa.SetCalculator(self.calc) else: self.loa.SetCartesianPositions(np2num(atoms.get_positions())) self.loa.SetUnitCell(np2num(atoms.get_cell()), fix=True) def get_atoms(self): atoms = OldASEListOfAtomsWrapper(self.loa).copy() atoms.set_calculator(self) return atoms def get_potential_energy(self, atoms): self.update(atoms) return self.calc.GetPotentialEnergy() def get_forces(self, atoms): self.update(atoms) return np.array(self.calc.GetCartesianForces()) def get_stress(self, atoms): self.update(atoms) stress = np.array(self.calc.GetStress()) if stress.ndim == 2: return stress.ravel()[[0, 4, 8, 5, 2, 1]] else: return stress def calculation_required(self, atoms, quantities): if self.calc is None: return True if atoms != self.get_atoms(): return True return False def get_number_of_bands(self): return self.calc.GetNumberOfBands() def get_k_point_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_magnetic_moment(self): return self.calc.GetMagneticMoment() def get_number_of_electrons(self): return self.calc.GetValenceElectrons() def get_number_of_grid_points(self): return np.array(self.get_pseudo_wave_function(0, 0, 0).shape) def get_pseudo_density(self, spin=0): return np.array(self.calc.GetDensityArray(s)) def get_pseudo_wave_function(self, band=0, kpt=0, spin=0, pad=True): kpt_c = self.get_bz_k_points()[kpt] state = self.calc.GetElectronicStates().GetState(band=band, spin=spin, kptindex=kpt) # Get wf, without bloch 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_c == 0): return wave coord = state.GetCoordinates() phase = coord[0] * kpt_c[0] + coord[1] * kpt_c[1] + coord[2] * kpt_c[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, np2num(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 valence = { 'H': 1, 'B': 3, 'C': 4, 'N': 5, 'O': 6, 'Li': 1, 'Na': 1, 'K': 9, 'Mg': 8, 'Ca': 10, 'Sr': 10, 'Al': 3, 'Ga': 13, 'Sc': 11, 'Ti': 12, 'V': 13, 'Cr': 14, 'Mn': 7, 'Fe': 8, 'Co': 9, 'Ni': 10, 'Cu': 11, 'Zn': 12, 'Y': 11, 'Zr': 12, 'Nb': 13, 'Mo': 6, 'Ru': 8, 'Rh': 9, 'Pd': 10, 'Ag': 11, 'Cd': 12, 'Ir': 9, 'Pt': 10, 'Au': 11, } python-ase-3.9.1.4567/ase/calculators/morse.py0000664000175000017500000000272612553425527021271 0ustar jensjjensj00000000000000import numpy as np from math import exp, sqrt from ase.calculators.calculator import Calculator class MorsePotential(Calculator): """Morse potential. Default values chosen to be similar as Lennard-Jones. """ implemented_properties = ['energy', 'forces'] default_parameters = {'epsilon': 1.0, 'rho0': 6.0, 'r0': 1.0} nolabel = True def __init__(self, **kwargs): Calculator.__init__(self, **kwargs) def calculate(self, atoms=None, properties=['energy'], system_changes=['positions', 'numbers', 'cell', 'pbc', 'charges','magmoms']): Calculator.calculate(self, atoms, properties, system_changes) epsilon = self.parameters.epsilon rho0 = self.parameters.rho0 r0 = self.parameters.r0 positions = self.atoms.get_positions() energy = 0.0 forces = np.zeros((len(self.atoms), 3)) preF = 2 * epsilon * rho0 / r0 for i1, p1 in enumerate(positions): for i2, p2 in enumerate(positions[:i1]): diff = p2 - p1 r = sqrt(np.dot(diff, diff)) expf = exp(rho0 * (1.0 - r / r0)) energy += epsilon * expf * (expf - 2) F = preF * expf * (expf - 1) * diff / r forces[i1] -= F forces[i2] += F self.results['energy'] = energy self.results['forces'] = forces python-ase-3.9.1.4567/ase/calculators/test.py0000664000175000017500000000762112553425527021122 0ustar jensjjensj00000000000000from math import pi import numpy as np from ase.atoms import Atoms from ase.calculators.calculator import Calculator def make_test_dft_calculation(): a = b = 2.0 c = 6.0 atoms = Atoms(positions=[(0, 0, c / 2)], symbols='H', pbc=(1, 1, 0), cell=(a, b, c), calculator=TestCalculator()) return atoms class TestCalculator: def __init__(self, nk=8): assert nk % 2 == 0 bzk = [] weights = [] ibzk = [] w = 1.0 / nk**2 for i in range(-nk + 1, nk, 2): for j in range(-nk + 1, nk, 2): k = (0.5 * i / nk, 0.5 * j / nk, 0) bzk.append(k) if i >= j > 0: ibzk.append(k) if i == j: weights.append(4 * w) else: weights.append(8 * w) assert abs(sum(weights) - 1.0) < 1e-12 self.bzk = np.array(bzk) self.ibzk = np.array(ibzk) self.weights = np.array(weights) # Calculate eigenvalues and wave functions: self.init() def init(self): nibzk = len(self.weights) nbands = 1 V = -1.0 self.eps = 2 * V * (np.cos(2 * pi * self.ibzk[:, 0]) + np.cos(2 * pi * self.ibzk[:, 1])) self.eps.shape = (nibzk, nbands) self.psi = np.zeros((nibzk, 20, 20, 60), complex) phi = np.empty((2, 2, 20, 20, 60)) z = np.linspace(-1.5, 1.5, 60, endpoint=False) for i in range(2): x = np.linspace(0, 1, 20, endpoint=False) - i for j in range(2): y = np.linspace(0, 1, 20, endpoint=False) - j r = (((x[:, None]**2 + y**2)[:, :, None] + z**2)**0.5).clip(0, 1) phi = 1.0 - r**2 * (3.0 - 2.0 * r) phase = np.exp(pi * 2j * np.dot(self.ibzk, (i, j, 0))) self.psi += phase[:, None, None, None] * phi def get_pseudo_wave_function(self, band=0, kpt=0, spin=0): assert spin == 0 and band == 0 return self.psi[kpt] def get_eigenvalues(self, kpt=0, spin=0): assert spin == 0 return self.eps[kpt] def get_number_of_bands(self): return 1 def get_k_point_weights(self): return self.weights def get_number_of_spins(self): return 1 def get_fermi_level(self): return 0.0 def get_pseudo_density(self): n = 0.0 for w, eps, psi in zip(self.weights, self.eps[:, 0], self.psi): if eps >= 0.0: continue n += w * (psi * psi.conj()).real n[1:] += n[:0:-1].copy() n[:, 1:] += n[:, :0:-1].copy() n += n.transpose((1, 0, 2)).copy() n /= 8 return n class TestPotential(Calculator): implemented_properties = ['energy', 'forces'] def calculate(self, atoms, properties, system_changes): Calculator.calculate(self, atoms, properties, system_changes) E = 0.0 R = atoms.positions F = np.zeros_like(R) for a, r in enumerate(R): D = R - r d = (D**2).sum(1)**0.5 x = d - 1.0 E += np.vdot(x, x) d[a] = 1 F -= (x / d)[:, None] * D energy = 0.25 * E self.results = {'energy': energy, 'forces': F} def numeric_force(atoms, a, i, d=0.001): """Evaluate force along i'th axis on a'th atom using finite difference. This will trigger two calls to get_potential_energy(), with atom a moved plus/minus d in the i'th axial direction, respectively. """ p0 = atoms.positions[a, i] atoms.positions[a, i] += d eplus = atoms.get_potential_energy() atoms.positions[a, i] -= 2 * d eminus = atoms.get_potential_energy() atoms.positions[a, i] = p0 return (eminus - eplus) / (2 * d) python-ase-3.9.1.4567/ase/calculators/castep.py0000664000175000017500000023656512553425527021435 0ustar jensjjensj00000000000000# -*- coding: utf-8 -*- from __future__ import print_function """This module defines an interface to CASTEP for use by the ASE (Webpage: http://wiki.fysik.dtu.dk/ase) Authors: Max Hoffmann, max.hoffmann@ch.tum.de Jörg Meyer, joerg.meyer@ch.tum.de """ __all__ = [ 'Castep', 'CastepCell', 'CastepParam', 'create_castep_keywords'] contact_email = 'max.hoffmann@ch.tum.de' from copy import deepcopy import difflib import numpy as np import os import re import shutil import subprocess import sys import tempfile import time import ase from ase.calculators.general import Calculator from ase.constraints import FixCartesian from ase.parallel import paropen # Adapt import path to give local versions of castep_keywords # a higher priority, assuming that personal folder will be # standardized at ~/.ase, watch [ase-developers] sys.path = ['', os.path.expanduser('~/.ase'), os.path.join(ase.__path__[0], 'calculators')] + sys.path class Castep(Calculator): r""" CASTEP Interface Documentation Introduction ============ CASTEP_ [1]_ W_ is a software package which uses density functional theory to provide a good atomic-level description of all manner of materials and molecules. CASTEP can give information about total energies, forces and stresses on an atomic system, as well as calculating optimum geometries, band structures, optical spectra, phonon spectra and much more. It can also perform molecular dynamics simulations. The CASTEP calculator interface class offers intuitive access to all CASTEP settings and most results. All CASTEP specific settings are accessible via attribute access (*i.e*. ``calc.param.keyword = ...`` or ``calc.cell.keyword = ...``) Getting Started: ================ Set the environment variables appropriately for your system. >>> export CASTEP_COMMAND=' ... ' >>> export CASTEP_PP_PATH=' ... ' Note: alternatively to CASTEP_PP_PATH one can set PSPOT_DIR as CASTEP consults this by default, i.e. >>> export PSPOT_DIR=' ... ' Running the Calculator ====================== The default initialization command for the CASTEP calculator is .. class:: Castep(directory='CASTEP', label='castep') To do a minimal run one only needs to set atoms, this will use all default settings of CASTEP, meaning LDA, singlepoint, etc.. With a generated castep_keywords.py in place all options are accessible by inspection, *i.e.* tab-completion. This works best when using ``ipython``. All options can be accessed via ``calc.param.`` or ``calc.cell.`` and documentation is printed with ``calc.param. ?`` or ``calc.cell. ?``. All options can also be set directly using ``calc.keyword = ...`` or ``calc.KEYWORD = ...`` or even ``calc.KeYwOrD`` or directly as named arguments in the call to the constructor (*e.g.* ``Castep(task='GeometryOptimization')``). All options that go into the ``.param`` file are held in an ``CastepParam`` instance, while all options that go into the ``.cell`` file and don't belong to the atoms object are held in an ``CastepCell`` instance. Each instance can be created individually and can be added to calculators by attribute assignment, *i.e.* ``calc.param = param`` or ``calc.cell = cell``. All internal variables of the calculator start with an underscore (_). All cell attributes that clearly belong into the atoms object are blocked. Setting ``calc.atoms_attribute`` (*e.g.* ``= positions``) is sent directly to the atoms object. Arguments: ========== ========================= ==================================================== Keyword Description ========================= ==================================================== ``directory`` The relative path where all input and output files will be placed. If this does not exist, it will be created. Existing directories will be moved to directory-TIMESTAMP unless self._rename_existing_dir is set to false. ``label`` The prefix of .param, .cell, .castep, etc. files. ========================= ==================================================== Additional Settings =================== ========================= ==================================================== Internal Setting Description ========================= ==================================================== ``_castep_command`` (``=castep``): the actual shell command used to call CASTEP. ``_check_checkfile`` (``=True``): this makes write_param() only write a continue or reuse statement if the addressed .check or .castep_bin file exists in the directory. ``_copy_pspots`` (``=False``): if set to True the calculator will actually copy the needed pseudo-potential (\*.usp) file, usually it will only create symlinks. ``_export_settings`` (``=True``): if this is set to True, all calculator internal settings shown here will be included in the .param in a comment line (#) and can be read again by merge_param. merge_param can be forced to ignore this directive using the optional argument ``ignore_internal_keys=True``. ``_force_write`` (``=True``): this controls wether the \*cell and \*param will be overwritten. ``_prepare_input_only`` (``=False``): If set to True, the calculator will create \*cell und \*param file but not start the calculation itself. If this is used to prepare jobs locally and run on a remote cluster it is recommended to set ``_copy_pspots = True``. ``_castep_pp_path`` (``='.'``) : the place where the calculator will look for pseudo-potential files. ``_rename_existing_dir`` (``=True``) : when using a new instance of the calculator, this will move directories out of the way that would be overwritten otherwise, appending a date string. ``_set_atoms`` (``=False``) : setting this to True will overwrite any atoms object previously attached to the calculator when reading a \.castep file. By de- fault, the read() function will only create a new atoms object if none has been attached and other- wise try to assign forces etc. based on the atom's positions. ``_set_atoms=True`` could be necessary if one uses CASTEP's internal geometry optimization (``calc.param.task='GeometryOptimization'``) because then the positions get out of sync. *Warning*: this option is generally not recommended unless one knows one really needs it. There should never be any need, if CASTEP is used as a single-point calculator. ``_track_output`` (``=False``) : if set to true, the interface will append a number to the label on all input and output files, where n is the number of calls to this instance. *Warning*: this setting may con- sume a lot more disk space because of the additio- nal \*check files. ``_try_reuse`` (``=_track_output``) : when setting this, the in- terface will try to fetch the reuse file from the previous run even if _track_output is True. By de- fault it is equal to _track_output, but may be overridden. Since this behavior may not always be desirable for single-point calculations. Regular reuse for *e.g.* a geometry-optimization can be achieved by setting ``calc.param.reuse = True``. ========================= ==================================================== Special features: ================= ``.dryrun_ok()`` Runs ``castep_command seed -dryrun`` in a temporary directory return True if all variables initialized ok. This is a fast way to catch errors in the input. Afterwards _kpoints_used is set. ``.merge_param()`` Takes a filename or filehandler of a .param file or CastepParam instance and merges it into the current calculator instance, overwriting current settings ``.keyword.clear()`` Can be used on any option like ``calc.param.keyword.clear()`` or ``calc.cell.keyword.clear()`` to return to the CASTEP default. ``.initialize()`` Creates all needed input in the ``_directory``. This can then copied to and run in a place without ASE or even python. ``.set_pspot('')`` This automatically sets the pseudo-potential for all present species to *_.usp*. Make sure that ``_castep_pp_path`` is set correctly. ``print(calc)`` Prints a short summary of the calculator settings and atoms. ``ase.io.castep.read_seed('path-to/seed')`` Given you have a combination of seed.{param,cell,castep} this will return an atoms object with the last ionic positions in the .castep file and all other settings parsed from the .cell and .param file. If no .castep file is found the positions are taken from the .cell file. The output directory will be set to the same directory, only the label is preceded by 'copy_of\_' to avoid overwriting. Notes/Issues: ============== * Currently *only* the FixAtoms *constraint* is fully supported for reading and writing. * There is no support for the CASTEP *unit system*. Units of eV and Angstrom are used throughout. In particular when converting total energies from different calculators, one should check that the same CODATA_ version is used for constants and conversion factors, respectively. .. _CASTEP: http://www.castep.org/ .. _W: http://en.wikipedia.org/wiki/CASTEP .. _CODATA: http://physics.nist.gov/cuu/Constants/index.html .. [1] S. J. Clark, M. D. Segall, C. J. Pickard, P. J. Hasnip, M. J. Probert, K. Refson, M. C. Payne Zeitschrift für Kristallographie 220(5-6) pp.567- 570 (2005) PDF_. .. _PDF: http://goo.gl/wW50m End CASTEP Interface Documentation """ # Class attributes ! # keys set through atoms object atoms_keys = [ 'charge', 'ionic_constraints', 'lattice_abs', 'lattice_cart', 'positions_abs', 'positions_abs_final', 'positions_abs_intermediate', 'positions_frac', 'positions_frac_final', 'positions_frac_intermediate', ] atoms_obj_keys = [ 'dipole', 'energy_free', 'energy_zero', 'fermi', 'forces', 'nbands', 'positions', 'stress', ] internal_keys = [ '_castep_command', '_check_checkfile', '_copy_pspots', '_directory', '_export_settings', '_force_write', '_label', '_prepare_input_only', '_castep_pp_path', '_rename_existing_dir', '_set_atoms', '_track_output', '_try_reuse', ] def __init__(self, directory='CASTEP', label='castep', castep_command=None, check_castep_version=False, castep_pp_path=None, **kwargs): self.__name__ = 'Castep' # initialize the ase.calculators.general calculator Calculator.__init__(self) from ase.io.castep import write_cell self._write_cell = write_cell castep_keywords = import_castep_keywords() self.param = CastepParam() self.cell = CastepCell() ################################### # Calculator state variables # ################################### self._calls = 0 self._castep_version = castep_keywords.castep_version # collects warning from .castep files self._warnings = [] # collects content from *.err file self._error = None # warnings raised by the ASE interface self._interface_warnings = [] # store to check if recalculation is necessary self._old_atoms = None self._old_cell = None self._old_param = None ################################### # Internal keys # # Allow to tweak the behavior # ################################### self._opt = {} self._castep_command = get_castep_command(castep_command) self._castep_pp_path = get_castep_pp_path(castep_pp_path) self._check_checkfile = True self._copy_pspots = False self._directory = os.path.abspath(directory) self._export_settings = True self._force_write = True self._label = label self._prepare_input_only = False self._rename_existing_dir = True self._set_atoms = False self._track_output = False self._try_reuse = False # will be set on during runtime self._seed = None ################################### # (Physical) result variables # ################################### self.atoms = None # initialize result variables self._forces = None self._energy_total = None self._energy_free = None self._energy_0K = None self._number_of_cell_constraints = None self._output_verbosity = None self._stress = None self._unit_cell = None self._kpoints = None # pointers to other files used at runtime self._check_file = None self._castep_bin_file = None # check version of CASTEP options module against current one if check_castep_version: local_castep_version = get_castep_version(self._castep_command) if not hasattr(self, '_castep_version'): print("No castep version found") return if not local_castep_version == self._castep_version: print(('The options module was generated from version %s\n' 'while your are currently using CASTEP version %s') % (self._castep_version, get_castep_version(self._castep_command))) self._castep_version = local_castep_version # processes optional arguments in kw style for keyword, value in kwargs.items(): # first fetch special keywords issued by ASE CLI if keyword == 'kpts': self.__setattr__('kpoint_mp_grid', '%s %s %s' % tuple(value)) elif keyword == 'xc': self.__setattr__('xc_functional', str(value)) elif keyword == 'ecut': self.__setattr__('cut_off_energy', str(value)) else: # the general case self.__setattr__(keyword, value) def _castep_find_last_record(self, castep_file): """Checks wether a given castep file has a regular ending message following the last banner message. If this is the case, the line number of the last banner is message is return, otherwise False. returns (record_start, record_end, end_found, last_record_complete) """ if isinstance(castep_file, str): castep_file = paropen(castep_file, 'r') file_opened = True else: file_opened = False record_starts = [] while True: line = castep_file.readline() if 'Welcome' in line and 'CASTEP' in line: record_starts = [castep_file.tell()] + record_starts if not line: break if record_starts == []: print("Could not find CASTEP label in result file: %s" % castep_file) print("Are you sure this is a .castep file?") return # search for regular end of file end_found = False # start to search from record beginning from the back # and see if record_end = -1 for record_nr, record_start in enumerate(record_starts): castep_file.seek(record_start) while True: line = castep_file.readline() if not line: break if 'warn' in line.lower(): self._warnings.append(line) if 'Writing analysis data to' in line: #if 'Writing model to' in line: end_found = True record_end = castep_file.tell() break if end_found: break if file_opened: castep_file.close() if end_found: # record_nr == 0 corresponds to the last record here if record_nr == 0: return (record_start, record_end, True, True) else: return (record_start, record_end, True, False) else: return (0, record_end, False, False) def read(self, castep_file=None): """Read a castep file into the current instance.""" if castep_file is None: if self._castep_file: castep_file = self._castep_file else: print('No CASTEP file specified') return if not os.path.exists(castep_file): print('No CASTEP file found') if self._seed is None: self._seed = os.path.splitext(os.path.basename(castep_file))[0] err_file = '%s.0001.err' % self._seed if os.path.exists(err_file): err_file = paropen(err_file) self._error = err_file.read() err_file.close() # we return right-away because it might # just be here from a previous run # look for last result, if several CASTEP # run are appended out = paropen(castep_file, 'r') record_start, record_end, end_found, _\ = self._castep_find_last_record(out) if not end_found: print("No regular end found in %s file" % castep_file) print(self._error) out.close() return # we return here, because the file has no a regular end # now iterate over last CASTEP output in file to extract information # could be generalized as well to extract trajectory from file # holding several outputs n_cell_const = 0 forces = [] stress = [] out.seek(record_start) while True: try: line = out.readline() if not line or out.tell() > record_end: break elif "output verbosity" in line: iprint = int(line.split()[-1][1]) if int(iprint) != 1: self.param.iprint = iprint elif "Unit Cell" in line: lattice_real = [] lattice_reci = [] while True: line = out.readline() fields = line.split() if len(fields) == 6: break for i in range(3): lattice_real.append([float(f) for f in fields[0:3]]) lattice_reci.append([float(f) for f in fields[3:7]]) line = out.readline() fields = line.split() elif "Cell Contents" in line: while True: line = out.readline() if "Total number of ions in cell" in line: n_atoms = int(line.split()[7]) if "Total number of species in cell" in line: _ = int(line.split()[7]) fields = line.split() if len(fields) == 0: break elif "Fractional coordinates of atoms" in line: species = [] positions_frac = [] # positions_cart = [] while True: line = out.readline() fields = line.split() if len(fields) == 7: break for n in range(n_atoms): species.append(fields[1]) positions_frac.append([float(s) for s in fields[3:6]]) line = out.readline() fields = line.split() elif "Files used for pseudopotentials" in line: while True: line = out.readline() if 'Pseudopotential generated on-the-fly' in line: continue fields = line.split() if (len(fields) >= 2): elem, pp_file = fields self.cell.species_pot = (elem, pp_file) else: break elif "k-Points For BZ Sampling" in line: # TODO: generalize for non-Monkhorst Pack case # (i.e. kpoint lists) - # kpoints_offset cannot be read this way and # is hence always set to None while True: line = out.readline() if not line.strip(): break if "MP grid size for SCF calculation" in line: #kpoints = ' '.join(line.split()[-3:]) #self.kpoints_mp_grid = kpoints #self.kpoints_mp_offset = '0. 0. 0.' # not set here anymore because otherwise # two calculator objects go out of sync # after each calculation triggering unecessary # recalculation break elif "Symmetry and Constraints" in line: self.read_symops(castep_castep=out) elif "Number of cell constraints" in line: n_cell_const = int(line.split()[4]) elif "Final energy" in line: self._energy_total = float(line.split()[-2]) elif "Final free energy" in line: self._energy_free = float(line.split()[-2]) elif "NB est. 0K energy" in line: self._energy_0K = float(line.split()[-2]) # remember to remove constraint labels in force components # (lacking a space behind the actual floating point number in # the CASTEP output) elif "******************** Forces *********************"\ in line or\ "************** Symmetrised Forces ***************"\ in line: fix = [] fix_cart = [] forces = [] while True: line = out.readline() fields = line.split() if len(fields) == 7: break for n in range(n_atoms): consd = np.array([0, 0, 0]) fxyz = [0, 0, 0] for (i, force_component) in enumerate(fields[-4:-1]): if force_component.count("(cons'd)") > 0: consd[i] = 1 fxyz[i] = float(force_component.replace( "(cons'd)", "")) if consd.all(): fix.append(n) elif consd.any(): fix_cart.append(FixCartesian(n, consd)) forces.append(fxyz) line = out.readline() fields = line.split() elif "***************** Stress Tensor *****************"\ in line or\ "*********** Symmetrised Stress Tensor ***********"\ in line: stress = [] while True: line = out.readline() fields = line.split() if len(fields) == 6: break for n in range(3): # print line stress.append([float(s) for s in fields[2:5]]) line = out.readline() fields = line.split() elif "BFGS: starting iteration" in line \ or "BFGS: improving iteration" in line: if n_cell_const < 6: lattice_real = [] lattice_reci = [] species = [] positions_frac = [] #positions_cart = [] forces = [] stress = [] elif "BFGS: Final Configuration:" in line: break elif 'warn' in line.lower(): self._warnings.append(line) except Exception as exception: print(line, end=' ') print("|-> line triggered exception: " + str(exception)) raise out.close() positions_frac_atoms = np.array(positions_frac) forces_atoms = np.array(forces) if self.atoms and not self._set_atoms: # compensate for internal reordering of atoms by CASTEP # to check if all atoms are assigned atoms_assigned = [False] * len(self.atoms) positions_frac_ase = (np.round(self.atoms.get_scaled_positions(), 6) % 1) % 1 positions_frac_castep = (np.array(positions_frac) % 1) % 1 # % is necessary because CASTEP output may contain fractional # coordinates > 1, which does not affect the calculation though # Source: http://goo.gl/xfwri # And, yes, the % needs to be done twice, see # ase.atoms.Atoms.get_scaled_positions # # np.round is used to catch the case that # a float roundoff error occurs right on # the border of the unit cell. species_castep = list(species) forces_castep = np.array(forces) tolerance = 1E-5 for n in range(n_atoms): for m in range(n_atoms): if (np.linalg.norm(positions_frac_ase[n] \ - positions_frac_castep[m], 1) < tolerance): if atoms_assigned[n]: raise UserWarning('Castep().read() tried to' + \ ' assign forces twice to the same' + \ ' atom.\n Please file a bug report to %s' + \ ' and attach your input files.' \ % contact_email) species[n] = species_castep[m] positions_frac_atoms[n] = \ np.array(positions_frac_castep[m]) forces_atoms[n] = np.array(forces_castep[m]) atoms_assigned[n] = True if not all(atoms_assigned): not_assigned = [i for (i, assigned) in zip(range(len(atoms_assigned)), atoms_assigned) if not assigned] print('%s atoms not assigned.' % atoms_assigned.count(False)) print('DEBUGINFO: The following atoms where not assigned: %s'\ % not_assigned) for atom in not_assigned: print('%s: %s <--> %s' % (atom, positions_frac_ase[atom], positions_frac_castep[atom])) print('dist.: %s' % ((np.linalg.norm(positions_frac_ase[n] - positions_frac_castep[m], 1)))) print('If you are trying to read a .castep where the atom\'s') print('positions have changed with respect to the atoms') print('object, set calc._set_atoms = True\n') print('On the other hand _set_atoms = True is not') print('recommended if CASTEP is only used as a single-point') print('calculator (e.g. in an ASE geometry optimzation)') print('as this might cause redundant recalculations.') raise UserWarning('Castep().read() did not assign forces' + \ ' and positions to all input atoms\n' + \ ' Sometimes this is caused if a node\n' + \ ' used in the calculation hits a\n' + \ ' wallclock limit that the head node has not noticed\n' + \ ' and accordingly tries to reread an unfinished\n' + \ ' calculation.\n' + \ 'If you think it should have assigned all of them,' + \ ' please file a bug report with your input file(s)' + \ ' to\n\n\t%s' % contact_email) else: # If no atoms, object has been previously defined # we define it here and set the Castep() instance as calculator. # This covers the case that we simply want to open a .castep file. # The next time around we will have an atoms object, since # set_calculator also set atoms in the calculator. if self.atoms: constraints = self.atoms.constraints else: constraints = [] atoms = ase.atoms.Atoms(species, cell=lattice_real, constraint=constraints, pbc=True, scaled_positions=positions_frac, ) atoms.set_calculator(self) self._forces = forces_atoms self._stress = np.array(stress) if self._warnings: print("WARNING: %s contains warnings" % castep_file) for warning in self._warnings: print(warning) # reset self._warnings = [] def read_symops(self, castep_castep=None): # TODO: check that this is really backwards compatible # with previous routine with this name... """Read all symmetry operations used from a .castep file.""" if castep_castep is None: castep_castep = self._seed + ".castep" if isinstance(castep_castep, str): if not os.path.isfile(castep_castep): print('Warning: CASTEP file %s not found!' % castep_castep) f = paropen(castep_castep, 'a') while True: line = f.readline() if not line: return if "output verbosity" in line: iprint = line.split()[-1][1] # filter out the default if int(iprint) != 1: self.param.iprint = iprint if "Symmetry and Constraints" in line: break elif isinstance(castep_castep, file): f = castep_castep else: raise TypeError('read_castep_castep_symops: castep_castep is' \ + 'not of type file or str!') if self.param.iprint is None or self.param.iprint < 2: self._interface_warnings.append('Warning: No symmetry' \ + 'operations could be read from %s (iprint < 2).' % f.name) return while True: line = f.readline() if not line: break if "Number of symmetry operations" in line: nsym = int(line.split()[5]) # print "nsym = %d" % nsym # information about symmetry related atoms currently not read symmetry_operations = [] for _ in range(nsym): rotation = [] displacement = [] while True: if "rotation" in f.readline(): break for _ in range(3): line = f.readline() rotation.append([float(r) for r in line.split()[1:4]]) while True: if "displacement" in f.readline(): break line = f.readline() displacement = [float(d) for d in line.split()[1:4]] symop = {'rotation': rotation, 'displacement': displacement} self.symmetry_ops = symop self.symmetry = symmetry_operations print("Symmetry operations successfully read from %s" % f.name) print(self.cell.symmetry_ops) break if isinstance(castep_castep, str): f.close() # return self.symmetry def set_label(self, label): """The label is part of each seed, which in turn is a prefix in each CASTEP related file. """ self._label = label def set_pspot(self, pspot, elems=None, notelems=None, clear=True, suffix='usp'): """Quickly set all pseudo-potentials: Usually CASTEP psp are named like _. so this function function only expects the . It then clears any previous pseudopotential settings apply the one with for each element in the atoms object. The optional elems and notelems arguments can be used to exclusively assign to some species, or to exclude with notelemens. Parameters :: - elems (None) : set only these elements - notelems (None): do not set the elements - clear (True): clear previous settings - suffix (usp): PP file suffix """ if clear and not elems and not notelems: self.cell.species_pot.clear() for elem in set(self.atoms.get_chemical_symbols()): if elems is not None and elem not in elems: continue if notelems is not None and elem in notelems: continue self.cell.species_pot = (elem, '%s_%s.%s' % (elem, pspot, suffix)) def get_forces(self, atoms): """Run CASTEP calculation if needed and return forces.""" self.update(atoms) return np.array(self._forces) def get_total_energy(self, atoms): """Run CASTEP calculation if needed and return total energy.""" self.update(atoms) return self._energy_total def get_free_energy(self, atoms): """Run CASTEP calculation if needed and return free energy. Only defined with smearing.""" self.update(atoms) return self._energy_free def get_0K_energy(self, atoms): """Run CASTEP calculation if needed and return 0K energy. Only defined with smearing.""" self.update(atoms) return self._energy_0K def get_potential_energy(self, atoms, force_consistent=False): #here for compatability with ase/calculators/general.py #but accessing only _name variables """Return the total potential energy.""" self.update(atoms) if force_consistent: return self._energy_free else: if self._energy_0K is not None: return self._energy_0K else: return self._energy_total def get_stress(self, atoms): """Return the stress.""" self.update(atoms) return self._stress def get_unit_cell(self, atoms): """Return the unit cell.""" self.update(atoms) return self._unit_cell def get_kpoints(self, atoms): """Return the kpoints.""" self.update(atoms) return self._kpoints def get_number_cell_constraints(self, atoms): """Return the number of cell constraints.""" self.update(atoms) return self._number_of_cell_constraints def set_atoms(self, atoms): """Sets the atoms for the calculator and vice versa.""" atoms.pbc = [True, True, True] self.__dict__['atoms'] = atoms.copy() self.atoms._calc = self def update(self, atoms): """Checks if atoms object or calculator changed and runs calculation if so. """ if self.calculation_required(atoms): self.calculate(atoms) def calculation_required(self, atoms, _=None): """Checks wether anything changed in the atoms object or CASTEP settings since the last calculation using this instance. """ if not self.atoms == self._old_atoms: return True if self._old_param is None or self._old_cell is None: return True if not self.param._options == self._old_param._options: return True if not self.cell._options == self._old_cell._options: return True return False def calculate(self, atoms): """Write all necessary input file and call CASTEP.""" self.prepare_input_files(atoms, force_write=self._force_write) if not self._prepare_input_only: self.run() self.read() def push_oldstate(self): """This function pushes the current state of the (CASTEP) Atoms object onto the previous state. Or in other words after calling this function, calculation_required will return False and enquiry functions just report the current value, e.g. get_forces(), get_potential_energy(). """ # make a snapshot of all current input # to be able to test if recalculation # is necessary self._old_atoms = self.atoms.copy() self._old_param = deepcopy(self.param) self._old_cell = deepcopy(self.cell) def initialize(self, *args, **kwargs): """Just an alias for prepar_input_files to comply with standard function names in ASE. """ self.prepare_input_files(*args, **kwargs) def prepare_input_files(self, atoms=None, force_write=None): """Only writes the input .cell and .param files and return This can be useful if one quickly needs to prepare input files for a cluster where no python or ASE is available. One can than upload the file manually and read out the results using Castep().read(). """ if self.param.reuse.value is None: print("You have not set e.g. calc.param.reuse = True") print("Reusing a previous calculation may save CPU time!\n") print("The interface will make sure by default, a .check exists") print("file before adding this statement to the .param file.\n") if self.param.num_dump_cycles.value is None: print("You have not set e.g. calc.param.num_dump_cycles = 0.") print("This can save you a lot of disk space. One only needs") print("*wvfn* if electronic convergence is not achieved.\n") from ase.io.castep import write_param if atoms is None: atoms = self.atoms else: self.atoms = atoms if force_write is None: force_write = self._force_write # if we have new instance of the calculator, # move existing results out of the way, first if os.path.isdir(self._directory)\ and self._calls == 0 \ and self._rename_existing_dir: if os.listdir(self._directory) == []: os.rmdir(self._directory) else: # rename appending creation date of the directory ctime = time.localtime(os.lstat(self._directory).st_ctime) os.rename(self._directory, '%s.bak-%s' % (self._directory, time.strftime("%Y%m%d-%H%M%S", ctime))) # create work directory if not os.path.isdir(self._directory): os.mkdir(self._directory, 0o775) if self._calls == 0: self._fetch_pspots() cwd = os.getcwd() os.chdir(self._directory) # if _try_reuse is requested and this # is not the first run, we try to find # the .check file from the previous run # this is only necessary if _track_output # is set to true if self._try_reuse and self._calls > 0: if os.path.exists(self._check_file): self.param.reuse = self._check_file elif os.path.exists(self._castep_bin_file): self.param.reuse = self._castep_bin_file self._seed = self._build_castep_seed() self._check_file = '%s.check' % self._seed self._castep_bin_file = '%s.castep_bin' % self._seed self._castep_file = os.path.abspath('%s.castep' % self._seed) # write out the input file self._write_cell('%s.cell' % self._seed, self.atoms, force_write=force_write) if self._export_settings: interface_options = self._opt else: interface_options = None write_param('%s.param' % self._seed, self.param, check_checkfile=True, force_write=force_write, interface_options=interface_options,) os.chdir(cwd) def _build_castep_seed(self): """Abstracts to construction of the final castep with and without _tracking_output. """ if self._track_output: return "%s-%06d" % (self._label, self._calls) else: return "%s" % (self._label) def run(self): """Simply call castep. If the first .err file contains text, this will be printed to the screen. """ # change to target directory cwd = os.getcwd() os.chdir(self._directory) self._calls += 1 # run castep itself stdout, stderr = shell_stdouterr('%s %s' % (self._castep_command, self._seed)) if stdout: print('castep call stdout:\n%s' % stdout) if stderr: print('castep call stderr:\n%s' % stderr) self.push_oldstate() # check for non-empty error files err_file = '%s.0001.err' % self._seed if os.path.exists(err_file): err_file = open(err_file) self._error = err_file.read() err_file.close() os.chdir(cwd) if self._error: print(self._error) def __repr__(self): """Returns generic, fast to capture representation of CASTEP settings along with atoms object. """ expr = '' expr += '-----------------Atoms--------------------\n' if self.atoms is not None: expr += str('%20s\n' % self.atoms) else: expr += 'None\n' expr += '-----------------Param keywords-----------\n' expr += str(self.param) expr += '-----------------Cell keywords------------\n' expr += str(self.cell) expr += '-----------------Internal keys------------\n' for key in self.internal_keys: expr += '%20s : %s\n' % (key, self._opt[key]) return expr def __getattr__(self, attr): """___getattr___ gets overloaded to reroute the internal keys and to be able to easily store them in in the param so that they can be read in again in subsequent calls. """ if attr in self.internal_keys: return self._opt[attr] if attr in ['__repr__', '__str__']: raise AttributeError elif attr not in self.__dict__: raise AttributeError else: return self.__dict__[attr] def __setattr__(self, attr, value): """We overload the settattr method to make value assignment as pythonic as possible. Internal values all start with _. Value assigment is case insensitive! """ if attr.startswith('_'): # internal variables all start with _ # let's check first if they are close but not identical # to one of the switches, that the user accesses directly similars = difflib.get_close_matches(attr, self.internal_keys, cutoff=0.9) if attr not in self.internal_keys and similars: print('Warning: You probably tried one of: %s' % similars) print('but typed %s' % attr) if attr in self.internal_keys: self._opt[attr] = value if attr == '_track_output': if value: self._try_reuse = True print('You switched _track_output on. This will') print('consume a lot of disk-space. The interface') print('also switched _try_reuse on, which will') print('try to find the last check file. Set') print('_try_reuse = False, if you need') print('really separate calculations') elif '_try_reuse' in self._opt and self._try_reuse: self._try_reuse = False print("_try_reuse is set to False, too") else: self.__dict__[attr] = value return elif attr in ['atoms', 'cell', 'param']: if value is not None: if attr == 'atoms' and not isinstance(value, ase.atoms.Atoms): raise TypeError('%s is not an instance of ase.atoms.Atoms.' % value) elif attr == 'cell' and not isinstance(value, CastepCell): raise TypeError('%s is not an instance of CastepCell.' % value) elif attr == 'param' and not isinstance(value, CastepParam): raise TypeError('%s is not an instance of CastepParam.' % value) # These 3 are accepted right-away, no matter what self.__dict__[attr] = value return elif attr in self.atoms_obj_keys: # keywords which clearly belong to the atoms object are # rerouted to go there self.atoms.__dict__[attr] = value return elif attr in self.atoms_keys: # CASTEP keywords that should go into the atoms object # itself are blocked print("Ignoring setings of '%s', since this has to be set\n" "through the atoms object" % attr) return attr = attr.lower() if attr not in (self.cell._options.keys()\ + self.param._options.keys()): # what is left now should be meant to be a castep keyword # so we first check if it defined, and if not offer some error # correction similars = difflib.get_close_matches(attr, self.cell._options.keys() + self.param._options.keys()) if similars: raise UserWarning(('Option "%s" not known! You mean "%s"?') % (attr, similars[0])) else: raise UserWarning('Option "%s" is not known!' % attr) # here we know it must go into one of the component param or cell # so we first determine which one if attr in self.param._options.keys(): comp = 'param' elif attr in self.cell._options.keys(): comp = 'cell' else: raise UserWarning('Programming error: could not attach ' \ + 'the keyword to an input file') self.__dict__[comp].__setattr__(attr, value) def merge_param(self, param, overwrite=True, ignore_internal_keys=False): """Parse a param file and merge it into the current parameters.""" INT_TOKEN = 'ASE_INTERFACE' if isinstance(param, CastepParam): for key, option in param._options.items(): if option.value is not None: self.param.__setattr__(key, option.value) return elif isinstance(param, str): param_file = open(param, 'r') elif isinstance(param, file): param_file = param else: print("The param filename is neither a string nor a filehandler") return for i, line in enumerate(param_file.readlines()): line = line.strip() # remove comments for comment_char in ['#', ';', '!']: if comment_char in line: if INT_TOKEN in line: # This block allows to read internal settings from # a *param file iline = line[line.index(INT_TOKEN) + len(INT_TOKEN):] if iline.split()[0] in self.internal_keys \ and not ignore_internal_keys: value = ' '.join(iline.split()[2:]) if value in ['True', 'False']: self._opt[iline.split()[0]] = eval(value) else: self._opt[iline.split()[0]] = value line = line[:line.index(comment_char)] # if nothing remains if not line.strip(): continue line = re.sub(':', ' ', line) if line == 'reuse': self.param.reuse.value = 'default' continue if line == 'continuation': self.param.continuation.value = 'default' continue try: key, value = line.split() except: print("Could not parse line %s of your param file: %s" % (i, line)) raise UserWarning("Seems to me malformed") if not overwrite and getattr(self.param, key).value is not None: continue self.__setattr__(key, value) def dryrun_ok(self, dryrun_flag='-dryrun'): """Starts a CASTEP run with the -dryrun flag [default] in a temporary and check wether all variables are initialized correctly. This is recommended for every bigger simulation. """ from ase.io.castep import write_param temp_dir = tempfile.mkdtemp() curdir = os.getcwd() self._fetch_pspots(temp_dir) os.chdir(temp_dir) self._fetch_pspots(temp_dir) seed = 'dryrun' cell_written = self._write_cell('%s.cell' % seed, self.atoms) if not cell_written: print("%s.cell not written - aborting dryrun" % seed) return write_param('%s.param' % seed, self.param, ) stdout, stderr = shell_stdouterr(('%s %s %s' % (self._castep_command, seed, dryrun_flag))) if stdout: print(stdout) if stderr: print(stderr) result_file = open('%s.castep' % seed) txt = result_file.read() ok_string = r'.*DRYRUN finished.*No problems found with input files.*' match = re.match(ok_string, txt, re.DOTALL) try: self._kpoints_used = int( re.search( r'Number of kpoints used = *([0-9]+)', txt).group(1)) except: print('Couldn\'t fetch number of kpoints from dryrun CASTEP file') err_file = '%s.0001.err' % seed if match is None and os.path.exists(err_file): err_file = open(err_file) self._error = err_file.read() err_file.close() result_file.close() os.chdir(curdir) shutil.rmtree(temp_dir) # re.match return None is the string does not match return match is not None # this could go into the Atoms() class at some point... def _get_number_in_species(self, at, atoms=None): """Return the number of the atoms within the set of it own species. If you are an ASE commiter: why not move this into ase.atoms.Atoms ?""" if atoms is None: atoms = self.atoms numbers = atoms.get_atomic_numbers() n = numbers[at] nis = numbers.tolist()[:at + 1].count(n) return nis def _get_absolute_number(self, species, nic, atoms=None): """This is the inverse function to _get_number in species.""" if atoms is None: atoms = self.atoms ch = atoms.get_chemical_symbols() ch.reverse() total_nr = 0 assert nic > 0, 'Number in species needs to be 1 or larger' while True: if ch.pop() == species: if nic == 1: return total_nr nic -= 1 total_nr += 1 def _fetch_pspots(self, directory=None): """Put all specified pseudo-potentials into the working directory. """ if not os.environ.get('PSPOT_DIR', None) \ and self._castep_pp_path != os.path.abspath('.'): # By default CASTEP consults the environment variable # PSPOT_DIR. If this contains a list of colon separated # directories it will check those directories for pseudo- # potential files if not in the current directory. # Thus if PSPOT_DIR is set there is nothing left to do. # If however PSPOT_DIR was been accidentally set # (e.g. with regards to a different program) # setting CASTEP_PP_PATH to an explicit value will # still be honored. return if directory is None: directory = self._directory if not os.path.isdir(self._castep_pp_path): print("PSPs directory %s not found" % self._castep_pp_path) pspots = {} if self.cell.species_pot.value is not None: for line in self.cell.species_pot.value.split('\n'): line = line.split() if line: pspots[line[0]] = line[1] for species in self.atoms.get_chemical_symbols(): if not pspots or species not in pspots.keys(): print("Warning: you have no PP specified for %s." % species) print("CASTEP will now generate an on-the-fly potentials.") print("For sake of numerical consistency and efficiency") print("this is discouraged.") if self.cell.species_pot.value: for (species, pspot) in pspots.items(): orig_pspot_file = os.path.join(self._castep_pp_path, pspot) cp_pspot_file = os.path.join(directory, pspot) if os.path.exists(orig_pspot_file)\ and not os.path.exists(cp_pspot_file): if self._copy_pspots: shutil.copy(orig_pspot_file, directory) else: os.symlink(os.path.join(self._castep_pp_path, pspot), cp_pspot_file) def get_castep_version(castep_command): """This returns the version number as printed in the CASTEP banner. """ temp_dir = tempfile.mkdtemp() curdir = os.getcwd() os.chdir(temp_dir) jname = 'dummy_jobname' stdout, stderr = "", "" try: stdout, stderr = subprocess.Popen( castep_command.split() + [jname], stderr=subprocess.PIPE, stdout=subprocess.PIPE, cwd=temp_dir).communicate() except: msg = "" msg += "Could not determine the version of your CASTEP binary \n" msg += "This usually means one of the following \n" msg += " * you don't have CASTEP installed \n" msg += " * you have not set the CASTEP_COMMAND to call it \n" msg += " * you have provided a wrong CASTEP_COMMAND. \n" msg += " Make sure it is in your PATH\n\n" msg += stdout msg += stderr raise Exception(msg) output = open('%s.castep' % jname) output_txt = output.readlines() output.close() os.chdir(curdir) shutil.rmtree(temp_dir) for line in output_txt: if 'CASTEP version' in line: return float(re.findall(r'(?<=CASTEP version )[0-9.]*', line)[0]) def create_castep_keywords(castep_command, filename='castep_keywords.py', force_write=True, path='.', fetch_only=None): """This function allows to fetch all available keywords from stdout of an installed castep binary. It furthermore collects the documentation to harness the power of (ipython) inspection and type for some basic type checking of input. All information is stored in two 'data-store' objects that are not distributed by default to avoid breaking the license of CASTEP. """ # Takes a while ... # Fetch all allowed parameters # fetch_only : only fetch that many parameters (for testsuite only) code = {} suffixes = ['cell', 'param'] for suffix in suffixes: code[suffix] = '' if os.path.exists(filename) and not force_write: print('CASTEP Options Module file exists.') print('You can overwrite it by calling') print('python castep.py -f [CASTEP_COMMAND].') return False fh = open(os.path.join(path, filename), 'w') fh.write('"""This file is generated by') fh.write('ase/calculators/castep.py\n') fh.write('and is not distributed with ASE to avoid breaking') fh.write('CASTEP copyright\n"""\n') fh.write('class Opt:\n') fh.write(' """"A CASTEP option"""\n') fh.write(""" def __init__(self): self.keyword = None self.level = None self.type = None self.type = None def clear(self): \"\"\"Reset the value of the option to None again\"\"\" self.value = None\n""") fh.write(' def __repr__(self):\n') fh.write(' expr = \'\'\n') fh.write(' if self.value:\n') fh.write(' expr += \'Option: %s(%s, %s):\\n%s\\n\''\ + '% (self.keyword, self.type, self.level, self.value)\n') fh.write(' else:\n') fh.write(' expr += \'Option: %s[unset]\' % self.keyword\n') fh.write(' expr += \'(%s, %s)\' % (self.type, self.level)\n') fh.write(' return expr\n\n') fh.write("""class ComparableDict(dict): \"\"\"Extends a dict to make to sets of options comparable\"\"\" def __init__(self): dict.__init__(self) def __ne__(self, other): return not self.__eq__(other) def __eq__(self, other): if not isinstance(other, ComparableDict): return False if set(self) - set(other): return False for key in sorted(self): if self[key].value != other[key].value: return False return True\n""") code['cell'] += '\n\nclass CastepCellDict(object):\n' code['param'] += '\n\nclass CastepParamDict(object):\n' types = [] levels = [] for suffix in suffixes: code[suffix] += ' """A flat object that holds %s options"""\n'\ % suffix code[suffix] += ' def __init__(self):\n' code[suffix] += ' object.__init__(self)\n' code[suffix] += ' self._options = ComparableDict()\n' castep_version = get_castep_version(castep_command) help_all, _ = shell_stdouterr('%s -help all' % castep_command) # Filter out proper keywords try: raw_options = re.findall(r'((?<=^ )[A-Z_]{2,}|(?<=^)[A-Z_]{2,})', help_all, re.MULTILINE) except: print('Problem parsing: %s' % help_all) raise processed_options = 0 for option in raw_options[:fetch_only]: doc, _ = shell_stdouterr('%s -help %s' % (castep_command, option)) # Stand Back! I know regular expressions (http://xkcd.com/208/) :-) match = re.match(r'(?P.*)Type: (?P[^ ]+).*' + \ r'Level: (?P[^ ]+)\n\s*\n' + \ r'(?P.*?)(\n\s*\n|$)', doc, re.DOTALL) if match is not None: match = match.groupdict() processed_options += 1 # JM: uncomment lines in following block to debug issues # with keyword assignment during extraction process from CASTEP suffix = None if re.findall(r'PARAMETERS keywords:\n\n\s?None found', doc): # print('%s : PARAMETERS keywords: None found' % option) suffix = 'cell' if re.findall(r'CELL keywords:\n\n\s?None found', doc): # print('%s : CELL keywords: None found' % option) suffix = 'param' if suffix is None: print('%s -> not assigned to either' ' CELL or PARAMETERS keywords' % option) # else: # print(('%s -> assigned input file' # ' suffix %s') % (option, suffix)) sys.stdout.write('.') sys.stdout.flush() code[suffix] += ' opt_obj = Opt()\n' code[suffix] += (' opt_obj.keyword = \'%s\'\n' % option.lower()) if 'type' in match: code[suffix] += (' opt_obj.type = \'%s\'\n' % match['type']) if match['type'] not in types: types.append(match['type']) else: raise Exception('Found no type for %s' % option) if 'level' in match: code[suffix] += (' opt_obj.level = \'%s\'\n' % match['level']) if match['level'] not in levels: levels.append(match['level']) else: raise Exception('Found no level for %s' % option) if 'doc' in match: code[suffix] += (' opt_obj.__doc__ = """%s\n"""\n' % match['doc']) else: raise Exception('Found no doc string for %s' % option) code[suffix] += (' opt_obj.value = None\n') code[suffix] += (' self._options[\'%s\'] = opt_obj\n\n' % option.lower()) code[suffix] += (' self.__dict__[\'%s\'] = opt_obj\n\n' % option.lower()) else: sys.stdout.write(doc) sys.stdout.flush() raise Exception('create_castep_keywords: Could not process %s' % option) # write classes out for suffix in suffixes: fh.write(code[suffix]) fh.write('types = %s\n' % types) fh.write('levels = %s\n' % levels) fh.write('castep_version = %s\n\n' % castep_version) fh.close() print('\nCASTEP v%s, fetched %s keywords' % (castep_version, processed_options)) return True class CastepParam(object): """CastepParam abstracts the settings that go into the .param file""" def __init__(self): object.__init__(self) castep_keywords = import_castep_keywords() castep_param_dict = castep_keywords.CastepParamDict() self._options = castep_param_dict._options self.__dict__.update(self._options) def __repr__(self): expr = '' if [x for x in self._options.values() if x.value is not None]: for key, option in sorted(self._options.items()): if option.value is not None: expr += ("%20s : %s\n" % (key, option.value)) else: expr += 'Default\n' return expr def __setattr__(self, attr, value): if attr.startswith('_'): self.__dict__[attr] = value return if attr not in self._options.keys(): similars = difflib.get_close_matches(attr, self._options.keys()) if similars: raise UserWarning(('Option "%s" not known! You mean "%s"?') % (attr, similars[0])) else: raise UserWarning('Option "%s" is not known!' % attr) attr = attr.lower() opt = self._options[attr] if not opt.type == 'Block' and isinstance(value, str): value = value.replace(':', ' ') if opt.type in ['Boolean', 'Defined']: if False: pass else: try: value = bool(eval(str(value).title())) except: raise ConversionError('bool', attr, value) self._options[attr].value = value elif opt.type == 'String': if attr == 'reuse': if self._options['continuation'].value: print('Cannot set reuse if continuation is set, and') print('vice versa. Set the other to None, if you want') print('this setting.') else: if value is True: self._options['reuse'].value = 'default' else: self._options['reuse'].value = str(value) elif attr == 'continuation': if self._options['reuse'].value: print('Cannot set continuation if reuse is set, and') print('vice versa. Set the other to None, if you want') print('this setting.') else: if value is True: self._options['continuation'].value = 'default' else: self._options['continuation'].value = str(value) else: try: value = str(value) except: raise ConversionError('str', attr, value) self._options[attr].value = value elif opt.type == 'Integer': if False: pass else: try: value = int(value) except: raise ConversionError('int', attr, value) self._options[attr].value = value elif opt.type in ['Real', 'Physical']: # Usage of the CASTEP unit system is not implemented for now. # We assume, that the user is happy with setting/getting the # CASTEP default units refer to http://goo.gl/bqYf2 # page 13, accessed Apr 6, 2011 try: value = float(value) except: raise ConversionError('float', attr, value) self._options[attr].value = value # So far there is no block type in .param else: raise RuntimeError("Caught unhandled option: %s = %s" % (attr, value)) class CastepCell(object): """CastepCell abstracts all setting that go into the .cell file""" def __init__(self): object.__init__(self) castep_keywords = import_castep_keywords() castep_cell_dict = castep_keywords.CastepCellDict() self._options = castep_cell_dict._options self.__dict__.update(self._options) def __repr__(self): expr = '' if [x for x in self._options.values() if x.value is not None]: for key, option in sorted(self._options.items()): if option.value is not None: expr += ("%20s : %s\n" % (key, option.value)) else: expr += 'Default\n' return expr def __setattr__(self, attr, value): if attr.startswith('_'): self.__dict__[attr] = value return if attr not in self._options.keys(): similars = difflib.get_close_matches(attr, self._options.keys()) if similars: raise UserWarning(('Option "%s" not known! You mean "%s"?') % (attr, similars[0])) else: raise UserWarning('Option "%s" is not known!' % attr) return attr = attr.lower() opt = self._options[attr] if not opt.type == 'Block' and isinstance(value, str): value = value.replace(':', ' ') if opt.type in ['Boolean', 'Defined']: try: value = bool(eval(str(value).title())) except: raise ConversionError('bool', attr, value) self._options[attr].value = value elif opt.type == 'String': if False: pass else: try: value = str(value) except: raise ConversionError('str', attr, value) self._options[attr].value = value elif opt.type == 'Integer': if attr == 'kpoint_mp_grid': opt = self._options['kpoints_mp_grid'] if attr in ['kpoints_mp_grid', 'kpoint_mp_grid']: if ',' in value: value = value.replace(',', ' ') if isinstance(value, str) and len(value.split()) == 3: try: _ = [int(x) for x in value.split()] except: raise ConversionError('int', attr, value) opt.value = value else: print('Wrong format for kpoints_mp_grid: expected R R R') print('and you said %s' % value) else: try: value = int(value) except: raise ConversionError('int', attr, value) self._options[attr].value = value elif opt.type in ['Real', 'Physical']: if attr == 'kpoint_mp_offset': opt = self._options['kpoints_mp_offset'] if attr in ['kpoints_mp_offset', 'kpoint_mp_offset']: if isinstance(value, str) and len(value.split()) == 3: try: _ = [float(x) for x in value.split()] except: raise ConversionError('float', attr, value) opt.value = value else: try: value = float(value) except: raise ConversionError('float', attr, value) self._options[attr].value = value elif opt.type == 'Block': if attr == 'species_pot': if not isinstance(value, tuple) \ or len(value) != 2: print("Please specify pseudopotentials in python as") print("a tuple, like:") print("(species, file), e.g. ('O', 'path-to/O_OTFG.usp')") print("Anything else will be ignored") else: if self.__dict__['species_pot'].value is None: self.__dict__['species_pot'].value = '' self.__dict__['species_pot'].value = \ re.sub(r'\n?\s*%s\s+.*' % value[0], '', self.__dict__['species_pot'].value) if value[1]: self.__dict__['species_pot'].value += '\n%s %s' \ % value # now sort lines as to match the CASTEP output pspots = self.__dict__['species_pot'].value.split('\n') # throw out empty lines pspots = [x for x in pspots if x] # sort based on atomic numbers pspots.sort(key=lambda x: ase.data.atomic_numbers[ x.split()[0]]) # rejoin; the first blank-line # makes the print(calc) output look prettier self.__dict__['species_pot'].value = \ '\n' + '\n'.join(pspots) return elif attr == 'symmetry_ops': if not isinstance(value, dict) \ or not 'rotation' in value \ or not len(value['rotation']) == 3 \ or not len(value['displacement']) == 3 \ or not 'displacement' in value: print("Cannot process your symmetry_op %s" % value) print("It has statet like {'rotation':[a, b, c], ") print(" 'displacement': [x, y, z]}") return if self.__dict__['symmetry_ops'].value is None: self.__dict__['symmetry_ops'].value = '' n = (len(self.__dict__['symmetry_ops'].value.split('\n')) / 4) + 1 for i in range(3): self.__dict__['symmetry_ops'].value += \ (("%9.6f " * 3 + "! rotation %5d\n")\ % (tuple(value['rotation'][i] + (n, )))) self.__dict__['symmetry_ops'].value\ += (("%9.6f " * 3 + "! displacement %5d \n")\ % (tuple(value['displacement'] + (n, )))) elif attr in ['positions_abs_intermediate', 'positions_abs_product']: if not isinstance(value, ase.atoms.Atoms): raise UserWarning('castep.cell.%s expects Atoms object' % attr) target = self.__dict__[attr] target.value = '' for elem, pos in zip(value.get_chemical_symbols(), value.get_positions()): target.value += ('%4s %9.6f %9.6f %9.6f\n' % (elem, pos[0], pos[1], pos[2])) return elif attr in ['cell_constraints']: # put block type options here, that don't need special care try: value = str(value) except: raise ConversionError('str', attr, value) else: print('Not implemented') print('The option %s is of block type, which usually' % attr) print('needs some special care to get the formattings right.') print('Please feel free to add it and send the') print('patch to %s, so we can all benefit.' % contact_email) raise self._options[attr].value = value else: raise RuntimeError('Caught unhandled option: %s = %s' % (attr, value)) class ConversionError(Exception): """Print customized error for options that are not converted correctly and point out that they are maybe not implemented, yet""" def __init__(self, key_type, attr, value): Exception.__init__(self) self.key_type = key_type self.value = value self.attr = attr def __str__(self): return "Could not convert %s = %s to %s\n" \ % (self.attr, self.value, self.key_type) \ + "This means you either tried to set a value of the wrong\n"\ + "type or this keyword needs some special care. Please feel\n"\ + "to add it to the corresponding __setattr__ method and send\n"\ + "the patch to max.hoffmann@tum.de, so we can all benefit." def get_castep_pp_path(castep_pp_path=''): """Abstract the quest for a CASTEP PSP directory.""" if castep_pp_path: return os.path.abspath(os.path.expanduser(castep_pp_path)) elif 'CASTEP_PP_PATH' in os.environ: return os.environ['CASTEP_PP_PATH'] else: return os.path.abspath('.') def get_castep_command(castep_command=''): """Abstract the quest for a castep_command string.""" if castep_command: return castep_command elif 'CASTEP_COMMAND' in os.environ: return os.environ['CASTEP_COMMAND'] else: return 'castep' def shell_stdouterr(raw_command): """Abstracts the standard call of the commandline, when we are only interested in the stdout and stderr """ stdout, stderr = subprocess.Popen(raw_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate() return stdout.strip(), stderr.strip() def import_castep_keywords(): try: import castep_keywords except ImportError: create_castep_keywords(get_castep_command()) print('Stored castep_keywords.py in %s' % os.path.abspath(os.path.curdir)) print('Copy castep_keywords.py to your ase installation') print('under ase/calculators for system-wide installation') print(""" Generating castep_keywords.py ... hang on. The castep_keywords.py contains abstractions for CASTEP input parameters (for both .cell and .param input files), including some format checks and descriptions. The latter are extracted from the internal online help facility of a CASTEP binary, thus allowing to easily keep the calculator synchronized with (different versions of) the CASTEP code. Consequently, avoiding licensing issues (CASTEP is distributed commercially by accelrys), we consider it wise not to provide castep_keywords.py in the first place. """) create_castep_keywords(get_castep_command()) print("""\n\n Stored castep_keywords.py in %s. Copy castep_keywords.py to your ASE installation under ase/calculators for system-wide installation """ % os.path.abspath(os.path.curdir)) print("""\n\n Using a *nix OS this can be a simple as\nmv %s %s""" % (os.path.join(os.path.abspath(os.path.curdir), 'castep_keywords.py'), os.path.join(os.path.dirname(ase.__file__), 'calculators'))) import castep_keywords return castep_keywords if __name__ == '__main__': print("When called directly this calculator will fetch all available") print("keywords from the binarys help function into a castep_keywords.py") print("in the current directory %s" % os.getcwd()) print("For system wide usage, it can be copied into an ase installation") print("at ASE/calculators.\n") print("This castep_keywords.py usually only needs to be generated once") print("for a CASTEP binary/CASTEP version.") import optparse parser = optparse.OptionParser() parser.add_option('-f', '--force-write', dest='force_write', help='Force overwriting existing castep_keywords.py', default=False, action='store_true') (options, args) = parser.parse_args() if args: opt_castep_command = ''.join(args) else: opt_castep_command = '' generated = create_castep_keywords(get_castep_command(opt_castep_command), force_write=options.force_write) if generated: try: exec(compile(open('castep_keywords.py').read(), 'castep_keywords.py', 'exec')) except Exception as e: print(e) print("Ooops, something went wrong with the CASTEP keywords") else: print("Import works. Looking good!") python-ase-3.9.1.4567/ase/calculators/siesta.py0000664000175000017500000007503512553425526021436 0ustar jensjjensj00000000000000from __future__ import print_function """This module defines an ASE interface to SIESTA. http://www.uam.es/departamentos/ciencias/fismateriac/siesta """ import os from os.path import join, isfile, islink, getmtime from cmath import exp import array import numpy as np from ase.data import chemical_symbols from ase.units import Rydberg, fs from ase.io.siesta import read_rho, read_fdf, read_struct from ase.io.cube import read_cube_data class Siesta: """Class for doing SIESTA calculations. The default parameters are very close to those that the SIESTA Fortran code would use. These are the exceptions:: calc = Siesta(label='siesta', xc='LDA', pulay=5, mix=0.1) Use the set_fdf method to set extra FDF parameters:: calc.set_fdf('PAO.EnergyShift', 0.01 * Rydberg) """ def __init__(self, label='siesta', xc='LDA', kpts=None, nbands=None, width=None, meshcutoff=None, charge=None, pulay=5, mix=0.1, maxiter=120, basis=None, ghosts=[], write_fdf=True): """Construct SIESTA-calculator object. Parameters ========== label: str Prefix to use for filenames (label.fdf, label.txt, ...). Default is 'siesta'. xc: str Exchange-correlation functional. Must be one of LDA, PBE, revPBE, RPBE. kpts: list of three int Monkhost-Pack sampling. nbands: int Number of bands. width: float Fermi-distribution width in eV. meshcutoff: float Cutoff energy in eV for grid. charge: float Total charge of the system. pulay: int Number of old densities to use for Pulay mixing. mix: float Mixing parameter between zero and one for density mixing. write_fdf: bool Use write_fdf=False to use your own fdf-file. Examples ======== Use default values: >>> h = Atoms('H', calculator=Siesta()) >>> h.center(vacuum=3.0) >>> e = h.get_potential_energy() """ self.name = 'Siesta' self.label = label#################### != out self.xc = xc self.kpts = kpts self.nbands = nbands self.width = width self.meshcutoff = meshcutoff self.charge = charge self.pulay = pulay self.mix = mix self.maxiter = maxiter self.basis = basis self.ghosts = ghosts self.write_fdf_file = write_fdf self.converged = False self.fdf = {} self.e_fermi = None def update(self, atoms): if (not self.converged 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 initialize(self, atoms): self.numbers = atoms.get_atomic_numbers().copy() self.species = [] for a, Z in enumerate(self.numbers): if a in self.ghosts: Z = -Z if Z not in self.species: self.species.append(Z) if 'SIESTA_PP_PATH' in os.environ: pppaths = os.environ['SIESTA_PP_PATH'].split(':') else: pppaths = [] for Z in self.species: symbol = chemical_symbols[abs(Z)] name = symbol + '.vps' name1 = symbol + '.psf' found = False for path in pppaths: filename = join(path, name) filename1 = join(path, name1) if isfile(filename) or islink(filename): found = True if path != '.': if islink(name) or isfile(name): os.remove(name) os.symlink(filename, name) elif isfile(filename1) or islink(filename1): found = True if path != '.': if islink(name1) or isfile(name1): os.remove(name1) os.symlink(filename1, name1) if not found: raise RuntimeError('No pseudopotential for %s!' % symbol) self.converged = False def get_potential_energy(self, atoms, force_consistent=False): self.update(atoms) if force_consistent: return self.efree else: # Energy extrapolated to zero Kelvin: return (self.etotal + self.efree) / 2 def get_forces(self, atoms): self.update(atoms) return self.forces.copy() def get_stress(self, atoms): self.update(atoms) return self.stress.copy() def get_dipole_moment(self, atoms): """Returns total dipole moment of the system.""" self.update(atoms) return self.dipole def read_dipole(self): dipolemoment = np.zeros([1, 3]) for line in open(self.label + '.txt', 'r'): if line.rfind('Electric dipole (Debye)') > -1: dipolemoment = np.array([float(f) for f in line.split()[5:8]]) #debye to e*Ang (the units of VASP) dipolemoment = dipolemoment*0.2081943482534 return dipolemoment 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). """ filename = self.label + '.RHO' if not isfile(filename): raise RuntimeError('Could not find rho-file (make sure to add fdf-option ' '"SaveRho=True" to your calculation)') rho = read_rho(filename) if spin is None: return rho.sum(axis=3) elif rho.shape[3] != 2: raise RuntimeError('Explicit spin-value requested. ' 'Only total density is available.') elif spin == 0 or spin == 1: return rho[:, :, :, spin] else: raise RuntimeError('Invalid spin-value requested. ' 'Expected 0 or 1, got %s' % spin) def get_pseudo_wave_function(self, band=0, kpt=0, spin=None): """Return pseudo-wave-function array. The method is limited to the gamma point, and is implemented as a wrapper to denchar (a tool shipped with siesta); denchar must be available in the command path. When retrieving a p_w_f from a non-spin-polarized calculation, spin must be None (default), and for spin-polarized calculations, spin must be set to either 0 (up) or 1 (down). As long as the necessary files are present and named correctly, old p_w_fs can be read as long as the calculator label is set. E.g. >>> c = Siesta(label='name_of_old_calculation') >>> pwf = c.get_pseudo_wave_function() The broadcast and pad options are not implemented. """ # Not implemented: kpt=0, broadcast=True, pad=True # kpoint must be Gamma assert kpt == 0, \ "siesta.get_pseudo_wave_function is unfortunately limited " \ "to the gamma point only. kpt must be 0." # In denchar, band numbering starts from 1 assert isinstance(band, int) and band >= 0 band = band+1 if spin is None: spin_name = "" elif spin == 0: spin_name = ".UP" elif spin == 1: spin_name = ".DOWN" label = self.label # If