Statistiques
| Révision :

root / ase / lattice / spacegroup / cell.py @ 20

Historique | Voir | Annoter | Télécharger (3,36 ko)

1 1 tkerber
# Copyright (C) 2010, Jesper Friis
2 1 tkerber
# (see accompanying license files for details).
3 1 tkerber
4 1 tkerber
import numpy as np
5 1 tkerber
from numpy import pi, sin, cos, tan, arcsin, arccos, arctan, sqrt
6 1 tkerber
from numpy import dot
7 1 tkerber
from numpy.linalg import norm
8 1 tkerber
9 1 tkerber
import ase
10 1 tkerber
11 1 tkerber
12 1 tkerber
__ALL__ = ['cell_to_cellpar', 'cellpar_to_cell', 'metric_from_cell']
13 1 tkerber
14 1 tkerber
15 1 tkerber
def unit_vector(x):
16 1 tkerber
    """Return a unit vector in the same direction as x."""
17 1 tkerber
    y = np.array(x, dtype='float')
18 1 tkerber
    return y/norm(y)
19 1 tkerber
20 1 tkerber
21 1 tkerber
def angle(x, y):
22 1 tkerber
    """Return the angle between vectors a and b in degrees."""
23 1 tkerber
    return arccos(dot(x, y)/(norm(x)*norm(y)))*180./pi
24 1 tkerber
25 1 tkerber
26 1 tkerber
def cell_to_cellpar(cell):
27 1 tkerber
    """Returns the cell parameters [a, b, c, alpha, beta, gamma] as a
28 1 tkerber
    numpy array."""
29 1 tkerber
    va, vb, vc = cell
30 1 tkerber
    a = np.linalg.norm(va)
31 1 tkerber
    b = np.linalg.norm(vb)
32 1 tkerber
    c = np.linalg.norm(vc)
33 1 tkerber
    alpha = 180.0/pi*arccos(dot(vb, vc)/(b*c))
34 1 tkerber
    beta  = 180.0/pi*arccos(dot(vc, va)/(c*a))
35 1 tkerber
    gamma = 180.0/pi*arccos(dot(va, vb)/(a*b))
36 1 tkerber
    return np.array([a, b, c, alpha, beta, gamma])
37 1 tkerber
38 1 tkerber
39 1 tkerber
def cellpar_to_cell(cellpar, ab_normal=(0,0,1), a_direction=None):
40 1 tkerber
    """Return a 3x3 cell matrix from `cellpar` = [a, b, c, alpha,
41 1 tkerber
    beta, gamma].  The returned cell is orientated such that a and b
42 1 tkerber
    are normal to `ab_normal` and a is parallel to the projection of
43 1 tkerber
    `a_direction` in the a-b plane.
44 1 tkerber

45 1 tkerber
    Default `a_direction` is (1,0,0), unless this is parallel to
46 1 tkerber
    `ab_normal`, in which case default `a_direction` is (0,0,1).
47 1 tkerber

48 1 tkerber
    The returned cell has the vectors va, vb and vc along the rows. The
49 1 tkerber
    cell will be oriented such that va and vb are normal to `ab_normal`
50 1 tkerber
    and va will be along the projection of `a_direction` onto the a-b
51 1 tkerber
    plane.
52 1 tkerber

53 1 tkerber
    Example:
54 1 tkerber

55 1 tkerber
    >>> cell = cellpar_to_cell([1, 2, 4,  10,  20, 30], (0,1,1), (1,2,3))
56 1 tkerber
    >>> np.round(cell, 3)
57 1 tkerber
    array([[ 0.816, -0.408,  0.408],
58 1 tkerber
           [ 1.992, -0.13 ,  0.13 ],
59 1 tkerber
           [ 3.859, -0.745,  0.745]])
60 1 tkerber

61 1 tkerber
    """
62 1 tkerber
    if a_direction is None:
63 1 tkerber
        if np.linalg.norm(np.cross(ab_normal, (1,0,0))) < 1e-5:
64 1 tkerber
            a_direction = (0,0,1)
65 1 tkerber
        else:
66 1 tkerber
            a_direction = (1,0,0)
67 1 tkerber
68 1 tkerber
    # Define rotated X,Y,Z-system, with Z along ab_normal and X along
69 1 tkerber
    # the projection of a_direction onto the normal plane of Z.
70 1 tkerber
    ad = np.array(a_direction)
71 1 tkerber
    Z = unit_vector(ab_normal)
72 1 tkerber
    X = unit_vector(ad - dot(ad, Z)*Z)
73 1 tkerber
    Y = np.cross(Z, X)
74 1 tkerber
75 1 tkerber
    # Express va, vb and vc in the X,Y,Z-system
76 1 tkerber
    alpha, beta, gamma = 90., 90., 90.
77 1 tkerber
    if isinstance(cellpar, (int, long, float)):
78 1 tkerber
        a = b = c = cellpar
79 1 tkerber
    elif len(cellpar) == 1:
80 1 tkerber
        a = b = c = cellpar[0]
81 1 tkerber
    elif len(cellpar) == 3:
82 1 tkerber
        a, b, c = cellpar
83 1 tkerber
        alpha, beta, gamma = 90., 90., 90.
84 1 tkerber
    else:
85 1 tkerber
        a, b, c, alpha, beta, gamma = cellpar
86 1 tkerber
    alpha *= pi/180.0
87 1 tkerber
    beta *= pi/180.0
88 1 tkerber
    gamma *= pi/180.0
89 1 tkerber
    va = a * np.array([1, 0, 0])
90 1 tkerber
    vb = b * np.array([cos(gamma), sin(gamma), 0])
91 1 tkerber
    cx = cos(beta)
92 1 tkerber
    cy = (cos(alpha) - cos(beta)*cos(gamma))/sin(gamma)
93 1 tkerber
    cz = sqrt(1. - cx*cx - cy*cy)
94 1 tkerber
    vc = c * np.array([cx, cy, cz])
95 1 tkerber
96 1 tkerber
    # Convert to the Cartesian x,y,z-system
97 1 tkerber
    abc = np.vstack((va, vb, vc))
98 1 tkerber
    T = np.vstack((X, Y, Z))
99 1 tkerber
    cell = dot(abc, T)
100 1 tkerber
    return cell
101 1 tkerber
102 1 tkerber
103 1 tkerber
def metric_from_cell(cell):
104 1 tkerber
    """Calculates the metric matrix from cell, which is given in the
105 1 tkerber
    Cartesian system."""
106 1 tkerber
    cell = np.asarray(cell, dtype=float)
107 1 tkerber
    return np.dot(cell, cell.T)
108 1 tkerber
109 1 tkerber
110 1 tkerber
111 1 tkerber
112 1 tkerber
if __name__ == '__main__':
113 1 tkerber
    import doctest
114 1 tkerber
    print 'doctest: ', doctest.testmod()