root / ase / xrdebye.py @ 16
Historique | Voir | Annoter | Télécharger (3,57 ko)
1 | 1 | tkerber | from math import exp, pi, sin, sqrt, cos, acos |
---|---|---|---|
2 | 1 | tkerber | import numpy as np |
3 | 1 | tkerber | |
4 | 1 | tkerber | from ase.data import atomic_numbers |
5 | 1 | tkerber | |
6 | 1 | tkerber | # Table (1) of
|
7 | 1 | tkerber | # D. WAASMAIER AND A. KIRFEL, Acta Cryst. (1995). A51, 416-431
|
8 | 1 | tkerber | waasmaier = { |
9 | 1 | tkerber | # a1 b1 a2 b2 a3 b3 a4 b4 a5 b5 c
|
10 | 1 | tkerber | 'C' : [2.657506, 14.780758, 1.078079, 0.776775, 1.490909, 42.086843, -4.241070, -0.000294, 0.713791, 0.239535, 4.297983], |
11 | 1 | tkerber | 'S' : [6.372157, 1.514347, 5.154568, 22.092528, 1.473732, 0.061373, 1.635073, 55.445176, 1.209372, 0.646925, 0.154722], |
12 | 1 | tkerber | 'Pd': [6.121511, 0.062549, 4.784063, 0.784031, 16.631683, 8.751391, 4.318258, 34.489983, 13.246773, 0.784031, 0.883099], |
13 | 1 | tkerber | 'Ag': [6.073874, 0.055333, 17.155437, 7.896512, 4.173344, 28.443739, 0.852238, 110.376108, 17.988685, 0.716809, 0.756603], |
14 | 1 | tkerber | 'Au': [16.777389, 0.122737, 19.317156, 8.621570, 32.979682, 1.256902, 5.595453, 38.008821, 10.576854, 0.000601, -6.279078], |
15 | 1 | tkerber | 'P' : [1.950541, 0.908139, 4.146930, 27.044953, 1.494560, 0.071280, 1.522042, 67.520190, 5.729711, 1.981173, 0.155233], |
16 | 1 | tkerber | 'Cl': [1.446071, 0.052357, 6.870609, 1.193165, 6.151801, 18.343416, 1.750347, 46.398394, 0.634168, 0.401005, 0.146773], |
17 | 1 | tkerber | } |
18 | 1 | tkerber | |
19 | 1 | tkerber | class XrDebye: |
20 | 1 | tkerber | def __init__(self, wavelength, alpha=1.01, damping=0.04, warn=True, |
21 | 1 | tkerber | method='Iwasa'):
|
22 | 1 | tkerber | """
|
23 | 1 | tkerber | Obtain powder x-ray spectra.
|
24 | 1 | tkerber |
|
25 | 1 | tkerber | wavelength in Angstrom
|
26 | 1 | tkerber | damping in Angstrom**2
|
27 | 1 | tkerber | """
|
28 | 1 | tkerber | self.wavelength = wavelength
|
29 | 1 | tkerber | self.damping = damping
|
30 | 1 | tkerber | self.alpha = alpha
|
31 | 1 | tkerber | self.warn = warn
|
32 | 1 | tkerber | self.method = method
|
33 | 1 | tkerber | |
34 | 1 | tkerber | def set_damping(self, damping): |
35 | 1 | tkerber | self.damping = damping
|
36 | 1 | tkerber | |
37 | 1 | tkerber | def get(self, atoms, s): |
38 | 1 | tkerber | """Get the powder x-ray (XRD) pattern using the Debye-Formula.
|
39 | 1 | tkerber |
|
40 | 1 | tkerber | After: T. Iwasa and K. Nobusada, J. Phys. Chem. C 111 (2007) 45
|
41 | 1 | tkerber | s is assumed to be in 1/Angstrom
|
42 | 1 | tkerber | """
|
43 | 1 | tkerber | |
44 | 1 | tkerber | sinth = self.wavelength * s / 2. |
45 | 1 | tkerber | costh = sqrt(1. - sinth**2) |
46 | 1 | tkerber | cos2th = cos(2. * acos(costh))
|
47 | 1 | tkerber | pre = exp(- self.damping * s**2 / 2) |
48 | 1 | tkerber | |
49 | 1 | tkerber | if self.method == 'Iwasa': |
50 | 1 | tkerber | pre *= costh / (1. + self.alpha * cos2th**2) |
51 | 1 | tkerber | |
52 | 1 | tkerber | f = {} |
53 | 1 | tkerber | def atomic(symbol): |
54 | 1 | tkerber | if not f.has_key(symbol): |
55 | 1 | tkerber | if self.method == 'Iwasa': |
56 | 1 | tkerber | f[symbol] = self.get_waasmaier(symbol, s)
|
57 | 1 | tkerber | else:
|
58 | 1 | tkerber | f[symbol] = atomic_numbers[symbol] |
59 | 1 | tkerber | return f[symbol]
|
60 | 1 | tkerber | |
61 | 1 | tkerber | def sinc(x): |
62 | 1 | tkerber | if x < 1.e-6: |
63 | 1 | tkerber | x2 = x * x |
64 | 1 | tkerber | return 1 - x2 / 6. + x2 * x2 / 120. |
65 | 1 | tkerber | else:
|
66 | 1 | tkerber | return sin(x) / x
|
67 | 1 | tkerber | |
68 | 1 | tkerber | I = 0.
|
69 | 1 | tkerber | for a in atoms: |
70 | 1 | tkerber | fa = atomic(a.symbol) |
71 | 1 | tkerber | # print a.symbol, fa
|
72 | 1 | tkerber | for b in atoms: |
73 | 1 | tkerber | fb = atomic(b.symbol) |
74 | 1 | tkerber | |
75 | 1 | tkerber | if a == b:
|
76 | 1 | tkerber | twopis = 0.
|
77 | 1 | tkerber | else:
|
78 | 1 | tkerber | vrij = a.position - b.position |
79 | 1 | tkerber | rij = np.sqrt(np.dot(vrij, vrij)) |
80 | 1 | tkerber | twopisr = 2 * pi * s * rij
|
81 | 1 | tkerber | |
82 | 1 | tkerber | I += fa * fb * sinc(twopisr) |
83 | 1 | tkerber | |
84 | 1 | tkerber | return pre * I
|
85 | 1 | tkerber | |
86 | 1 | tkerber | def get_waasmaier(self, symbol, s): |
87 | 1 | tkerber | """Scattering factor for free atoms."""
|
88 | 1 | tkerber | if symbol == 'H': |
89 | 1 | tkerber | # XXXX implement analytical H
|
90 | 1 | tkerber | return 0 |
91 | 1 | tkerber | elif waasmaier.has_key(symbol):
|
92 | 1 | tkerber | abc = waasmaier[symbol] |
93 | 1 | tkerber | f = abc[10]
|
94 | 1 | tkerber | s2 = s*s |
95 | 1 | tkerber | for i in range(5): |
96 | 1 | tkerber | f += abc[2 * i] * exp(-abc[2 * i + 1] * s2) |
97 | 1 | tkerber | return f
|
98 | 1 | tkerber | if self.warn: |
99 | 1 | tkerber | print '<xrdebye::get_atomic> Element', symbol, 'not available' |
100 | 1 | tkerber | return 0 |