Skip to content

Commit c2c866e

Browse files
committed
Version 3.3.3
Simplified input options for polarised neutron scattering for issue #27. functions_scattering.py - added options 'neutron polarised' and 'xray polarised' to scattering types - Corrected error in sf_magnetic_neutron_polarised classes_scattering.py - improved docs and setup_scatter tkgui/scattering.py - added polarisation options Added example_polarised_neutrons.py, MnO.mcif to example structures and additional tests
1 parent ef046ee commit c2c866e

File tree

8 files changed

+312
-54
lines changed

8 files changed

+312
-54
lines changed
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
#\#CIF_2.0
2+
# Created by the Bilbao Crystallographic Server
3+
# http://www.cryst.ehu.es
4+
# Date: 11/19/2017 17:07:02
5+
# Database entry: 1.31 MnO
6+
# Cif-like file for the case 1.31
7+
8+
9+
data_5yOhtAoR
10+
_audit_creation_date 2017-11-19
11+
_audit_creation_method "Bilbao Crystallographic Server"
12+
13+
_chemical_name_systematic
14+
;
15+
;
16+
_chemical_name_common ?
17+
_chemical_formula_moiety ?
18+
_chemical_formula_structural ?
19+
_chemical_formula_analytical ?
20+
_chemical_formula_iupac ?
21+
_chemical_formula_sum 'Mn O'
22+
_chemical_formula_weight ?
23+
_chemical_melting_point ?
24+
_chemical_compound_source ?
25+
_chemical_absolute_configuration .
26+
27+
28+
_citation_journal_abbrev "PHYSICAL REVIEW LETTERS"
29+
_citation_journal_volume 96
30+
_citation_page_first ?
31+
_citation_page_last ?
32+
_citation_article_id 047209
33+
_citation_year 2006
34+
_citation_DOI 10.1103/physrevlett.96.047209
35+
36+
loop_
37+
_citation_author_name
38+
"A.L. Goodwin"
39+
"M.G. Tucker"
40+
"M.T. Dove"
41+
"D.A. Keen"
42+
43+
44+
45+
46+
47+
_atomic_positions_source_database_code_ICSD 9864
48+
_atomic_positions_source_other .
49+
50+
_transition_temperature 120
51+
_experiment_temperature 10
52+
53+
loop_
54+
_irrep_id
55+
_irrep_dimension
56+
_irrep_small_dimension
57+
_irrep_direction_type
58+
_irrep_action
59+
_irrep_modes_number
60+
_irrep_presence
61+
mL3+ 8 2 special primary . .
62+
63+
_exptl_crystal_magnetic_properties_details
64+
;
65+
NSD
66+
Additional modulation observed. Only average structure presented here
67+
Atomic positions used are of the parent phase (icsd 9864).
68+
The reference reports a C2 positional structure.
69+
Its deviations from from the parent structure used here smaller than 0.1 A.
70+
Modulus magnetic moment Mn: 5.65
71+
Other source: Phys. Rev. 83 (1951) 333
72+
The magnetic symmetry implies the space group C2/m as effective
73+
symmetry for the positional structure, higher than the symmetry C2
74+
proposed in the reference.
75+
;
76+
77+
_active_magnetic_irreps_details
78+
;
79+
1k magnetic structure
80+
a secondary magnetic irrep possible but not present: mL2+
81+
;
82+
83+
_parent_space_group.name_H-M_alt 'F m -3m'
84+
_parent_space_group.IT_number 225
85+
_parent_space_group.transform_Pp_abc 'a,b,c;0,0,0'
86+
87+
loop_
88+
_parent_propagation_vector.id
89+
_parent_propagation_vector.kxkykz
90+
k1 [0.5 0.5 0.5]
91+
92+
_parent_space_group.child_transform_Pp_abc '2a,2b,2c;0,0,0'
93+
_space_group_magn.transform_BNS_Pp_abc 'a/4+b/4-c/2,a/4-b/4,-a/2-b/2;0,0,0'
94+
95+
96+
_space_group_magn.number_BNS 15.90
97+
_space_group_magn.name_BNS "C_c 2/c"
98+
_space_group_magn.point_group_name "2/m1'"
99+
_space_group_magn.point_group_number "5.2.13"
100+
_cell_length_a 8.8920
101+
_cell_length_b 8.8920
102+
_cell_length_c 8.8920
103+
_cell_angle_alpha 90.0000
104+
_cell_angle_beta 90.0000
105+
_cell_angle_gamma 90.0000
106+
107+
loop_
108+
_space_group_symop_magn_operation.id
109+
_space_group_symop_magn_operation.xyz
110+
1 x,y,z,+1
111+
2 -y+3/4,-x+3/4,-z,+1
112+
3 -x+1/4,-y+3/4,-z,+1
113+
4 y,x+1/2,z,+1
114+
115+
loop_
116+
_space_group_symop_magn_centering.id
117+
_space_group_symop_magn_centering.xyz
118+
1 x,y,z,+1
119+
2 x,y+1/4,z+3/4,+1
120+
3 x,y+1/2,z+1/2,+1
121+
4 x,y+3/4,z+1/4,+1
122+
5 x+1/4,y,z+3/4,+1
123+
6 x+1/4,y+1/4,z+1/2,+1
124+
7 x+1/4,y+1/2,z+1/4,+1
125+
8 x+1/4,y+3/4,z,+1
126+
9 x+1/2,y,z+1/2,+1
127+
10 x+1/2,y+1/4,z+1/4,+1
128+
11 x+1/2,y+1/2,z,+1
129+
12 x+1/2,y+3/4,z+3/4,+1
130+
13 x+3/4,y,z+1/4,+1
131+
14 x+3/4,y+1/4,z,+1
132+
15 x+3/4,y+1/2,z+3/4,+1
133+
16 x+3/4,y+3/4,z+1/2,+1
134+
17 x+3/4,y+3/4,z,-1
135+
18 x+3/4,y,z+3/4,-1
136+
19 x+3/4,y+1/4,z+1/2,-1
137+
20 x+3/4,y+1/2,z+1/4,-1
138+
21 x,y+3/4,z+3/4,-1
139+
22 x,y,z+1/2,-1
140+
23 x,y+1/4,z+1/4,-1
141+
24 x,y+1/2,z,-1
142+
25 x+1/4,y+3/4,z+1/2,-1
143+
26 x+1/4,y,z+1/4,-1
144+
27 x+1/4,y+1/4,z,-1
145+
28 x+1/4,y+1/2,z+3/4,-1
146+
29 x+1/2,y+3/4,z+1/4,-1
147+
30 x+1/2,y,z,-1
148+
31 x+1/2,y+1/4,z+3/4,-1
149+
32 x+1/2,y+1/2,z+1/2,-1
150+
151+
loop_
152+
_atom_site_label
153+
_atom_site_type_symbol
154+
_atom_site_fract_x
155+
_atom_site_fract_y
156+
_atom_site_fract_z
157+
_atom_site_occupancy
158+
Mn1 Mn 0.00000 0.00000 0.00000 1
159+
O1 O 0.75000 0.50000 0.00000 1
160+
161+
loop_
162+
_atom_site_moment.label
163+
_atom_site_moment.crystalaxis_x
164+
_atom_site_moment.crystalaxis_y
165+
_atom_site_moment.crystalaxis_z
166+
_atom_site_moment.symmform
167+
Mn1 2.31 2.31 -4.62 mx,mx,mz
168+

