syned 1.0.47__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- syned/__init__.py +0 -0
- syned/__test/__init__.py +46 -0
- syned/__test/test.py +28 -0
- syned/beamline/__init__.py +1 -0
- syned/beamline/beamline.py +155 -0
- syned/beamline/beamline_element.py +76 -0
- syned/beamline/element_coordinates.py +199 -0
- syned/beamline/optical_element.py +47 -0
- syned/beamline/optical_element_with_surface_shape.py +126 -0
- syned/beamline/optical_elements/__init__.py +1 -0
- syned/beamline/optical_elements/absorbers/__init__.py +0 -0
- syned/beamline/optical_elements/absorbers/absorber.py +21 -0
- syned/beamline/optical_elements/absorbers/beam_stopper.py +64 -0
- syned/beamline/optical_elements/absorbers/filter.py +61 -0
- syned/beamline/optical_elements/absorbers/holed_filter.py +67 -0
- syned/beamline/optical_elements/absorbers/slit.py +81 -0
- syned/beamline/optical_elements/crystals/__init__.py +1 -0
- syned/beamline/optical_elements/crystals/crystal.py +70 -0
- syned/beamline/optical_elements/gratings/__init__.py +1 -0
- syned/beamline/optical_elements/gratings/grating.py +279 -0
- syned/beamline/optical_elements/ideal_elements/__init__.py +1 -0
- syned/beamline/optical_elements/ideal_elements/ideal_element.py +16 -0
- syned/beamline/optical_elements/ideal_elements/ideal_fzp.py +183 -0
- syned/beamline/optical_elements/ideal_elements/ideal_lens.py +54 -0
- syned/beamline/optical_elements/ideal_elements/screen.py +16 -0
- syned/beamline/optical_elements/mirrors/__init__.py +1 -0
- syned/beamline/optical_elements/mirrors/mirror.py +39 -0
- syned/beamline/optical_elements/multilayers/__init__.py +46 -0
- syned/beamline/optical_elements/multilayers/multilayer.py +45 -0
- syned/beamline/optical_elements/refractors/__init__.py +1 -0
- syned/beamline/optical_elements/refractors/crl.py +79 -0
- syned/beamline/optical_elements/refractors/interface.py +61 -0
- syned/beamline/optical_elements/refractors/lens.py +105 -0
- syned/beamline/shape.py +2803 -0
- syned/storage_ring/__init__.py +1 -0
- syned/storage_ring/electron_beam.py +804 -0
- syned/storage_ring/empty_light_source.py +40 -0
- syned/storage_ring/light_source.py +90 -0
- syned/storage_ring/magnetic_structure.py +8 -0
- syned/storage_ring/magnetic_structures/__init__.py +1 -0
- syned/storage_ring/magnetic_structures/bending_magnet.py +329 -0
- syned/storage_ring/magnetic_structures/insertion_device.py +169 -0
- syned/storage_ring/magnetic_structures/undulator.py +413 -0
- syned/storage_ring/magnetic_structures/wiggler.py +27 -0
- syned/syned_object.py +264 -0
- syned/util/__init__.py +22 -0
- syned/util/json_tools.py +198 -0
- syned/widget/__init__.py +0 -0
- syned/widget/widget_decorator.py +67 -0
- syned-1.0.47.dist-info/METADATA +88 -0
- syned-1.0.47.dist-info/RECORD +54 -0
- syned-1.0.47.dist-info/WHEEL +5 -0
- syned-1.0.47.dist-info/licenses/LICENSE +20 -0
- syned-1.0.47.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base class for LighSource, which contains:
|
|
3
|
+
- a name
|
|
4
|
+
- an electron beam
|
|
5
|
+
- a magnetic structure
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from syned.syned_object import SynedObject
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EmptyLightSource(SynedObject):
|
|
12
|
+
"""
|
|
13
|
+
Defines an empty light source. This is for creating "movable" beamlines (using Beamline()). These are beamlines
|
|
14
|
+
that do not have a particular light source.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
name : str, optional
|
|
19
|
+
The name of the (empty) light source.
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
def __init__(self, name="Empty"):
|
|
23
|
+
self._name = name
|
|
24
|
+
# support text containg name of variable, help text and unit. Will be stored in self._support_dictionary
|
|
25
|
+
self._set_support_text([
|
|
26
|
+
("name", "Name",""),
|
|
27
|
+
] )
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_name(self):
|
|
31
|
+
"""
|
|
32
|
+
Returns the name of the light source.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
str
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
return self._name
|
|
40
|
+
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
from syned.syned_object import SynedObject
|
|
6
|
+
from syned.storage_ring.magnetic_structure import MagneticStructure
|
|
7
|
+
from syned.storage_ring.electron_beam import ElectronBeam
|
|
8
|
+
|
|
9
|
+
class LightSource(SynedObject):
|
|
10
|
+
"""
|
|
11
|
+
Base class for LighSource. A light source contains:
|
|
12
|
+
* a name
|
|
13
|
+
* an electron beam
|
|
14
|
+
* a magnetic structure
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
name : str, optional
|
|
19
|
+
The light source name.
|
|
20
|
+
electron_beam : instance of ElectronBeam, optional
|
|
21
|
+
The electron beam. If None, it is initialized with ElectronBeam().
|
|
22
|
+
magnetic_structure : instance of MagneticStructure, optional
|
|
23
|
+
The electron beam. If None, it is initialized with MagneticStructure().
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
def __init__(self, name="Undefined", electron_beam=None, magnetic_structure=None):
|
|
27
|
+
self._name = name
|
|
28
|
+
if electron_beam is None:
|
|
29
|
+
self._electron_beam = ElectronBeam()
|
|
30
|
+
else:
|
|
31
|
+
self._electron_beam = electron_beam
|
|
32
|
+
if magnetic_structure is None:
|
|
33
|
+
self._magnetic_structure = MagneticStructure()
|
|
34
|
+
else:
|
|
35
|
+
self._magnetic_structure = magnetic_structure
|
|
36
|
+
# support text containg name of variable, help text and unit. Will be stored in self._support_dictionary
|
|
37
|
+
self._set_support_text([
|
|
38
|
+
("name", "Name",""),
|
|
39
|
+
("electron_beam", "Electron Beam",""),
|
|
40
|
+
("magnetic_structure","Magnetic Strtructure",""),
|
|
41
|
+
] )
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_name(self):
|
|
45
|
+
"""
|
|
46
|
+
Returns the name of the light source.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
str
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
return self._name
|
|
54
|
+
|
|
55
|
+
def get_electron_beam(self):
|
|
56
|
+
"""
|
|
57
|
+
Returns the electron beam.
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
instance of ElectronBeam
|
|
62
|
+
|
|
63
|
+
"""
|
|
64
|
+
return self._electron_beam
|
|
65
|
+
|
|
66
|
+
def get_magnetic_structure(self):
|
|
67
|
+
"""
|
|
68
|
+
Returns the magnetic structure.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
instance of MagneticStructure
|
|
73
|
+
|
|
74
|
+
"""
|
|
75
|
+
return self._magnetic_structure
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
if __name__ == "__main__":
|
|
81
|
+
|
|
82
|
+
from syned.storage_ring.magnetic_structures.undulator import Undulator
|
|
83
|
+
|
|
84
|
+
eb = ElectronBeam.initialize_as_pencil_beam( energy_in_GeV=2.0,energy_spread=0.0,current=0.5)
|
|
85
|
+
ms = Undulator.initialize_as_vertical_undulator( K=1.8, period_length=0.038, periods_number=56.0 )
|
|
86
|
+
|
|
87
|
+
light_source = LightSource(name="",electron_beam=eb,magnetic_structure=ms)
|
|
88
|
+
|
|
89
|
+
print(light_source.info())
|
|
90
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base class for a Bending Magnet
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
from syned.storage_ring.magnetic_structure import MagneticStructure
|
|
7
|
+
import numpy
|
|
8
|
+
import scipy.constants as codata
|
|
9
|
+
|
|
10
|
+
class BendingMagnet(MagneticStructure):
|
|
11
|
+
"""
|
|
12
|
+
Constructor.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
radius : float, optional
|
|
17
|
+
Physical Radius/curvature of the magnet in m.
|
|
18
|
+
magnetic_field : float, optional
|
|
19
|
+
Magnetic field strength in T.
|
|
20
|
+
length : float, optional
|
|
21
|
+
physical length of the bending magnet (along the arc) in m.
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
def __init__(self, radius=1.0, magnetic_field=1.0, length=1.0):
|
|
25
|
+
MagneticStructure.__init__(self)
|
|
26
|
+
self._radius = radius
|
|
27
|
+
self._magnetic_field = magnetic_field
|
|
28
|
+
self._length = length
|
|
29
|
+
|
|
30
|
+
# support text contaning name of variable, help text and unit. Will be stored in self._support_dictionary
|
|
31
|
+
self._set_support_text([
|
|
32
|
+
("radius" , "Radius of bending magnet" , "m" ),
|
|
33
|
+
("magnetic_field" , "Magnetic field", "T" ),
|
|
34
|
+
("length" , "Bending magnet length", "m" ),
|
|
35
|
+
] )
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
#methods for practical calculations
|
|
39
|
+
#
|
|
40
|
+
@classmethod
|
|
41
|
+
def initialize_from_magnetic_field_divergence_and_electron_energy(cls,
|
|
42
|
+
magnetic_field=1.0,
|
|
43
|
+
divergence=1e-3,
|
|
44
|
+
electron_energy_in_GeV=1.0,
|
|
45
|
+
**params):
|
|
46
|
+
"""
|
|
47
|
+
Returns an bending magnet from the magnetic field and electron energy.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
magnetic_field : float, optional
|
|
52
|
+
Magnetic field strength in T.
|
|
53
|
+
divergence : float, optional
|
|
54
|
+
The beam divergence also corresponding to the BM angle in rad.
|
|
55
|
+
electron_energy_in_GeV : float, optional
|
|
56
|
+
The electron beam energy in GeV.
|
|
57
|
+
|
|
58
|
+
params :
|
|
59
|
+
Other parameters accepted by BendingMagnet.
|
|
60
|
+
|
|
61
|
+
Returns
|
|
62
|
+
-------
|
|
63
|
+
instance of BendingMagnet
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
magnetic_radius = cls.calculate_magnetic_radius(magnetic_field, electron_energy_in_GeV)
|
|
67
|
+
|
|
68
|
+
return cls(magnetic_radius, magnetic_field, numpy.abs(divergence * magnetic_radius), **params)
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def initialize_from_magnetic_radius_divergence_and_electron_energy(cls,
|
|
72
|
+
magnetic_radius=10.0,
|
|
73
|
+
divergence=1e-3,
|
|
74
|
+
electron_energy_in_GeV=1.0,
|
|
75
|
+
**params):
|
|
76
|
+
"""
|
|
77
|
+
Returns an bending magnet from the magnetic radius and electron energy.
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
----------
|
|
81
|
+
magnetic_radius : float, optional
|
|
82
|
+
Magnetic radius in m.
|
|
83
|
+
divergence : float, optional
|
|
84
|
+
The beam divergence also corresponding to the BM angle in rad.
|
|
85
|
+
electron_energy_in_GeV : float, optional
|
|
86
|
+
The electron beam energy in GeV.
|
|
87
|
+
|
|
88
|
+
params :
|
|
89
|
+
Other parameters accepted by BendingMagnet.
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
instance of BendingMagnet
|
|
94
|
+
|
|
95
|
+
"""
|
|
96
|
+
magnetic_field = cls.calculate_magnetic_field(magnetic_radius, electron_energy_in_GeV)
|
|
97
|
+
|
|
98
|
+
return cls(magnetic_radius,magnetic_field,numpy.abs(divergence * magnetic_radius), **params)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def length(self):
|
|
102
|
+
"""
|
|
103
|
+
returns the BM length in m.
|
|
104
|
+
|
|
105
|
+
Returns
|
|
106
|
+
-------
|
|
107
|
+
float
|
|
108
|
+
|
|
109
|
+
"""
|
|
110
|
+
return self._length
|
|
111
|
+
|
|
112
|
+
def magnetic_field(self):
|
|
113
|
+
"""
|
|
114
|
+
Returns the bagnetic field in T.
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
float
|
|
119
|
+
|
|
120
|
+
"""
|
|
121
|
+
return self._magnetic_field
|
|
122
|
+
|
|
123
|
+
def radius(self):
|
|
124
|
+
"""
|
|
125
|
+
Returns the BM radius in m.
|
|
126
|
+
|
|
127
|
+
Returns
|
|
128
|
+
-------
|
|
129
|
+
float
|
|
130
|
+
|
|
131
|
+
"""
|
|
132
|
+
return self._radius
|
|
133
|
+
|
|
134
|
+
def horizontal_divergence(self):
|
|
135
|
+
"""
|
|
136
|
+
returns the horizontal divergence in rad.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
float
|
|
141
|
+
|
|
142
|
+
"""
|
|
143
|
+
return numpy.abs(self.length()/self.radius())
|
|
144
|
+
|
|
145
|
+
def get_magnetic_field(self, electron_energy_in_GeV):
|
|
146
|
+
"""
|
|
147
|
+
returns magnetic field in T (from the magnetic radius and electron energy).
|
|
148
|
+
|
|
149
|
+
Parameters
|
|
150
|
+
----------
|
|
151
|
+
electron_energy_in_GeV : float, optional
|
|
152
|
+
The electron beam energy in GeV.
|
|
153
|
+
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
float
|
|
157
|
+
|
|
158
|
+
"""
|
|
159
|
+
return BendingMagnet.calculate_magnetic_field(self._radius, electron_energy_in_GeV)
|
|
160
|
+
|
|
161
|
+
def get_magnetic_radius(self, electron_energy_in_GeV):
|
|
162
|
+
"""
|
|
163
|
+
Calculates magnetic radius (from the magnetic field and electron energy).
|
|
164
|
+
|
|
165
|
+
Parameters
|
|
166
|
+
----------
|
|
167
|
+
electron_energy_in_GeV : float, optional
|
|
168
|
+
The electron beam energy in GeV.
|
|
169
|
+
|
|
170
|
+
Returns
|
|
171
|
+
-------
|
|
172
|
+
float
|
|
173
|
+
|
|
174
|
+
"""
|
|
175
|
+
return BendingMagnet.calculate_magnetic_radius(self._magnetic_field, electron_energy_in_GeV)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def get_critical_energy(self, electron_energy_in_GeV, method=1):
|
|
179
|
+
"""
|
|
180
|
+
Returns the photon critical energy in eV.
|
|
181
|
+
|
|
182
|
+
Parameters
|
|
183
|
+
----------
|
|
184
|
+
electron_energy_in_GeV : float, optional
|
|
185
|
+
The electron beam energy in GeV.
|
|
186
|
+
method : int, optional
|
|
187
|
+
0= uses magnetic radius, 1=uses magnetic field
|
|
188
|
+
|
|
189
|
+
Returns
|
|
190
|
+
-------
|
|
191
|
+
float
|
|
192
|
+
|
|
193
|
+
"""
|
|
194
|
+
if method == 0:
|
|
195
|
+
return BendingMagnet.calculate_critical_energy(self._radius, electron_energy_in_GeV)
|
|
196
|
+
else:
|
|
197
|
+
return BendingMagnet.calculate_critical_energy_from_magnetic_field(self._magnetic_field, electron_energy_in_GeV)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
# for equations, see for example https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
|
|
202
|
+
@classmethod
|
|
203
|
+
def calculate_magnetic_field(cls, magnetic_radius, electron_energy_in_GeV):
|
|
204
|
+
"""
|
|
205
|
+
Calculates magnetic field from magnetic radius and electron energy.
|
|
206
|
+
|
|
207
|
+
Parameters
|
|
208
|
+
----------
|
|
209
|
+
magnetic_radius : float
|
|
210
|
+
Magnetic radius in m.
|
|
211
|
+
electron_energy_in_GeV : float
|
|
212
|
+
The electron beam energy in GeV.
|
|
213
|
+
|
|
214
|
+
Returns
|
|
215
|
+
-------
|
|
216
|
+
float
|
|
217
|
+
The magnetic field in T.
|
|
218
|
+
|
|
219
|
+
References
|
|
220
|
+
----------
|
|
221
|
+
See, for example, https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
|
|
222
|
+
|
|
223
|
+
"""
|
|
224
|
+
# return 3.334728*electron_energy_in_GeV/magnetic_radius
|
|
225
|
+
return 1e9 / codata.c * electron_energy_in_GeV / magnetic_radius
|
|
226
|
+
|
|
227
|
+
@classmethod
|
|
228
|
+
def calculate_magnetic_radius(cls, magnetic_field, electron_energy_in_GeV):
|
|
229
|
+
"""
|
|
230
|
+
Calculates magnetic radius from magnetic field and electron energy.
|
|
231
|
+
|
|
232
|
+
Parameters
|
|
233
|
+
----------
|
|
234
|
+
magnetic_field : float
|
|
235
|
+
Magnetic field in T.
|
|
236
|
+
electron_energy_in_GeV : float
|
|
237
|
+
The electron beam energy in GeV.
|
|
238
|
+
|
|
239
|
+
Returns
|
|
240
|
+
-------
|
|
241
|
+
float
|
|
242
|
+
The magnetic radius in m.
|
|
243
|
+
|
|
244
|
+
References
|
|
245
|
+
----------
|
|
246
|
+
See, for example, https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
|
|
247
|
+
|
|
248
|
+
"""
|
|
249
|
+
# return 3.334728*electron_energy_in_GeV/magnetic_field
|
|
250
|
+
return 1e9 / codata.c * electron_energy_in_GeV / magnetic_field
|
|
251
|
+
|
|
252
|
+
@classmethod
|
|
253
|
+
def calculate_critical_energy(cls, magnetic_radius, electron_energy_in_GeV):
|
|
254
|
+
"""
|
|
255
|
+
Calculates the photon critical energy from magnetic radius and electron energy.
|
|
256
|
+
|
|
257
|
+
Parameters
|
|
258
|
+
----------
|
|
259
|
+
magnetic_radius : float
|
|
260
|
+
Magnetic radius in m.
|
|
261
|
+
electron_energy_in_GeV : float
|
|
262
|
+
The electron beam energy in GeV.
|
|
263
|
+
|
|
264
|
+
Returns
|
|
265
|
+
-------
|
|
266
|
+
float
|
|
267
|
+
The photon critical energy in eV.
|
|
268
|
+
|
|
269
|
+
References
|
|
270
|
+
----------
|
|
271
|
+
See, for example, https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
|
|
272
|
+
|
|
273
|
+
"""
|
|
274
|
+
# omega = 3 g3 c / (2r)
|
|
275
|
+
gamma = 1e9 * electron_energy_in_GeV / (codata.m_e * codata.c**2 / codata.e)
|
|
276
|
+
critical_energy_J = 3 * codata.c * codata.hbar * gamma**3 / (2 * numpy.abs(magnetic_radius))
|
|
277
|
+
critical_energy_eV = critical_energy_J / codata.e
|
|
278
|
+
return critical_energy_eV
|
|
279
|
+
|
|
280
|
+
@classmethod
|
|
281
|
+
def calculate_critical_energy_from_magnetic_field(cls, magnetic_field, electron_energy_in_GeV):
|
|
282
|
+
"""
|
|
283
|
+
Calculates the photon critical energy from magnetic field and electron energy.
|
|
284
|
+
|
|
285
|
+
Parameters
|
|
286
|
+
----------
|
|
287
|
+
magnetic_field : float
|
|
288
|
+
Magnetic field in T.
|
|
289
|
+
electron_energy_in_GeV : float
|
|
290
|
+
The electron beam energy in GeV.
|
|
291
|
+
|
|
292
|
+
Returns
|
|
293
|
+
-------
|
|
294
|
+
float
|
|
295
|
+
The critical energy in eV.
|
|
296
|
+
|
|
297
|
+
References
|
|
298
|
+
----------
|
|
299
|
+
See, for example, https://people.eecs.berkeley.edu/~attwood/srms/2007/Lec09.pdf
|
|
300
|
+
|
|
301
|
+
"""
|
|
302
|
+
# omega = 3 g3 c / (2r)
|
|
303
|
+
magnetic_radius = cls.calculate_magnetic_radius(magnetic_field, electron_energy_in_GeV)
|
|
304
|
+
return cls.calculate_critical_energy(magnetic_radius, electron_energy_in_GeV)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
if __name__ == "__main__":
|
|
308
|
+
print("input for ESRF: ")
|
|
309
|
+
B = BendingMagnet.calculate_magnetic_field(25.0,6.04)
|
|
310
|
+
print(">> B = ",B)
|
|
311
|
+
print(">> R = ",BendingMagnet.calculate_magnetic_radius(B,6.04))
|
|
312
|
+
print(">> Ec = ",BendingMagnet.calculate_critical_energy(25.0,6.04))
|
|
313
|
+
print(">> Ec = ",BendingMagnet.calculate_critical_energy_from_magnetic_field(B, 6.04))
|
|
314
|
+
BB = BendingMagnet.calculate_magnetic_radius (BendingMagnet.calculate_magnetic_radius (B,6.04),6.04)
|
|
315
|
+
RR = BendingMagnet.calculate_magnetic_radius(BendingMagnet.calculate_magnetic_field(25.0,6.04), 6.04)
|
|
316
|
+
assert(BB == B)
|
|
317
|
+
assert(RR == 25.0)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
print("input for ALS: ")
|
|
321
|
+
B = BendingMagnet.calculate_magnetic_field(5.0,1.9)
|
|
322
|
+
print(">> B = ",B)
|
|
323
|
+
print(">> R = ",BendingMagnet.calculate_magnetic_radius (B,1.9))
|
|
324
|
+
print(">> Ec = ",BendingMagnet.calculate_critical_energy(5.0,1.9))
|
|
325
|
+
print(">> Ec = ",BendingMagnet.calculate_critical_energy_from_magnetic_field(B, 1.9))
|
|
326
|
+
BB = BendingMagnet.calculate_magnetic_radius (BendingMagnet.calculate_magnetic_radius (B,1.9),1.9)
|
|
327
|
+
RR = BendingMagnet.calculate_magnetic_radius(BendingMagnet.calculate_magnetic_field(5.0, 1.9), 1.9)
|
|
328
|
+
assert(BB == B)
|
|
329
|
+
assert(RR == 5.0)
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
Base class for all insertion devices: wiggler, undulator
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from numpy import pi
|
|
8
|
+
import scipy.constants as codata
|
|
9
|
+
|
|
10
|
+
from syned.storage_ring.magnetic_structure import MagneticStructure
|
|
11
|
+
|
|
12
|
+
class InsertionDevice(MagneticStructure):
|
|
13
|
+
"""
|
|
14
|
+
Base clase for the Insertion Device (ID) (common class for wigglers and undulators).
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
K_vertical : float, optional
|
|
19
|
+
The deflection K parameter corresponding to magnetic field in the vertical direction.
|
|
20
|
+
K_horizontal : float, optional
|
|
21
|
+
The deflection K parameter corresponding to magnetic field in the horizontal direction.
|
|
22
|
+
period_length : float, optional
|
|
23
|
+
The ID period in m.
|
|
24
|
+
number_of_periods : float, optional
|
|
25
|
+
The number of periods. It may be a float, considering that number_of_periods = ID_length / period_length.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
def __init__(self,
|
|
29
|
+
K_vertical = 0.0,
|
|
30
|
+
K_horizontal = 0.0,
|
|
31
|
+
period_length = 0.0,
|
|
32
|
+
number_of_periods = 1.0):
|
|
33
|
+
MagneticStructure.__init__(self)
|
|
34
|
+
|
|
35
|
+
self._K_vertical = K_vertical
|
|
36
|
+
self._K_horizontal = K_horizontal
|
|
37
|
+
self._period_length = period_length
|
|
38
|
+
self._number_of_periods = number_of_periods
|
|
39
|
+
|
|
40
|
+
# support text containg name of variable, help text and unit. Will be stored in self._support_dictionary
|
|
41
|
+
self._set_support_text([
|
|
42
|
+
("K_vertical" , "K value (vertical)" , "" ),
|
|
43
|
+
("K_horizontal" , "K value (horizontal)", "" ),
|
|
44
|
+
("period_length" , "Period length" , "m" ),
|
|
45
|
+
("number_of_periods" , "Number of periods" , "" ),
|
|
46
|
+
] )
|
|
47
|
+
|
|
48
|
+
def K_vertical(self):
|
|
49
|
+
"""
|
|
50
|
+
Returns K vertical.
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
float
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
return self._K_vertical
|
|
58
|
+
|
|
59
|
+
def K_horizontal(self):
|
|
60
|
+
"""
|
|
61
|
+
Returns K horizontal.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
float
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
return self._K_horizontal
|
|
69
|
+
|
|
70
|
+
def period_length(self):
|
|
71
|
+
"""
|
|
72
|
+
Returns the ID period in m.
|
|
73
|
+
|
|
74
|
+
Returns
|
|
75
|
+
-------
|
|
76
|
+
float
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
return self._period_length
|
|
80
|
+
|
|
81
|
+
def number_of_periods(self):
|
|
82
|
+
"""
|
|
83
|
+
Returns the number of periods.
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
float
|
|
88
|
+
|
|
89
|
+
"""
|
|
90
|
+
return self._number_of_periods
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
#
|
|
94
|
+
# some easy calculations
|
|
95
|
+
#
|
|
96
|
+
|
|
97
|
+
def K(self):
|
|
98
|
+
"""
|
|
99
|
+
Returns K vertical.
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
float
|
|
104
|
+
|
|
105
|
+
"""
|
|
106
|
+
return self.K_vertical()
|
|
107
|
+
|
|
108
|
+
def length(self):
|
|
109
|
+
"""
|
|
110
|
+
Returns the ID length in m.
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
float
|
|
115
|
+
|
|
116
|
+
"""
|
|
117
|
+
return self.number_of_periods() * self.period_length()
|
|
118
|
+
|
|
119
|
+
def magnetic_field_vertical(self):
|
|
120
|
+
"""
|
|
121
|
+
Returns the peak magnetic field in T in the vertical direction.
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
-------
|
|
125
|
+
float
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
return self.__magnetic_field_from_K(self.K_vertical())
|
|
129
|
+
|
|
130
|
+
def magnetic_field_horizontal(self):
|
|
131
|
+
"""
|
|
132
|
+
Returns the peak magnetic field in T in the horizontal direction.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
float
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
return self.__magnetic_field_from_K(self.K_horizontal())
|
|
140
|
+
|
|
141
|
+
def set_K_vertical_from_magnetic_field(self, B_vertical):
|
|
142
|
+
"""
|
|
143
|
+
Set the vertical K value given the corresponding peak magnetic field.
|
|
144
|
+
|
|
145
|
+
Parameters
|
|
146
|
+
----------
|
|
147
|
+
B_vertical : float
|
|
148
|
+
Peak magnetic field in T.
|
|
149
|
+
|
|
150
|
+
"""
|
|
151
|
+
self._K_vertical = self.__K_from_magnetic_field(B_vertical)
|
|
152
|
+
|
|
153
|
+
def set_K_horizontal_from_magnetic_field(self, B_horizontal):
|
|
154
|
+
"""
|
|
155
|
+
Set the horizontal K value given the corresponding peak magnetic field.
|
|
156
|
+
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
B_vertical : float
|
|
160
|
+
Peak magnetic field in T.
|
|
161
|
+
|
|
162
|
+
"""
|
|
163
|
+
self._K_horizontal = self.__K_from_magnetic_field(B_horizontal)
|
|
164
|
+
|
|
165
|
+
def __magnetic_field_from_K(self, K):
|
|
166
|
+
return K * 2 * pi * codata.m_e * codata.c / (codata.e * self.period_length())
|
|
167
|
+
|
|
168
|
+
def __K_from_magnetic_field(self, B):
|
|
169
|
+
return B /(2 * pi * codata.m_e * codata.c / (codata.e * self.period_length()))
|