pySRU 0.5.5__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.
@@ -0,0 +1,59 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2016 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["S Thery, M Glass, M Sanchez del Rio - ESRF ISDD Advanced Analysis and Modelling"]
27
+ __license__ = "MIT"
28
+ __date__ = "31/08/2016"
29
+
30
+
31
+ import numpy as np
32
+ class ElectricalField(object):
33
+ def __init__(self, electrical_field, X, Y, distance):
34
+ # TODO: maybe check constants if we just calcualte vector potential A
35
+ self._electrical_field = electrical_field.copy()
36
+ self._X = X.copy()
37
+ self._Y = Y.copy()
38
+ self._distance = distance
39
+
40
+ def X(self):
41
+ return self._X.copy()
42
+
43
+ def Y(self):
44
+ return self._Y.copy()
45
+
46
+ def distance(self):
47
+ return self._distance
48
+
49
+ def electrical_field(self):
50
+ return self._electrical_field.copy()
51
+
52
+
53
+
54
+ def intensity(self):
55
+ return np.sum(np.abs(self.electrical_field()) ** 2, axis=-1)
56
+
57
+
58
+
59
+
pySRU/ElectronBeam.py ADDED
@@ -0,0 +1,67 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2016 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["S Thery, M Glass, M Sanchez del Rio - ESRF ISDD Advanced Analysis and Modelling"]
27
+ __license__ = "MIT"
28
+ __date__ = "31/08/2016"
29
+
30
+ import numpy as np
31
+ import scipy.constants as codata
32
+
33
+
34
+ # container class
35
+ # parameter of the beam
36
+ class ElectronBeam(object):
37
+ def __init__(self, Electron_energy, I_current):
38
+ self.Electron_energy=Electron_energy
39
+ self.I_current=I_current
40
+
41
+ def copy(self):
42
+ return ElectronBeam(Electron_energy=self.Electron_energy, I_current=self.I_current)
43
+
44
+ def Lorentz_factor(self):
45
+ return 1e9*self.Electron_energy / (codata.m_e * codata.c**2 / codata.e)
46
+
47
+ def electron_speed(self):
48
+ gamma = self.Lorentz_factor()
49
+ Beta = np.sqrt(1.0 - 1.0 / gamma ** 2)
50
+ return Beta
51
+
52
+ def print_parameters(self):
53
+ print(' Electron Beam')
54
+ print(' Electron energy (GeV): %.3f' %self.Electron_energy)
55
+ print(' Intensity (A): %.3f' % self.I_current)
56
+ print(' Electron speed : %.10f' %self.electron_speed())
57
+ print(' Lorentz factor : %.7f' % self.Lorentz_factor())
58
+
59
+ if __name__ == "__main__" :
60
+ K = 1.87
61
+ E = 1.3
62
+ I = 1.0
63
+ beam=ElectronBeam(Electron_energy=E, I_current=I)
64
+
65
+ beam.print_parameters()
66
+
67
+ print('Lorentz factor: %f'%beam.Lorentz_factor())
pySRU/MagneticField.py ADDED
@@ -0,0 +1,146 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2016 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["S Thery, M Glass, M Sanchez del Rio - ESRF ISDD Advanced Analysis and Modelling"]
27
+ __license__ = "MIT"
28
+ __date__ = "31/08/2016"
29
+
30
+ import numpy as np
31
+
32
+
33
+
34
+
35
+
36
+ class MagneticField(object):
37
+ def __init__(self,Bx,By,Bz):
38
+ self.Bx = Bx
39
+ self.By = By
40
+ self.Bz = Bz
41
+
42
+ def copy(self):
43
+ if type(self.Bx)==np.ndarray:
44
+ Bx = self.Bx.copy()
45
+ else :
46
+ Bx=self.Bx
47
+ if type(self.By)==np.ndarray:
48
+ By = self.By.copy()
49
+ else :
50
+ By=self.By
51
+ if type(self.Bz)==np.ndarray:
52
+ Bz = self.Bz.copy()
53
+ else :
54
+ Bz=self.Bz
55
+ return MagneticField(Bx=Bx, By=By, Bz=Bz)
56
+
57
+ #faire une fct aui fait l'interpolation et elargissement
58
+ #
59
+
60
+ #TODO a modifier
61
+ # enelarge 2 vector for the interpolation of the magnetic field use in trajectory_undulator_from_magnetic_field2
62
+ def enlargement_vector_for_interpolation(self,Z,Y ,nb_enlarg=0):
63
+ dz = Z[1] -Z[0]
64
+ enlarg_1 = np.linspace(Z[0] - nb_enlarg * dz, Z[0] - dz, nb_enlarg)
65
+ enlarg_2 = np.linspace(Z[- 1] + dz, Z[- 1] + nb_enlarg * dz, nb_enlarg)
66
+ Z = np.concatenate((enlarg_1, Z))
67
+ Z = np.concatenate((Z, enlarg_2))
68
+ if (type(Y )==np.ndarray) :
69
+ dy = Y [1] - Y [0]
70
+ enlarg_1 = np.linspace(Y [0] - nb_enlarg * dz, Y [0] - dy, nb_enlarg)
71
+ enlarg_2 = np.linspace(Y [- 1] + dy, Y [- 1] + nb_enlarg * dy, nb_enlarg)
72
+ Y = np.concatenate((enlarg_1, Y ))
73
+ Y = np.concatenate((Y , enlarg_2))
74
+ if (type(self.By)==np.ndarray) :
75
+ enlarg_3 = np.zeros(nb_enlarg)
76
+ self.By = np.concatenate((enlarg_3, self.By))
77
+ self.By = np.concatenate((self.By, enlarg_3))
78
+ return Z,Y
79
+
80
+
81
+
82
+
83
+ def plot_z(self,X,Y,Z,title="Magnetic field",field_component=None):
84
+ import matplotlib.pyplot as plt
85
+
86
+ if ( (field_component == None) or (field_component == 0) or (field_component == 'x') ):
87
+ plt.plot(Z, self.Bx(z=Z,y=Y,x=X))
88
+
89
+ plt.ylabel('Bx [T]')
90
+ plt.xlabel('Z [m]')
91
+ plt.title(title+" Bx = f(z) ")
92
+ plt.show()
93
+
94
+ if ( (field_component == None) or (field_component == 1) or (field_component == 'y') ):
95
+ plt.plot(Z, self.By(z=Z,y=Y,x=X))
96
+ plt.ylabel('By [T]')
97
+ plt.xlabel('Z [m]')
98
+ plt.title(title+" By = f(z) ")
99
+ plt.show()
100
+
101
+ if ( (field_component == None) or (field_component == 2) or (field_component == 'z') ):
102
+ plt.plot(Z, self.Bz(z=Z,y=Y,x=X))
103
+ plt.ylabel('Bz [T]')
104
+ plt.xlabel('Z [m]')
105
+ plt.title(title+" Bz = f(z) ")
106
+ plt.show()
107
+
108
+ # # TODO A CHANGER COMME PLOT_z
109
+ #TODO quiver plot ?
110
+ # def plot_y(self):
111
+ # plt.plot(self.y, self.Bx(self.z, self.y))
112
+ # plt.title(" Bx = f(y) ")
113
+ # plt.xlabel('Bx')
114
+ # plt.ylabel('y')
115
+ # plt.show()
116
+ #
117
+ # plt.plot(self.y, self.By(self.z, self.y))
118
+ # plt.title(" By = f(y) ")
119
+ # plt.xlabel('By')
120
+ # plt.ylabel('y')
121
+ # plt.show()
122
+ #
123
+ # plt.plot(self.y, self.Bz(self.z, self.y))
124
+ # plt.title(" Bz = f(y) ")
125
+ # plt.xlabel('Bz')
126
+ # plt.ylabel('y')
127
+ # plt.show()
128
+
129
+
130
+ if __name__ == "__main__" :
131
+ Bx = lambda x,y,z : np.cos(y*z)
132
+ By = lambda x,y,z : np.sin(x)*np.cos(z)
133
+ Bz = lambda x,y,z : np.sin(y*z)
134
+
135
+ B=MagneticField(Bx=Bx,By=By,Bz=Bz)
136
+
137
+ Z=np.linspace(0.0,2.*np.pi,10000)
138
+ Y=np.linspace(0.0,2.*np.pi,10000)
139
+ X=np.linspace(0.0,2.*np.pi,10000)
140
+
141
+ print('plot X=pi/2 , Y=1 , Z in [0,2 pi]')
142
+ B.plot_z(X=np.pi*0.5,Y=1.0,Z=Z)
143
+ print('plot X= pi/2 , Y and Z in [0,2 pi]')
144
+ B.plot_z(X=np.pi*0.5,Y=Y,Z=Z)
145
+ print('plot X , Y and Z in [0,2 pi]')
146
+ B.plot_z(X=X,Y=Y,Z=Z)
@@ -0,0 +1,133 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2016 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["S Thery, M Glass, M Sanchez del Rio - ESRF ISDD Advanced Analysis and Modelling"]
27
+ __license__ = "MIT"
28
+ __date__ = "31/08/2016"
29
+
30
+ import numpy as np
31
+ import scipy.constants as codata
32
+ from abc import abstractmethod
33
+ from pySRU.MagneticField import MagneticField
34
+
35
+ PLANE_UNDULATOR=0
36
+ BENDING_MAGNET=1
37
+
38
+ class MagneticStructure(object):
39
+ def __init__(self, magnet_type ):
40
+ self.magnet_type=magnet_type
41
+
42
+ @abstractmethod
43
+ def copy(self):
44
+ return
45
+
46
+
47
+ @abstractmethod
48
+ def print_parameters(self):
49
+ pass
50
+
51
+
52
+ # magnetic field
53
+ @abstractmethod
54
+ def fct_magnetic_field(self, z, y, x, harmonic_number, coordonnee='y'):
55
+ return 0.0
56
+
57
+
58
+ # TODO la faire plus jolie ?
59
+ def calculate_magnetic_field(self, Z, Y, X, harmonic_number=1, coordonnee='y'):
60
+ if (type(Z) == np.ndarray):
61
+ B = np.zeros_like(Z)
62
+ else:
63
+ if (type(Y) == np.ndarray):
64
+ B = np.zeros_like(Y)
65
+ else:
66
+ if (type(X) == np.ndarray):
67
+ B = np.zeros_like(X)
68
+ else:
69
+ B = self.fct_magnetic_field(z=Z, y=Y, x=X,
70
+ harmonic_number=harmonic_number, coordonnee=coordonnee)
71
+
72
+ if (type(Z) == np.ndarray):
73
+ if (type(Y) == np.ndarray):
74
+ if (len(Y) != len(Z)):
75
+ raise Exception(' Y and Z must have the same lenght')
76
+ if (type(X) == np.ndarray):
77
+ if (len(X) != len(Z)):
78
+ raise Exception(' X and Z must have the same lenght')
79
+ for i, Zi in enumerate(Z):
80
+ B[i] = self.fct_magnetic_field(z=Zi, y=Y[i], x=X[i],
81
+ harmonic_number=harmonic_number, coordonnee=coordonnee)
82
+ else:
83
+ for i, Zi in enumerate(Z):
84
+ B[i] = self.fct_magnetic_field(z=Zi, y=Y[i], x=X,
85
+ harmonic_number=harmonic_number, coordonnee=coordonnee)
86
+ else:
87
+ if (type(X) == np.ndarray):
88
+ if (len(X) != len(Z)):
89
+ raise Exception(' X and Z must have the same lenght')
90
+ for i, Zi in enumerate(Z):
91
+ B[i] = self.fct_magnetic_field(z=Zi, y=Y, x=X[i],
92
+ harmonic_number=harmonic_number, coordonnee=coordonnee)
93
+ else:
94
+ for i, Zi in enumerate(Z):
95
+ B[i] = self.fct_magnetic_field(z=Zi, y=Y, x=X,
96
+ harmonic_number=harmonic_number, coordonnee=coordonnee)
97
+ else:
98
+ if (type(Y) == np.ndarray):
99
+ if (type(X) == np.ndarray):
100
+ if (len(X) != len(Y)):
101
+ raise Exception(' X and Z must have the same lenght')
102
+ for i, Yi in enumerate(Y):
103
+ B[i] = self.fct_magnetic_field(z=Z, y=Yi, x=X[i], harmonic_number=harmonic_number,
104
+ coordonnee=coordonnee)
105
+ else:
106
+ if (type(X) == np.ndarray):
107
+ for i, Xi in enumerate(X):
108
+ B[i] = self.fct_magnetic_field(z=Z, y=Y, x=Xi, harmonic_number=harmonic_number,
109
+ coordonnee=coordonnee)
110
+ else:
111
+ B = self.fct_magnetic_field(z=Z, y=Y, x=X, harmonic_number=harmonic_number, coordonnee=coordonnee)
112
+ return B
113
+
114
+
115
+ # a Magnetic structur create a magnetic field
116
+ # the object MagneticField is create like :
117
+ # Bx , By , Bz are function R**(3) -> R
118
+ # this function depend of the magnet type (BendingMagnet or undulator ..)
119
+ # X, Y can be array or number, they describe the area where we want to work
120
+ # Z must be an array , it will be use later
121
+ # they have not necessary the same len
122
+ # peux etre a changer et ne metrre que les fonctions ... oui
123
+ def create_magnetic_field(self, harmonic_number=1):
124
+ By = (lambda z, y, x: self.calculate_magnetic_field(Z=z, Y=y, X=x, harmonic_number=harmonic_number, coordonnee='y'))
125
+ Bz = (lambda z, y, x: self.calculate_magnetic_field(Z=z, Y=y, X=x, harmonic_number=harmonic_number, coordonnee='z'))
126
+ Bx = (lambda z, y, x: self.calculate_magnetic_field(Z=z, Y=y, X=x, harmonic_number=harmonic_number, coordonnee='x'))
127
+ B = MagneticField(Bx, By, Bz)
128
+ return B
129
+
130
+
131
+
132
+ if __name__ == "__main__" :
133
+ pass
@@ -0,0 +1,114 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2016 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["S Thery, M Glass, M Sanchez del Rio - ESRF ISDD Advanced Analysis and Modelling"]
27
+ __license__ = "MIT"
28
+ __date__ = "31/08/2016"
29
+
30
+ import numpy as np
31
+ import scipy.constants as codata
32
+ import scipy.special as special
33
+ from pySRU.MagneticStructure import MagneticStructure, PLANE_UNDULATOR,BENDING_MAGNET
34
+
35
+
36
+ #TODO changer et mettre la divergeance en parametre ?
37
+ class MagneticStructureBendingMagnet(MagneticStructure):
38
+ def __init__(self, Bo, horizontale_divergeance,electron_energy=1e9):
39
+ super(self.__class__, self).__init__(magnet_type=BENDING_MAGNET)
40
+ self.horizontal_div=horizontale_divergeance
41
+ self.radius_curv=electron_energy*1e9/(codata.c*Bo)
42
+ self.length=np.sin(horizontale_divergeance)*self.radius_curv
43
+ self.Bo = Bo
44
+
45
+
46
+ def copy(self):
47
+ return MagneticStructureBendingMagnet(length=self.length, Bo=self.Bo)
48
+
49
+ def fct_magnetic_field(self, z, y, x, harmonic_number, coordonnee='y'):
50
+ Zo = self.length * 0.6
51
+ if coordonnee == 'y' and z >= -Zo and z <= Zo:
52
+ # codata.m_e * codata.c / codata.e= 0.00170450894933
53
+ Bo = self.Bo
54
+
55
+ else: # coordonnee == 'z' :
56
+ Bo = 0.0
57
+ return Bo
58
+
59
+
60
+ def fct_magnetic_field2(self, z, y, x, harmonic_number, coordonnee='y'):
61
+ Zo = self.length * 0.5
62
+ if coordonnee == 'y':
63
+ # codata.m_e * codata.c / codata.e= 0.00170450894933
64
+ Bo = self.Bo
65
+ else: # coordonnee == 'z' :
66
+ Bo = 0.0
67
+
68
+ # we enelarge the real effect of the magnetic field by 4 lambda_u
69
+ # on each extremity of the undulator
70
+ L_magn_field = self.length * 1.5
71
+
72
+ # we know considere that if -(L/2 + lambda_u/4) < Z < (L/2 + lambda_u/4)
73
+ # the magnetic field if a classic cosinus (or sinus)
74
+ L_cosinus_part = -Zo
75
+
76
+ if ((z < -L_magn_field) or (z > L_magn_field)):
77
+ dB = 0.0
78
+
79
+ else:
80
+ if (z < -L_cosinus_part or z > L_cosinus_part):
81
+
82
+ # in this case, we work with a gaussian,
83
+ # so we shift the coordinate frame for use a central gaussian
84
+ if z > 0.0:
85
+ z_shift = z - L_cosinus_part
86
+ else:
87
+ z_shift = z + L_cosinus_part
88
+
89
+ sigma = (L_magn_field - L_cosinus_part) / 5.0
90
+ # dB= Bo*(1.0-z_shift*self.get_L()**2/2.0)*np.exp(-0.5*(z_shift/sigma)**2)
91
+ dB = Bo * np.exp(-0.5 * (z_shift / sigma) ** 2)
92
+ else:
93
+ # in this case we work in the cosinus part
94
+ dB = Bo
95
+ return dB
96
+
97
+
98
+
99
+ def print_parameters(self):
100
+ print(" Magnetic Structure (Bending Magnet):")
101
+ print(' length : %.5f (m)'%self.length)
102
+ print(' magnetic_field_strength : %.5f'%self.Bo)
103
+
104
+
105
+ if __name__ == "__main__" :
106
+
107
+ BM = MagneticStructureBendingMagnet(Bo=0.85, length=1e-3 * 20.0)
108
+
109
+ print('bending magnet test :')
110
+ BM.print_parameters()
111
+ B = BM.create_magnetic_field()
112
+ Z=np.linspace(-BM.length/2.0,BM.length/2.0,10000)
113
+ B.plot_z(Z=Z,Y=0.0,X=0.0)
114
+
@@ -0,0 +1,145 @@
1
+ # coding: utf-8
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2016 European Synchrotron Radiation Facility
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+
26
+ __authors__ = ["S Thery, M Glass, M Sanchez del Rio - ESRF ISDD Advanced Analysis and Modelling"]
27
+ __license__ = "MIT"
28
+ __date__ = "31/08/2016"
29
+
30
+ import numpy as np
31
+ import scipy.constants as codata
32
+ from scipy.special import jn,yn,jv,yv
33
+ from pySRU.MagneticField import MagneticField
34
+ from pySRU.MagneticStructure import MagneticStructure , PLANE_UNDULATOR,BENDING_MAGNET
35
+
36
+
37
+
38
+ class MagneticStructureUndulatorPlane(MagneticStructure):
39
+ def __init__(self, K, period_length, length):
40
+ super(self.__class__, self).__init__(magnet_type=PLANE_UNDULATOR)
41
+ self.K = K
42
+ self.period_length = period_length
43
+ self.length=length
44
+
45
+ def copy(self):
46
+ return MagneticStructureUndulatorPlane(K=self.K, period_length=self.period_length, length=self.length)
47
+
48
+ def fct_magnetic_field(self, z, y, x, harmonic_number, coordonnee='y'):
49
+ lambda_h = self.period_length / harmonic_number
50
+ ku = 2.0 * np.pi / self.period_length
51
+
52
+ if coordonnee == 'x':
53
+ dB = 0.0
54
+ else:
55
+ # codata.m_e * codata.c / codata.e= 0.00170450894933
56
+ K_to_B = ku * codata.m_e * codata.c / codata.e
57
+ if coordonnee == 'y':
58
+
59
+ Bo = (self.K * K_to_B) * np.cosh(ku * y)
60
+ # print(Bo)
61
+ f_base = np.cos
62
+ else: # coordonnee == 'z' :
63
+ Bo = -(self.K * K_to_B) * np.sinh(ku * y)
64
+ f_base = np.sin
65
+
66
+ # we enelarge the real effect of the magnetic field by 4 lambda_u
67
+ # on each extremity of the undulator
68
+ L_magn_field = self.length / 2.0 + 4.0 * self.period_length
69
+
70
+ # we know considere that if -(L/2 + lambda_u/4) < Z < (L/2 + lambda_u/4)
71
+ # the magnetic field if a classic cosinus (or sinus)
72
+ if coordonnee == 'y':
73
+ a1 = self.length / self.period_length \
74
+ - np.floor(self.period_number())
75
+ a2 = (0.25 - a1 / 2.0)
76
+ L_cosinus_part = self.length / 2.0 \
77
+ + self.period_length * a2
78
+
79
+ else:
80
+ L_cosinus_part = self.length / 2.0
81
+
82
+ if ((z < -L_magn_field) or (z > L_magn_field)):
83
+ dB = 0.0
84
+
85
+ else:
86
+ if (z < -L_cosinus_part or z > L_cosinus_part):
87
+
88
+ # in this case, we work with a gaussian,
89
+ # so we shift the coordinate frame for use a central gaussian
90
+ if z < -L_cosinus_part:
91
+ sign = 1
92
+ else: # z> L_cosinus_part
93
+ sign = -1
94
+
95
+ shift_z = z + sign * L_cosinus_part
96
+
97
+ p = 2.0 * np.pi ** 2 / (3.0 * lambda_h ** 2)
98
+ dB = ((2.0 * np.pi * Bo / lambda_h) * shift_z) * (
99
+ 1.0 - 4.0 * np.pi ** 2 * shift_z ** 2 / (9.0 * lambda_h ** 2)
100
+ ) * np.exp(-p * shift_z ** 2)
101
+
102
+ # test du signe
103
+ z_test = sign * (-L_cosinus_part + lambda_h / 4.0)
104
+ test_trig = f_base(ku * z_test)
105
+ if (sign * test_trig < 0):
106
+ dB = -dB
107
+
108
+ else:
109
+ # in this case we work in the cosinus part
110
+ dB = Bo * f_base(ku * z)
111
+
112
+ return dB
113
+
114
+
115
+ def print_parameters(self):
116
+ print(' Magnetic Structure (Plane Undulator)')
117
+ print(' K : %.2f'%(self.K))
118
+ print(' period lenght : %.3f' % (self.period_length))
119
+ print(' lenght : %.2f'% (self.length))
120
+ print(' number of periods : %d (L/lambdau=%.2f)' % (int(self.period_number()),self.period_number()))
121
+ print(' magntic field intensity: %.2f'% (self.magnetic_field_strength()))
122
+
123
+ def period_number(self):
124
+ return self.length / self.period_length
125
+
126
+ def magnetic_field_strength(self):
127
+ Bo = (2.0 * np.pi * codata.m_e * codata.c * self.K) / (
128
+ self.period_length * codata.e)
129
+ return Bo
130
+
131
+ if __name__ == "__main__" :
132
+ und_test = MagneticStructureUndulatorPlane(K=1.87, period_length=0.035, length=0.035 * 14)
133
+ ESRF18 = MagneticStructureUndulatorPlane(K=1.68, period_length=0.018, length=2.0)
134
+
135
+ print('undulator test :')
136
+ und_test.print_parameters()
137
+ B=und_test.create_magnetic_field()
138
+ Z=np.linspace(-und_test.length/2.0,und_test.length/2.0,10000)
139
+ B.plot_z(Z=Z,Y=0.0,X=0.0)
140
+
141
+ print('undulator ESRF18 :')
142
+ ESRF18.print_parameters()
143
+ B=ESRF18.create_magnetic_field()
144
+ Z=np.linspace(-ESRF18.length/2.0,ESRF18.length/2.0,10000)
145
+ B.plot_z(Z=Z,Y=0.0,X=0.0)