Dans_Diffraction/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
26/09/24 3.3.0 Added complex neutron scattering lengths for isotopes from package periodictable. Thanks thamnos!
8484
06/11/24 3.3.1 Fixed incorrect cell basis for triclinic cells. Added functions_lattice.py and tests. Thanks LeeRichter!
8585
20/11/24 3.3.2 Added alternate option for neutron scattering lengths
86+
23/12/24 3.3.3 Added scattering options for polarised neutron and x-ray scattering. Thanks dragonyanglong!
8687
8788
Acknoledgements:
8889
2018 Thanks to Hepesu for help with Python3 support and ideas about breaking up calculations
@@ -109,6 +110,7 @@
109110
Aug 2024 Thanks to MaxPelly for spell checks in examples
110111
Sep 2024 Thanks to thamnos for suggestion to add complex neutron scattering lengths
111112
Oct 2024 Thanks to Lee Richter for pointing out the error in triclinic basis definition
113+
Dec 2024 Thanks to dragonyanglong for pointing out the error with magnetic neutron scattering
112114
113115
-----------------------------------------------------------------------------
114116
Copyright 2024 Diamond Light Source Ltd.
@@ -163,8 +165,8 @@
163165
'Structures', 'Fdmnes', 'FdmnesAnalysis']
164166

165167

166-
__version__ = '3.3.2'
167-
__date__ = '2024/11/20'
168+
__version__ = '3.3.3'
169+
__date__ = '2024/12/23'
168170

169171

170172
# Build

