1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """ Radiation.py - Classes defining the radiation impedance models
24
25 """
26
27 __all__ = ['UnflangedOpenEnd','FlangedOpenEnd','IdealOpenEnd','ClosedEnd',
28 'SaxophoneBell']
29
30 import os
31 import math
32
33 import numpy
34 from numpy import log, sqrt
35
36 import scipy.integrate
37 from scipy.integrate import quad
38
39 import scipy.special
40 from scipy.special import jn_zeros, j1
41
42 import scipy.interpolate
43 from scipy.interpolate import UnivariateSpline
44
45 import wiat
46 from wiat.util import air_properties, transform_R2Z
55 """ Unflanged open end radiation impedance models
56
57 References:
58
59 1. J. Dalmont and C.J. Nederveen,
60 "Radiation impedance of tubes with different flanges:
61 numerical and experimental investigations ,"
62 Journal of Sound and Vibration, vol. 244, pp. 505-534, 2001.
63 2. R. Caussé, J. Kergomard, and X. Lurton,
64 "Input impedance of brass musical instruments -
65 Comparaison between experimental and numerical models,"
66 J. Acoust. Soc. Am., vol. 75, pp. 241-254, 1984.
67 3. H. Levine and J. Schwinger,
68 On the radiation of sound from an unflanged circular pipe.
69 Phys. Rev., 73(4), pp. 383-406, 1948.
70
71 TODO: implement the exact solution from Levine and Schwinger
72
73 """
74
75 - def __init__(self,d,model='Dalmont_Nederveen',m=1.):
76 """ Radiation from an unflanged open pipe (Levine and schwinger)
77
78 @param d: diameter of the open end
79 @param m: multiplication factor (to take care of sperical wave,
80 approximation from Causse)
81 """
82 self.a = d/2.
83 self.m = m
84 self.model = model
85 self.Z = {'Dalmont_Nederveen': self.Z_Dalmont_Nederveen,
86 'Causse': self.Z_Causse,
87 'Levine_Schwinger': self.Z_Levine_Schwinger}
88
90 return self.Z[self.model](f,T)
91
93 return numpy.array([[self.Z[self.model](f,T)],
94 [numpy.ones(numpy.size(f))]],dtype=complex)
95
97 """ Unflanged pipe radiation impedance approximation (ka < 3.5) from
98 Dalmont and Nederveen
99
100 R = -|R0|exp(-2j*ka*delta), where delta is the frequency dependant
101 length correction
102
103 See reference [1] page 509
104 """
105 air = air_properties(T)
106 ka = 2*numpy.pi*f*self.a/air['c']
107 R0 = (1 + 0.2*ka - 0.084*ka**2)/(1 + 0.2*ka + (0.5 - 0.084)*ka**2)
108 delta = 0.6113 * ((1+0.044*ka**2)/(1+0.19*ka**2) -
109 0.02*(numpy.sin(2*ka))**2 )
110 R = - R0 * numpy.exp( -2 * 1j * ka * delta)
111 Zl = transform_R2Z(R)
112 return self.m*Zl
113
115 """ Unflanged pipe radiation impedance approximation (ka < 1.5)
116 from Causse & al.
117 See [2]
118 """
119 air = air_properties(T)
120 ka = 2*numpy.pi*f*self.a/air['c']
121 Zl = 0.25*(ka)**2 + 0.0127*(ka)**4 + 0.082*(ka)**4 * numpy.log(ka) -\
122 0.023*(ka)**6 + 1j * (0.6113*(ka) - 0.036*(ka)**3 + \
123 0.034*(ka)**3 * numpy.log(ka) - 0.0187*(ka)**5)
124 return Zl
125
127 air = air_properties(T)
128 ka = 2*numpy.pi*f*self.a/air['c']
129
130
131
132
133 s = numpy.empty((len(ka)))
134 for i,z in enumerate(ka):
135 s[i] = scipy.integrate.quad(
136 lambda x,z: log(1/(2*scipy.special.i1(x)*\
137 scipy.special.k1(x)))/(x*scipy.sqrt(x**2 + z**2)),
138 0,20,(z,))
139
149 - def __init__(self,d,model='Dalmont_Nederveen'):
150
151 self.a = d/2
152 self.model = model
153 self.Z = {'Dalmont_Nederveen': self.Z_Dalmont_Nederveen}
154
156 return self.Z[self.model](f,T)
157
159 return numpy.array([[self.Z[self.model](f,T)],[numpy.ones(numpy.size(f))]],dtype=complex)
160
162 """ Flanged pipe radiation impedance approximation (ka < 3.5)
163 from Dalmont and Nederveen
164
165 R = -|R0|exp(-2j*ka*delta), where delta is the frequency dependant
166 length correction
167
168 Z = (1+R)/(1-R)
169 See [1] page 509
170 """
171 air = air_properties(T)
172 k = 2*numpy.pi*f/air['c']
173 ka = k * self.a
174 Rinf = (1 + 0.323*ka - 0.077*ka**2)/(1 + 0.323*ka + (1 - 0.077)*ka**2)
175
176
177 delta = (0.82159-0.49*ka**2)/(1 -0.46*ka**3)
178
179 R = - Rinf * numpy.exp( -2 * 1j * ka * delta)
180 Zl = transform_R2Z(R)
181 return Zl
182
183 @staticmethod
185 return 2*s*j1(s)**2 / (sqrt(x**2-s**2) * (s**2-jn_zeros(1,i)**2))
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 -class FlangedPiston():
223
226
229 return numpy.zeros(numpy.size(f))
230
232 return numpy.array([[numpy.zeros(numpy.size(f))],
233 [numpy.ones(numpy.size(f))]],dtype=complex)
234
237 return numpy.inf*numpy.ones(numpy.size(f))
238
240 return numpy.array([[numpy.ones(numpy.size(f))],
241 [numpy.zeros(numpy.size(f))]],dtype=complex)
242
245 """ Radiation model of a saxophone bell.
246
247 It uses the multimodal calculation method to calculate the planar
248 wave input impedance of the bell.
249 """
251 """
252 @param d: diameter of the bell at the junction with the body (small end)
253 the diameter of the large end is implicit.
254 @param theta: opening angle of the bell at the junction with the body.
255 This is usually the same at the body angle in order to have a continuity
256 in the tangent.
257 """
258 self.a = d/2.
259
260
261
262
263 self.kas = numpy.arange(0.,5.,0.1)
264
265
266 self.d0 = 0.1
267 self.de = 0.15
268
269
270 self.Zr = wiat.MM.Radiation.RadiationFlanged(self.de)
271
272 self.bell = wiat.MM.Waveguides.QuarterCircleHorn(
273 self.d0,self.de,math.radians(theta),math.radians(80.))
274
275 self.number_of_modes = 5
276
277 self.backup_filename = os.path.join(os.path.dirname(__file__),
278 'SaxophoneBell.mat')
279
281 return "SaxophoneBell :: %s, length = %.4f"%\
282 (str(self.bell), self.bell.L)
283
284
286 air = wiat.util.air_properties(T)
287
288
289
290 kas = 2*numpy.pi*f*self.a/air['c']
291
292
293
294
295 Z = wiat.util.load_or_calculate(self.backup_filename,
296 wiat.MM.Solver.SolveImpedance,
297 geometry=self.bell, Zr=self.Zr,
298
299 freqs=air['c']*self.kas/(self.d0*numpy.pi),
300 air=air,
301 N=self.number_of_modes)
302
303 spl_real = UnivariateSpline(self.kas, numpy.real(Z),s=0.0000001)
304 spl_imag = UnivariateSpline(self.kas, numpy.imag(Z),s=0.0000001)
305
306 return spl_real(kas) - 1j*spl_imag(kas)
307
308
310 return numpy.array([[self(f,T)],[numpy.ones(numpy.size(f))]],
311 dtype=complex)
312