root / ase / lattice / spacegroup / crystal.py @ 1
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 |
|