Skip to content

Commit 683dba8

Browse files
authored
Merge pull request #23 from sbadrian/feature/improved_layered_sphere_support_2
Extend permeability and permittivity function to LayeredSphere
2 parents 3669178 + aa7fe5f commit 683dba8

File tree

3 files changed

+245
-2
lines changed

3 files changed

+245
-2
lines changed

src/SphericalScattering.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export DielectricSphereThinImpedanceLayer
4545
export field, scatteredfield
4646
export rcs
4747
export sphericalGridPoints, phiCutPoints, thetaCutPoints
48+
export numlayers, layer
49+
export permittivity, permeability, medium
4850

4951

5052
# -------- extensions

src/sphere.jl

Lines changed: 182 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,18 @@ end
108108
109109
Constructor for the layered dielectric sphere.
110110
"""
111-
LayeredSphere(; radii=error("Missing argument `radii`"), filling=error("`missing argument `filling`")) = LayeredSphere(radii, filling)
111+
function LayeredSphere(; radii=error("Missing argument `radii`"), filling=error("`missing argument `filling`"))
112112

113+
if sort(radii) != radii
114+
error("Radii are not ordered ascendingly.")
115+
end
116+
117+
if length(radii) != length(filling)
118+
error("Number of fillings does not match number of radii.")
119+
end
120+
121+
LayeredSphere(radii, filling)
122+
end
113123

114124

115125

@@ -126,9 +136,32 @@ end
126136
127137
Constructor for the layered dielectric sphere.
128138
"""
129-
LayeredSpherePEC(; radii=error("Missing argument `radii`"), filling=error("Missing argument `filling`")) =
139+
function LayeredSpherePEC(; radii=error("Missing argument `radii`"), filling=error("Missing argument `filling`"))
140+
141+
if sort(radii) != radii
142+
error("Radii are not ordered ascendingly.")
143+
end
144+
145+
if length(radii) != length(filling) + 1
146+
error("Number of fillings does not match number of radii.")
147+
end
148+
130149
LayeredSpherePEC(radii, filling)
150+
end
151+
131152

153+
"""
154+
numlayers(sp::Sphere)
155+
156+
Returns the number of layers.
157+
"""
158+
function numlayers(sp::Sphere)
159+
return 2
160+
end
161+
162+
function numlayers(sp::Union{LayeredSphere,LayeredSpherePEC})
163+
return length(sp.radii) + 1
164+
end
132165

133166

134167

@@ -149,6 +182,38 @@ function layer(sp::Sphere, r)
149182
end
150183
end
151184

185+
186+
187+
"""
188+
layer(sp::LayeredSphere, r)
189+
190+
Returns the index of the layer, `r` is located, where `1` denotes the inner most layer.
191+
"""
192+
function layer(sp::Union{LayeredSphere,LayeredSpherePEC}, r)
193+
# Using Jin's numbering from the multi-layered cartesian
194+
# in anticipation. For PEC and dielectric sphere;
195+
# 1 = interior, 2 = exterior
196+
197+
r < 0.0 && error("The radius must be a positive number.")
198+
199+
N = numlayers(sp)
200+
201+
for i in 1:(N - 1)
202+
if r < sp.radii[i]
203+
return i # Convention: Boundary belongs to outer layer
204+
end
205+
end
206+
207+
return N
208+
end
209+
210+
211+
"""
212+
wavenumber(sp::Sphere, ex::Excitation, r)
213+
214+
Returns the wavenumber at radius `r` in the sphere `sp`.
215+
If this part is PEC, k=0 is rweturned.
216+
"""
152217
function wavenumber(sp::PECSphere, ex::Excitation, r)
153218
ε = ex.embedding.ε
154219
μ = ex.embedding.μ
@@ -178,6 +243,12 @@ function wavenumber(sp::DielectricSphere, ex::Excitation, r)
178243
return k
179244
end
180245

246+
"""
247+
impedance(sp::Sphere, ex::Excitation, r)
248+
249+
Returns the wavenumber at radius `r` in the sphere `sp`.
250+
If this part is PEC, a zero medium is returned.
251+
"""
181252
function impedance(sp::DielectricSphere, ex::Excitation, r)
182253
if layer(sp, r) == 2
183254
ε = ex.embedding.ε
@@ -190,6 +261,12 @@ function impedance(sp::DielectricSphere, ex::Excitation, r)
190261
return sqrt/ ε)
191262
end
192263

