-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathReciprocalLattice.py
More file actions
169 lines (151 loc) · 6.16 KB
/
ReciprocalLattice.py
File metadata and controls
169 lines (151 loc) · 6.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# -*- coding: utf-8 -*-
"""
Created on Mon Jul 22 12:00:35 2024
@author: Jacob Watkiss
"""
"""
-----------------------------------------------
Imports any necessary packages, libraries, modules etc.
-----------------------------------------------
"""
import numpy as np
from read_cif_mod import read_cif
import re
import globalvariables as g
IErr=g.IErr
"""
-----------------------------------------------
Define the function
-----------------------------------------------
"""
def ReciprocalLattice(IDiffractionFLAG,
RLengthX,RLengthY,RLengthZ,RAlpha,RBeta,RGamma,RVolume,RNormDirC,RXDirC,RZDirC,
SSpaceGroupName):
"""
-----------------------------------------------
Define and declare variables
-----------------------------------------------
"""
tiny=np.finfo(np.float32).tiny
RarVecO=np.ones(3,dtype="float")
RbrVecO=np.ones(3,dtype="float")
RcrVecO=np.ones(3,dtype="float")
RXDirO=np.ones(3,dtype="float")
RYDirO=np.ones(3,dtype="float")
RZDirO=np.ones(3,dtype="float")
RTMatC2O=np.zeros((3,3),dtype="float")
RTMatO2M=np.zeros((3,3),dtype="float")
"""
-----------------------------------------------
Direct lattice vectors in an orthogonal reference
frame, Angstrom units
-----------------------------------------------
"""
RaVecO=np.array((RLengthX,0,0),dtype="float")
RbVecO=np.array((RLengthY*g.cos(RGamma),RLengthY*g.sin(RGamma),0),dtype="float")
RcVecO=np.array((RLengthZ*g.cos(RBeta),RLengthZ*((g.cos(RAlpha)-g.cos(RBeta)*g.cos(RGamma))/g.sin(RGamma)),(RLengthZ*RVolume)/(g.sin(RGamma)*RLengthX*RLengthY*RLengthZ)),dtype="float")
"""
-----------------------------------------------
"Some checks for rhombohedral cells?"?
-----------------------------------------------
"""
if IDiffractionFLAG==0:
aMod=np.sqrt(np.dot(RaVecO,RaVecO))
bMod=np.sqrt(np.dot(RbVecO,RbVecO))
cMod=np.sqrt(np.dot(RcVecO,RcVecO))
RTTest=(aMod*bMod*cMod)**(-4)*np.dot(RaVecO,RbVecO)*np.dot(RbVecO,RcVecO)*np.dot(RcVecO,RaVecO)
if re.search("rR",SSpaceGroupName):
if abs(RTTest)<tiny:
SSpaceGroupName="V"
"""Crystal is either Obverse or Reverse
Selection Rules are not in place to determine
the difference, assume the crystal is Obverse"""
else:
SSpaceGroupName="P"
"""Primitive setting (Rhombohedral axes)"""
"""
-----------------------------------------------
Set up Reciprocal Lattice Vectors: orthogonal reference
frame in 1/Angstrom units
-----------------------------------------------
"""
"""
RarDirO,RbrDirO,RcrDirO vectors are reiprocal lattice vectors
2pi/a, 2pi/b, 2pi/c in an orthogonal frame
Note that reciprocal lattice vectors have two pi included,
we are using the Physics convention exp(i*g.r)
"""
RarVecO=2*np.pi*np.cross(RbVecO,RcVecO)/np.dot(RbVecO,np.cross(RcVecO,RaVecO))
RbrVecO=2*np.pi*np.cross(RcVecO,RaVecO)/np.dot(RcVecO,np.cross(RaVecO,RbVecO))
RcrVecO=2*np.pi*np.cross(RaVecO,RbVecO)/np.dot(RaVecO,np.cross(RbVecO,RcVecO))
for i in range(0,3):
if abs(RarVecO[i]<tiny):
RarVecO[i]=0
if abs(RbrVecO[i]<tiny):
RbrVecO[i]=0
if abs(RcrVecO[i]<tiny):
RcrVecO[i]=0
"""
RTmat transforms from crystal (implicit units)
to orthogonal reference frame (Angstrom)
"""
for i in range(len(RaVecO)):
RTMatC2O[i][0]=RaVecO[i]
RTMatC2O[i][1]=RbVecO[i]
RTMatC2O[i][2]=RcVecO[i]
"""
RXDirC is the reciprocal lattice vector that defines the
x-axis of the diffraction pattern and RZDirC the beam
direction, coming from felix.inp. No check has been made
to ensure that they are perpendicular, it is assumed.
RXDirO,RYDirO,RZDirO vectors are UNIT reciprocal lattice
vectors parallel to the above in an orthogonal frame
"""
RXDirO=(RXDirC[0]*RarVecO)+(RXDirC[1]*RbrVecO)+(RXDirC[2]*RcrVecO)
RXDirOMod=np.sqrt(np.dot(RXDirO,RXDirO))
RXDirO=RXDirO/RXDirOMod
RZDirO=(RZDirC[0]*RaVecO)+(RZDirC[1]*RbVecO)+(RZDirC[2]*RcVecO)
RZDirOMod=np.sqrt(np.dot(RZDirO,RZDirO))
RZDirO=RZDirO/RZDirOMod
RYDirO=np.cross(RZDirO,RXDirO)
"""RTMatO2M transforms from orthogonal to microscope reference frame"""
for i in range(len(RXDirO)):
RTMatO2M[0][i]=RXDirO[i]
RTMatO2M[1][i]=RYDirO[i]
RTMatO2M[2][i]=RZDirO[i]
"""
Unit normal to the specimen in REAL space
This is used in diffraction pattern calculation
"""
RNormDirM=np.matmul(RTMatO2M,np.matmul(RTMatC2O,RNormDirC))
RNormDirMMod=np.sqrt(np.dot(RNormDirM,RNormDirM))
RNormDirM=RNormDirM/RNormDirMMod
"""
-----------------------------------------------
Now transform from crystal reference frame to orthogonal
and then to microscope frame
-----------------------------------------------
"""
"""
RaVecM,RbVecM,RcVecM unit cell vectors in Angstrom
units in the microscope frame
"""
RaVecM=np.matmul(RTMatO2M,RaVecO)
RbVecM=np.matmul(RTMatO2M,RbVecO)
RcVecM=np.matmul(RTMatO2M,RcVecO)
"""
-----------------------------------------------
Create new set of reciprocal lattice vectors in microscope
reference frame.
Note that reciprocal lattice vectors have two pi included
We are using the optical convention exp(i*g.r)
-----------------------------------------------
"""
RarVecM=2*np.pi*np.cross(RbVecM,RcVecM)/np.dot(RbVecM,np.cross(RcVecM,RaVecM))
RbrVecM=2*np.pi*np.cross(RcVecM,RaVecM)/np.dot(RcVecM,np.cross(RaVecM,RbVecM))
RcrVecM=2*np.pi*np.cross(RaVecM,RbVecM)/np.dot(RaVecM,np.cross(RbVecM,RcVecM))
return (RTTest,SSpaceGroupName,
RaVecO,RbVecO,RcVecO,RarVecO,RbrVecO,RcrVecO,RXDirO,RYDirO,RZDirO,
RaVecM,RbVecM,RcVecM,RarVecM,RbrVecM,RcrVecM,RNormDirM,
RTMatC2O,RTMatO2M
)