Skip to content

Commit 710d3ec

Browse files
committed
Improve type hygene in wavelike
No allocations for Float32/64/Duals. Also tested nearfield and NKPanelSystem which were fine.
1 parent 23554a1 commit 710d3ec

File tree

4 files changed

+27
-21
lines changed

4 files changed

+27
-21
lines changed

src/NKPanelSystem.jl

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,23 @@ Ngk(X::SVector{3}) = Ngk(X...)
103103
# Wave-like disturbance
104104
function wavelike(x::T,y::T,z::T)::T where T
105105
(x0 || z-10) && return zero(T) # trivial case
106-
R = (-10/z-1) # heuristic t limit
107-
S = filter(s->-R<s<R,stationary_points(x,y)) # g'=0 points
106+
xv,yv,zv = value.((x,y,z)) # strip any Duals for ranges
107+
R,Δg = (-10/zv-1),typeof(xv).(5.4) # heuristic angle & phase limits
108+
S = filter(s->-R<s<R,stationary_points(xv,yv)) # g'=0 points
108109
f(t) = exp(z*(1+t^2))*sin(g(x,y,t)) # integrand
109-
length(S)==0 && return quadgl(f,-R,R) # easy case
110-
rngs = finite_ranges(S,t->g(x,y,t),5.4,R) # finite phase ranges
111-
4complex_path(t->g(x,y,t)-im*z*(1+t^2), # complex phase
112-
t->dg(x,y,t)-2im*z*t, rngs; f) # it's derivative
110+
length(S)==0 && return quadgl(f,-R,R) # real-line case
111+
rngs = finite_ranges(S,t->g(xv,yv,t),Δg,R) # finite phase ranges
112+
4complex_path(t->g(x,y,t)-im*z*(1+t^2), # complex case: complex phase
113+
t->dg(x,y,t)-2im*z*t, rngs; f) # ...and it's derivative
113114
end
114115
g(x,y,t) = (x+y*t)*⎷(1+t^2) # phase function
115116
dg(x,y,t) = (x*t+y*(2t^2+1))/⎷(1+t^2) # it's derivative
116117
⎷(z::Complex) = π/2angle(z)π ? -√z : z # move √ branch-cut
117118
⎷(x) = x
118119

119120
# Return points where dg=0
120-
function stationary_points(x,y)
121-
abs(y)eps() && return (0.,)
121+
function stationary_points(x::T,y::T) where T
122+
abs(y)eps(T) && return (zero(T),)
122123
diff = x^2-8y^2
123124
diffeps() ? (-x/4y,) : @. (-x+(-1,1)*√diff)/4y
124125
end

