root / ase / lattice / spacegroup / crystal.py @ 5
Historique | Voir | Annoter | Télécharger (4,93 ko)
| 1 |
# Copyright (C) 2010, Jesper Friis
|
|---|---|
| 2 |
# (see accompanying license files for details).
|
| 3 |
|
| 4 |
"""
|
| 5 |
A module for ASE for simple creation of crystalline structures from
|
| 6 |
knowledge of the space group.
|
| 7 |
|
| 8 |
"""
|
| 9 |
|
| 10 |
import numpy as np |
| 11 |
|
| 12 |
import ase |
| 13 |
from ase.atoms import string2symbols |
| 14 |
from spacegroup import Spacegroup |
| 15 |
from cell import cellpar_to_cell |
| 16 |
|
| 17 |
__all__ = ['crystal']
|
| 18 |
|
| 19 |
|
| 20 |
|
| 21 |
def crystal(symbols=None, basis=None, spacegroup=1, setting=1, |
| 22 |
cell=None, cellpar=None, |
| 23 |
ab_normal=(0,0,1), a_direction=None, size=(1,1,1), |
| 24 |
ondublicates='warn', symprec=0.001, |
| 25 |
pbc=True, **kwargs):
|
| 26 |
"""Create an Atoms instance for a conventional unit cell of a
|
| 27 |
space group.
|
| 28 |
|
| 29 |
Parameters:
|
| 30 |
|
| 31 |
symbols : string | sequence of strings
|
| 32 |
Either a string formula or a sequence of element
|
| 33 |
symbols. E.g. ('Na', 'Cl') and 'NaCl' are equivalent.
|
| 34 |
basis : list of scaled coordinates | atoms instance
|
| 35 |
Positions of the non-equivalent sites given either as
|
| 36 |
scaled positions or through an atoms instance.
|
| 37 |
spacegroup : int | string | Spacegroup instance
|
| 38 |
Space group given either as its number in International Tables
|
| 39 |
or as its Hermann-Mauguin symbol.
|
| 40 |
setting : 1 | 2
|
| 41 |
Space group setting.
|
| 42 |
cell : 3x3 matrix
|
| 43 |
Unit cell vectors.
|
| 44 |
cellpar : [a, b, c, alpha, beta, gamma]
|
| 45 |
Cell parameters with angles in degree. Is not used when `cell`
|
| 46 |
is given.
|
| 47 |
ab_normal : vector
|
| 48 |
Is used to define the orientation of the unit cell relative
|
| 49 |
to the Cartesian system when `cell` is not given. It is the
|
| 50 |
normal vector of the plane spanned by a and b.
|
| 51 |
a_direction : vector
|
| 52 |
Defines the orientation of the unit cell a vector. a will be
|
| 53 |
parallel to the projection of `a_direction` onto the a-b plane.
|
| 54 |
size : 3 positive integers
|
| 55 |
How many times the conventional unit cell should be repeated
|
| 56 |
in each direction.
|
| 57 |
ondublicates : 'keep' | 'replace' | 'warn' | 'error'
|
| 58 |
Action if `basis` contain symmetry-equivalent positions:
|
| 59 |
'keep' - ignore additional symmetry-equivalent positions
|
| 60 |
'replace' - reolace
|
| 61 |
'warn' - like 'keep', but issue an UserWarning
|
| 62 |
'error' - raises a SpacegroupValueError
|
| 63 |
symprec : float
|
| 64 |
Minimum "distance" betweed two sites in scaled coordinates
|
| 65 |
before they are counted as the same site.
|
| 66 |
pbc : one or three bools
|
| 67 |
Periodic boundary conditions flags. Examples: True,
|
| 68 |
False, 0, 1, (1, 1, 0), (True, False, False). Default
|
| 69 |
is True.
|
| 70 |
|
| 71 |
Keyword arguments:
|
| 72 |
|
| 73 |
All additional keyword arguments are passed on to the Atoms constructor.
|
| 74 |
Currently, probably the most useful additional keyword arguments are
|
| 75 |
`constraint` and `calculator`.
|
| 76 |
|
| 77 |
Examples:
|
| 78 |
|
| 79 |
Two diamond unit cells (space group number 227)
|
| 80 |
|
| 81 |
>>> diamond = crystal('C', [(0,0,0)], spacegroup=227,
|
| 82 |
... cellpar=[3.57, 3.57, 3.57, 90, 90, 90], size=(2,1,1))
|
| 83 |
>>> ase.view(diamond) # doctest: +SKIP
|
| 84 |
|
| 85 |
A CoSb3 skutterudite unit cell containing 32 atoms
|
| 86 |
|
| 87 |
>>> skutterudite = crystal(('Co', 'Sb'),
|
| 88 |
... basis=[(0.25,0.25,0.25), (0.0, 0.335, 0.158)],
|
| 89 |
... spacegroup=204, cellpar=[9.04, 9.04, 9.04, 90, 90, 90])
|
| 90 |
>>> len(skutterudite)
|
| 91 |
32
|
| 92 |
"""
|
| 93 |
sg = Spacegroup(spacegroup, setting) |
| 94 |
if isinstance(symbols, ase.Atoms): |
| 95 |
basis = symbols |
| 96 |
symbols = basis.get_chemical_symbols() |
| 97 |
if isinstance(basis, ase.Atoms): |
| 98 |
basis_coords = basis.get_scaled_positions() |
| 99 |
if cell is None and cellpar is None: |
| 100 |
cell = basis.cell |
| 101 |
if symbols is None: |
| 102 |
symbols = basis.get_chemical_symbols() |
| 103 |
else:
|
| 104 |
basis_coords = np.array(basis, dtype=float, copy=False, ndmin=2) |
| 105 |
sites, kinds = sg.equivalent_sites(basis_coords, |
| 106 |
ondublicates=ondublicates, |
| 107 |
symprec=symprec) |
| 108 |
symbols = parse_symbols(symbols) |
| 109 |
symbols = [symbols[i] for i in kinds] |
| 110 |
if cell is None: |
| 111 |
cell = cellpar_to_cell(cellpar, ab_normal, a_direction) |
| 112 |
|
| 113 |
atoms = ase.Atoms(symbols, |
| 114 |
scaled_positions=sites, |
| 115 |
cell=cell, |
| 116 |
pbc=pbc, |
| 117 |
**kwargs) |
| 118 |
|
| 119 |
if isinstance(basis, ase.Atoms): |
| 120 |
for name in basis.arrays: |
| 121 |
if not atoms.has(name): |
| 122 |
array = basis.get_array(name) |
| 123 |
atoms.new_array(name, [array[i] for i in kinds], |
| 124 |
dtype=array.dtype, shape=array.shape[1:])
|
| 125 |
|
| 126 |
if size != (1, 1, 1): |
| 127 |
atoms = atoms.repeat(size) |
| 128 |
return atoms
|
| 129 |
|
| 130 |
def parse_symbols(symbols): |
| 131 |
"""Return `sumbols` as a sequence of element symbols."""
|
| 132 |
if isinstance(symbols, basestring): |
| 133 |
symbols = string2symbols(symbols) |
| 134 |
return symbols
|
| 135 |
|
| 136 |
|
| 137 |
|
| 138 |
|
| 139 |
|
| 140 |
|
| 141 |
#-----------------------------------------------------------------
|
| 142 |
# Self test
|
| 143 |
if __name__ == '__main__': |
| 144 |
import doctest |
| 145 |
print 'doctest: ', doctest.testmod() |
| 146 |
|