Dans_Diffraction/classes_scattering.py

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
Diamond
88
2017
99
10-
Version 2.3.4
11-
Last updated: 17/05/24
10+
Version 2.3.5
11+
Last updated: 23/12/24
1212
1313
Version History:
1414
10/09/17 0.1 Program created
@@ -40,6 +40,7 @@
4040
15/05/24 2.3.4 Added "save" and "load" methods to structure factor calculation, improved powder for large calculations
4141
16/05/24 2.3.4 Added printed progress bar to generate_intensity_cut during convolusion
4242
17/05/24 2.3.4 Changed generate_intensity_cut to make it much faster
43+
23/12/24 2.3.5 Added polarised neutron options
4344
4445
@author: DGPorter
4546
"""
@@ -53,13 +54,7 @@
5354
from . import multiple_scattering as ms
5455
# from . import tensor_scattering as ts # Removed V1.7
5556

56-
__version__ = '2.3.4'
57-
__scattering_types__ = {'xray': ['xray', 'x', 'x-ray', 'thomson', 'charge'],
58-
'neutron': ['neutron', 'n', 'nuclear'],
59-
'xray magnetic': ['xray magnetic', 'magnetic xray', 'spin xray', 'xray spin'],
60-
'neutron magnetic': ['neutron magnetic', 'magnetic neutron', 'magnetic'],
61-
'xray resonant': ['xray resonant', 'resonant', 'resonant xray', 'rxs'],
62-
'xray dispersion': ['dispersion', 'xray dispersion']}
57+
__version__ = '2.3.5'
6358

6459

6560
class Scattering:
@@ -119,14 +114,14 @@ class Scattering:
119114
# Polarisation Options
120115
_polarised = False
121116
_polarisation = 'sp'
122-
_polarisation_vector_incident = [0, 1, 0]
117+
_polarisation_vector_incident = (0, 1, 0)
123118

124119
# Radiation energy
125120
_energy_kev = fg.Cu
126121

127122
# Resonant X-ray Options
128123
_azimuthal_angle = 0
129-
_azimuthal_reference = [1,0,0]
124+
_azimuthal_reference = [1, 0, 0]
130125
_resonant_flm = (0, 1, 0)
131126
_resonant_approximation_e1e1 = True
132127
_resonant_approximation_e2e2 = False
@@ -137,7 +132,7 @@ def __init__(self, xtl):
137132
self.xtl = xtl
138133

139134
# Initialise the scattering type container
140-
self.Type = ScatteringTypes(self, __scattering_types__)
135+
self.Type = ScatteringTypes(self, fs.SCATTERING_TYPES)
141136

142137
def __repr__(self):
143138
return 'Scattering(%s, %s)' % (self.xtl.name, self._scattering_type)
@@ -195,7 +190,7 @@ def setup_scatter(self, scattering_type=None, energy_kev=None, wavelength_a=None
195190
"""
196191
Simple way to set scattering parameters, each parameter is internal to xtl (self)
197192
198-
scattering_type: self._scattering type : 'xray','neutron','xray magnetic','neutron magnetic','xray resonant', 'xray dispersion'
193+
scattering_type: self._scattering type : 'xray','neutron','xray magnetic','neutron magnetic','xray resonant', 'xray dispersion', 'neutron polarised', 'xray polarised'
199194
energy_kev : self._energy_kev : radiation energy in keV
200195
wavelength_a: self._wavelength_a : radiation wavelength in Angstrom
201196
powder_units: self._powder_units : units to use when displaying/ plotting ['twotheta', 'd',' 'q']
@@ -379,9 +374,11 @@ def structure_factor(self, hkl=None, scattering_type=None, int_hkl=True, **kwarg
379374
'xray' - uses x-ray form factors
380375
'neutron' - uses neutron scattering lengths
381376
'xray magnetic' - calculates the magnetic (non-resonant) component of the x-ray scattering
382-
'neutron magnetic' - calculates the magnetic component of neutron scattering
377+
'neutron magnetic' - calculates the magnetic component of neutron scattering with average polarisation
383378
'xray resonant' - calculates magnetic resonant scattering
384379
'xray dispersion' - uses x-ray form factors including f'-if'' components
380+
'neutron polarised' - calcualtes magnetic component with incident polarised neutrons
381+
'xray polarised' - calcualtes magnetic component with incident polarised x-rays
385382
386383
Notes:
387384
- Uses x-ray atomic form factors, calculated from approximated tables in the ITC
@@ -1088,7 +1085,7 @@ def magnetic_neutron(self, HKL):
10881085
# Calculate intensity
10891086
I = SF * np.conj(SF)
10901087
return np.real(I)
1091-
1088+
10921089
def xray_magnetic(self, HKL):
10931090
"""
10941091
Calculate the non-resonant magnetic component of the structure factor
@@ -1102,51 +1099,53 @@ def xray_magnetic(self, HKL):
11021099
No orbital component assumed
11031100
magnetic moments assumed to be in the same reference frame as the polarisation
11041101
"""
1105-
1106-
HKL = np.asarray(np.rint(HKL),dtype=float).reshape([-1,3])
1102+
1103+
HKL = np.asarray(np.rint(HKL), dtype=float).reshape([-1, 3])
11071104
Nref = len(HKL)
1108-
1109-
uvw,type,label,occ,uiso,mxmymz = self.xtl.Structure.get()
1105+
1106+
uvw, type, label, occ, uiso, mxmymz = self.xtl.Structure.get()
11101107
Nat = len(uvw)
1111-
1108+
11121109
Qmag = self.xtl.Cell.Qmag(HKL)
1113-
1110+
11141111
# Get magnetic form factors
11151112
if self._use_magnetic_form_factor:
1116-
ff = fc.magnetic_form_factor(type,Qmag)
1113+
ff = fc.magnetic_form_factor(type, Qmag)
11171114
else:
1118-
ff = np.ones([len(HKL),Nat])
1119-
1115+
ff = np.ones([len(HKL), Nat])
1116+
11201117
# Calculate moment
1121-
momentmag = fg.mag(mxmymz).reshape([-1,1])
1122-
momentxyz = self.xtl.Cell.calculateR(mxmymz) # moment direction in cartesian reference frame
1123-
moment = momentmag*fg.norm(momentxyz) # broadcast n*1 x n*3 = n*3
1118+
momentmag = fg.mag(mxmymz).reshape([-1, 1])
1119+
momentxyz = self.xtl.Cell.calculateR(mxmymz) # moment direction in cartesian reference frame
1120+
moment = momentmag * fg.norm(momentxyz) # broadcast n*1 x n*3 = n*3
11241121
moment[np.isnan(moment)] = 0.
1125-
1122+
11261123
# Calculate dot product
1127-
dot_KR = np.dot(HKL,uvw.T)
1128-
1124+
dot_KR = np.dot(HKL, uvw.T)
1125+
11291126
# Calculate structure factor
1130-
SF = np.zeros(Nref,dtype=complex)
1127+
SF = np.zeros(Nref, dtype=complex)
11311128
for n in range(Nref):
11321129
# Calculate vector structure factor
1133-
SFm = [0.,0.,0.]
1134-
for m,mom in enumerate(moment):
1135-
SFm = SFm + ff[n,m]*np.exp(1j*2*np.pi*dot_KR[n,m])*mom
1136-
1130+
SFm = [0., 0., 0.]
1131+
for m, mom in enumerate(moment):
1132+
SFm = SFm + ff[n, m] * np.exp(1j * 2 * np.pi * dot_KR[n, m]) * mom
1133+
11371134
# Calculate polarisation with incident x-ray
11381135
# The reference frame of the x-ray and the crystal are assumed to be the same
11391136
# i.e. pol=[1,0,0] || mom=[1,0,0] || (1,0,0)
11401137
if self._polarised:
1141-
SF[n] = np.dot(SFm,self._polarisation_vector_incident)
1138+
SF[n] = np.dot(SFm, self._polarisation_vector_incident)
11421139
else:
1143-
#SF[n] = np.dot(SFm,SFm) # maximum possible
1144-
SF[n] = (np.dot(SFm,[1,0,0]) + np.dot(SFm,[0,1,0]) + np.dot(SFm,[0,0,1]))/3 # average polarisation
1145-
1146-
SF = SF/self.xtl.scale
1147-
1140+
# SF[n] = np.dot(SFm,SFm) # maximum possible
1141+
SF[n] = (
1142+
np.dot(SFm, [1, 0, 0]) + np.dot(SFm, [0, 1, 0]) + np.dot(SFm, [0, 0, 1])
1143+
) / 3 # average polarisation
1144+
1145+
SF = SF / self.xtl.scale
1146+
11481147
if self._return_structure_factor: return SF
1149-
1148+
11501149
# Calculate intensity
11511150
I = SF * np.conj(SF)
11521151
return np.real(I)
@@ -1207,7 +1206,7 @@ def xray_resonant(self, HKL, energy_kev=None, polarisation='sp', F0=1, F1=1, F2=
12071206

12081207
# Calculate structure factor
12091208
# Broadcasting used on 2D fxres
1210-
SF[:,psival] = np.sum(fxres*dw*occ*np.exp(1j*2*np.pi*dot_KR),axis=1)
1209+
SF[:, psival] = np.sum(fxres*dw*occ*np.exp(1j*2*np.pi*dot_KR), axis=1)
12111210

12121211
SF = SF/self.xtl.scale
12131212

0 commit comments

Comments
 (0)