264+
"""
265+
impedance(sp::Sphere, r)
266+
267+
Returns the impedance of the sphere `sp` at radius `r`.
268+
If this part is PEC, a zero medium is returned.
269+
"""
193270
function impedance(sp::PECSphere, ex::Excitation, r)
194271
if layer(sp, r) == 2
195272
ε = ex.embedding.ε
@@ -200,3 +277,106 @@ function impedance(sp::PECSphere, ex::Excitation, r)
200277

201278
return sqrt/ ε)
202279
end
280+
281+
function medium(sp::LayeredSphere, ex::Excitation, r)
282+
N = numlayers(sp) # Number of interior layers
283+
284+
if layer(sp, r) == N # Outer layer has largest index
285+
return ex.embedding
286+
else
287+
return sp.filling[layer(sp, r)]
288+
end
289+
end
290+
291+
292+
293+
function medium(sp::LayeredSpherePEC, ex::Excitation, r)
294+
N = numlayers(sp) # Number of interior layers
295+
296+
if layer(sp, r) == N # Outer layer has largest index
297+
return ex.embedding
298+
elseif layer(sp, r) == 1
299+
Z = promote_type(typeof(sp.filling[end].ε), typeof(sp.filling[end].μ), typeof(ex.embedding.ε), typeof(ex.embedding.μ))(0.0)
300+
return Medium(Z, Z)
301+
else
302+
return sp.filling[layer(sp, r) - 1]
303+
end
304+
end
305+
306+
307+
308+
function medium(sp::Union{DielectricSphere,DielectricSphereThinImpedanceLayer}, ex::Excitation, r)
309+
if layer(sp, r) == 2
310+
return ex.embedding
311+
else
312+
return sp.filling
313+
end
314+
end
315+
316+
317+
318+
"""
319+
medium(sp::Sphere, ex::Excitation, r)
320+
321+
Returns the medium of the sphere `sp` at radius `r`.
322+
If this part is PEC, a zero medium is returned. The
323+
argument `r` may be a vector of positions.
324+
"""
325+
function medium(sp::PECSphere, ex::Excitation, r)
326+
if layer(sp, r) == 2
327+
return ex.embedding
328+
else
329+
Z = promote_type(typeof(ex.embedding.ε), typeof(ex.embedding.μ))(0.0)
330+
return Medium(Z, Z)
331+
end
332+
end
333+
334+
"""
335+
permittivity(sp::Sphere, ex::Excitation, r)
336+
337+
Returns the permittivity of the sphere `sp` at radius `r`.
338+
If this part is PEC, a zero permittivity is returned. The
339+
argument `r` may be a vector of positions.
340+
"""
341+
function permittivity(sp::Sphere, ex::Excitation, r)
342+
md = medium(sp, ex, r)
343+
return md.ε
344+
end
345+
346+
"""
347+
permeability(sp::Sphere, ex::Excitation, r)
348+
349+
Returns the permeability of the sphere `sp` at radius `r`.
350+
If this part is PEC, a zero permeability is returned. The
351+
argument `r` may be a vector of positions.
352+
"""
353+
function permeability(sp::Sphere, ex::Excitation, r)
354+
md = medium(sp, ex, r)
355+
return md.μ
356+
end
357+
358+
function permittivity(sp::Sphere, ex::Excitation, pts::AbstractVecOrMat)
359+
360+
ε = permittivity(sp, ex, norm(first(pts)))
361+
F = zeros(typeof(ε), size(pts))
362+
363+
# --- compute field in Cartesian representation
364+
for (ind, point) in enumerate(pts)
365+
F[ind] = permittivity(sp, ex, norm(point))
366+
end
367+
368+
return F
369+
end
370+
371+
function permeability(sp::Sphere, ex::Excitation, pts::AbstractVecOrMat)
372+
373+
ε = permeability(sp, ex, norm(first(pts)))
374+
F = zeros(typeof(ε), size(pts))
375+
376+
# --- compute field in Cartesian representation
377+
for (ind, point) in enumerate(pts)
378+
F[ind] = permeability(sp, ex, norm(point))
379+
end
380+
381+
return F
382+
end