src/panels.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@ The parameter `(hᵤ+hᵥ)*c` sets the max deviation of the panel from a flat pl
99
panel size in regions of high curvature. Errors if the adaptive routine gives more than `N_max` panels.
1010
"""
1111
function panelize(surface,u₀=0.,u₁=1.,v₀=0.,v₁=1.;hᵤ=1.,hᵥ=hᵤ,c=0.05,
12-
transpose=false,flip=false,N_max=1000,verbose=false,kwargs...)
12+
transpose=false,flip=false,N_max=1000,verbose=false,T=Float64,kwargs...)
1313
# Transpose arguments u,v -> v,u
1414
transpose && return panelize((v,u)->surface(u,v),v₀,v₁,u₀,u₁,;hᵤ=hᵥ,hᵥ=hᵤ,c,
15-
transpose=false,flip=!flip,N_max,verbose,kwargs...)
15+
transpose=false,flip=!flip,N_max,verbose,T,kwargs...)
1616

1717
# Check inputs and get output type
1818
(u₀u₁ || v₀v₁) && throw(ArgumentError("Need `u₀<u₁` and `v₀<v₁`. Got [$u₀,$u₁],[$v₀,$v₁]."))
1919
(hᵤ0 || hᵥ0 || c0) && throw(ArgumentError("Need positive `hᵤ,hᵥ,c`. Got $hᵤ,$hᵥ,$c."))
20+
u₀,u₁,v₀,v₁ = T.((u₀,u₁,v₀,v₁))
2021
!(typeof(surface(u₀,v₀)) <: SVector) && throw(ArgumentError("`surface` function doesn't return an SVector."))
21-
init = typeof(measure(surface,0.5u₀+0.5u₁,0.5v₀+0.5v₁,u₁-u₀,v₁-v₀))[]
22+
init = typeof(measure(surface,(u₀+u₁)/2,(v₀+v₁)/2,u₁-u₀,v₁-v₀))[]
2223

2324
# Get arcslength and inverse along bottom & top edges
2425
S₀,s₀⁻¹ = arclength(u->surface(u,v₀),hᵤ,c,u₀,u₁)
@@ -45,7 +46,7 @@ function panelize(surface,u₀=0.,u₁=1.,v₀=0.,v₁=1.;hᵤ=1.,hᵥ=hᵤ,c=0.
4546
dv = ve[2:end]-ve[1:end-1] # panel heights
4647

4748
# Measure panels along strip
48-
@. measure(surface,u,v,du,dv;flip,kwargs...)
49+
@. measure(surface,u,v,du,dv;flip,T,kwargs...)
4950
end
5051

5152
# Check length and return as a Table

src/quad.jl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ quadgl(f,a,b;x=xg32,w=wg32) = (b-a)/2*quadgl(t->f((b+a)/2+t*(b-a)/2);x,w)
1717
"""
1818
complex_path(g,dg,rngs;atol=1e-3,γ=one,f=Im(γ*exp(im*g)))
1919
20-
Estimate the integral `∫f(t)dt` from `t=[-∞,∞]` using a complex path, see Gibbs 2024. The
21-
finite phase ranges `rngs` are integrated along the real line with QuadGK. The range end
20+
Estimate the integral `∫f(t)dt` from `t=[-∞,∞]` using a complex path, see Gibbs 2024. The
21+
finite phase ranges `rngs` are integrated along the real line with QuadGK. The range end
2222
points where `flag=true` are integrated to ±∞ in the complex-plane using `±nsp(t₀,g,dg,γ)`.
2323
"""
2424
@inline function complex_path(g,dg,rngs;γ=one,
2525
f = t->((u,v)=reim(g(t)); @fastmath γ(t)*exp(-v)*sin(u)))
2626

2727
# Sum the flagged endpoints and interval contributions
28-
val = zero(rngs[1][1])
28+
val = zero(f(rngs[1][1]))
2929
for i in 1:2:length(rngs)
3030
(t₁,∞₁),(t₂,∞₂) = rngs[i],rngs[i+1]
3131
∞₁ && (val -= nsp(t₁,g,dg,γ))
@@ -62,15 +62,14 @@ such that `|g(a)-g(aᵢ)|≈Δg`. Ranges do no overlap and limited to `±R`. "Un
6262
`fᵢ=false` if `aᵢ=±R`.
6363
"""
6464
function finite_ranges(S::NTuple{N}, g, Δg, R; atol=Δg/10) where N
65-
Sv, Rv, gv = map(value,S), value(R), t->value(g(t)) # no Duals
6665
# helper functions to offset the phase and flag if there's no root
67-
dg(a) = t->abs(gv(a)-gv(t))-Δg
68-
no(a,b) = abs(gv(a)-gv(b)) Δg+atol
66+
dg(a) = t->abs(g(a)-g(t))-Δg
67+
no(a,b) = abs(g(a)-g(b)) Δg+atol
6968
# find roots of dg using brackets (Order0) or secant method (Order1)
7069
fz0(a,b) = no(a,b) ? (return b, false) : (find_zero(dg(a), (a,b), Order0()), true)
71-
fz1(a,b) = (isfinite(b) && no(a,b)) ? (return b, false) : (find_zero(dg(a), (a,a+copysign(1,b)), Order1(); atol), true)
70+
fz1(a,b) = (isfinite(b) && no(a,b)) ? (return b, false) : (find_zero(dg(a), (a,a+copysign(1,b)), Order1(); atol), true)
7271
# return flagged sub-range
73-
(fz1(first(Sv), -Rv), mid_ranges(Val(N), Sv, fz0)..., fz1(last(Sv), Rv))
72+
(fz1(first(S), -R), mid_ranges(Val(N), S, fz0)..., fz1(last(S), R))
7473
end
7574
using TupleTools
7675
mid_ranges(::Val{N}, S, fz) where N = TupleTools.vcat(ntuple(N-1) do i

test/runtests.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,9 @@ end
226226
@inline bruteW(x,y,z) = 4quadgk(t->exp(z*(1+t^2))*sin((x+y*t)*hypot(1,t)),-Inf,Inf,atol=1e-10)[1]
227227
@inline bruteN(x,y,z) = -2*(1-z/(hypot(x,y,z)+abs(x)))+NeumannKelvin.Ngk(x,y,z)
228228
using SpecialFunctions
229+
using ForwardDiff: Dual
229230
@testset "kelvin.jl" begin
230-
@test NeumannKelvin.stationary_points(-1,1/sqrt(8))[1]1/sqrt(2)
231+
@test NeumannKelvin.stationary_points(-1.,1/sqrt(8))[1]1/sqrt(2)
231232
@test NeumannKelvin.wavelike(10.,0.,-0.)==NeumannKelvin.wavelike(0.,10.,-0.)==0.
232233
@test 4π*bessely1(10)NeumannKelvin.wavelike(-10.,0.,-0.) atol=1e-5
233234

@@ -241,7 +242,11 @@ using SpecialFunctions
241242
end
242243

243244
@test @ballocations(NeumannKelvin.nearfield(-1.,0.,0.)) TEST_ALLOCS
245+
@test @ballocations(NeumannKelvin.nearfield(Dual(-1.,0),Dual(0.,0),Dual(0.,0))) TEST_ALLOCS
246+
@test @ballocations(NeumannKelvin.nearfield(Dual(-1f0,0),Dual(0f0,0),Dual(0f0,0))) TEST_ALLOCS
244247
@test @ballocations(NeumannKelvin.wavelike(-10.,1.,-1.)) TEST_ALLOCS
248+
@test @ballocations(NeumannKelvin.wavelike(Dual(-10.,1),Dual(1.,1),Dual(-1.,1))) TEST_ALLOCS
249+
@test @ballocations(NeumannKelvin.wavelike(Dual(-10f0,1),Dual(1f0,1),Dual(-1f0,1))) TEST_ALLOCS
245250
end
246251

247252
function prism(h;q=0.2,Z=1)

0 commit comments

Comments
 (0)