test/sphere.jl

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,73 @@
1111

1212
@test Medium{Float64}(mdf) isa Medium{Float64}
1313

14+
pecsp = PECSphere(; radius=Float32(1.0))
15+
16+
@test numlayers(pecsp) == 2
17+
18+
ex_md = planeWave(; frequency=1e8, embedding=md)
19+
20+
@test medium(pecsp, ex_md, 3.0) == ex_md.embedding
21+
22+
@test medium(pecsp, ex_md, 0.5) == Medium(0.0, 0.0)
23+
24+
@test SphericalScattering.wavenumber(pecsp, ex_md, 0.0) == 0.0
25+
1426
sp = DielectricSphere(; radius=Float32(1.0), filling=md)
1527

28+
@test medium(sp, ex_md, 0.5) == md
29+
@test medium(sp, ex_md, 1.5) == md
30+
@test medium(sp, planeWave(; frequency=1e8, embedding=mdf), 1.5) == mdf
31+
1632
@test sp isa DielectricSphere{Float64,Float32}
1733

1834
@test SphericalScattering.impedance(sp, planeWave(; frequency=1e8, embedding=mdf), 2.0) 0.707106 rtol = 1e-5
1935

2036
@test SphericalScattering.wavenumber(sp, planeWave(; frequency=1e8, embedding=mdf), 2.0) 8.8857658e8 rtol = 1e-5
2137

38+
md1 = Medium(15.0, -2.1) # innermost medium
39+
md2 = Medium(-10, -2.0) # innermost medium
40+
41+
@test_throws ErrorException("Radii are not ordered ascendingly.") LayeredSphere(;
42+
radii=SVector(0.25, 0.5, 0.3), filling=SVector(md1, md2, md)
43+
)
44+
@test_throws ErrorException("Number of fillings does not match number of radii.") LayeredSphere(;
45+
radii=SVector(0.25, 0.3, 0.5), filling=SVector(md1, md2)
46+
)
47+
48+
@test_throws ErrorException("Radii are not ordered ascendingly.") LayeredSpherePEC(;
49+
radii=SVector(0.25, 0.5, 0.3), filling=SVector(md1, md2)
50+
)
51+
@test_throws ErrorException("Number of fillings does not match number of radii.") LayeredSpherePEC(;
52+
radii=SVector(0.25, 0.3, 0.5), filling=SVector(md1)
53+
)
54+
55+
spl = LayeredSphere(; radii=SVector(0.25, 0.3, 0.5), filling=SVector(md1, md2, md))
56+
57+
@test numlayers(spl) == 4
58+
59+
@test layer(spl, 0.1) == 1
60+
@test layer(spl, 0.24999) == 1
61+
@test layer(spl, 0.25) == 2
62+
@test layer(spl, 0.4) == 3
63+
@test layer(spl, 0.5) == 4
64+
@test layer(spl, 1.6) == 4
65+
66+
ex = planeWave(; frequency=1e8, embedding=Medium(-3.0, 2.0))
67+
68+
@test permittivity(spl, ex, 0.1) == 15.0
69+
@test permittivity(spl, ex, 0.24999) == 15.0
70+
@test permeability(spl, ex, 0.25) == -2.0
71+
@test permeability(spl, ex, 1.25) == 2.0
72+
73+
spl = LayeredSpherePEC(; radii=SVector(0.25, 0.3, 0.5), filling=SVector(md1, md2))
74+
@test medium(spl, ex_md, 1.5) == md
75+
76+
@test permittivity(spl, ex, 0.1) == 0.0
77+
@test permittivity(spl, ex, 0.25) == 15.0
78+
79+
pts = [SVector(0.1, 0.0, 0.0), SVector(0.25, 0.0, 0.0)]
80+
81+
@test permittivity(spl, ex, pts) == [0.0, 15.0]
82+
@test permeability(spl, ex, pts) == [0.0, -2.1]
2283
end

0 commit comments

Comments
 (0)