diff --git a/src/Greens_kernels.jl b/src/Greens_kernels.jl new file mode 100644 index 0000000..95d3d43 --- /dev/null +++ b/src/Greens_kernels.jl @@ -0,0 +1,43 @@ +# zero kernel, useful sometimes +zero_kernel(_, _) = zero(Complex{Float64}) + +# Kernel for 2D Helmholtz BIE +HelhmoltzGreen2D(k::Number,r::Real) = im/4*besselh(0,1,k*r) +HelhmoltzGreen2D(k::Number,x::Real, y::Real) = im/4*besselh(0,1,k*abs(x-y)) +HelhmoltzGreen2D(k::Number,x::AbstractVector, y::AbstractVector) = im/4*besselh(0,1,k*norm(x-y)) + +# Kernel for Laplace BIE, covers all dimensions, generalised from t=0,1 to any t +function Φₜ(t::Real, r::T) where T<:Union{Real,AbstractVector} + if t==0 + return log(norm(r)) + else + return norm(r)^(-t) + end +end +Φₜ(t::Real, x::Real, y::Real) = Φₜ(t,abs(x-y)) +Φₜ(t::Real, x::AbstractVector, y::AbstractVector) = Φₜ(t,norm(x-y)) + +function HelhmoltzGreen2D_Lipschitz_part(k::Number, r::Real)# where T<:Union{Real,AbstractVector} + if isapprox(r,0.0,atol=1e-14) # r ≈ 0 + return im/4 -1/(2π)*(0.577215664901532 + log(k/2)) + else + return HelhmoltzGreen2D(k,r) + 1/(2π)*log(r) + end +end +HelhmoltzGreen2D_Lipschitz_part(k::Number, x::Real, y::Real) = HelhmoltzGreen2D_Lipschitz_part(k,abs(x-y)) +HelhmoltzGreen2D_Lipschitz_part(k::Number, x::AbstractVector, y::AbstractVector) = HelhmoltzGreen2D_Lipschitz_part(k,norm(x-y)) + +# 3D Helmholtz kernels +HelhmoltzGreen3D(k::Number,r::Real) = exp(im*k*r)/(4π*r) +HelhmoltzGreen3D(k::Number,x::Real,y::Real) = exp(im*k*abs(x-y))/(4π*abs(x-y)) +HelhmoltzGreen3D(k::Number,x::AbstractVector,y::AbstractVector) = exp(im*k*norm(x-y))/(4π*norm(x-y)) + +function HelhmoltzGreen3D_Lipschitz_part(k::Number, r::Real) + if isapprox(r,0.0,atol=1e-14) + return im*k/(4π) + else + return expm1(im*k*norm(r)) /(4π*norm(r)) + end +end +HelhmoltzGreen3D_Lipschitz_part(k::Number, x::Real, y::Real) = HelhmoltzGreen3D_Lipschitz_part(k,abs(x-y)) +HelhmoltzGreen3D_Lipschitz_part(k::Number, x::AbstractVector, y::AbstractVector) = HelhmoltzGreen3D_Lipschitz_part(k,norm(x-y)) diff --git a/src/IFSintegrals.jl b/src/IFSintegrals.jl index de85dc7..363baa1 100644 --- a/src/IFSintegrals.jl +++ b/src/IFSintegrals.jl @@ -42,8 +42,9 @@ include("Galerkin_discretisation.jl") include("projections.jl") include("diam_approx.jl") include("fractal_presets.jl") +include("Greens_kernels.jl") include("operator_presets.jl") -include("screen_scattering.jl") +include("scattering_functionals.jl") include("plotting.jl") include("Jacobi_matrices.jl") include("VIE_operators.jl") diff --git a/src/operator_presets.jl b/src/operator_presets.jl index 77aabb8..789367e 100644 --- a/src/operator_presets.jl +++ b/src/operator_presets.jl @@ -1,35 +1,3 @@ -HelhmoltzGreen2D(k::Number,x::T, y::T) where T<:Union{Real,AbstractVector} = im/4*besselh(0,1,k*norm(x-y)) -HelhmoltzGreen2D(k::Number,r::Real) = im/4*besselh(0,1,k*r) -function Φₜ(t::Real, x::T, y::T) where T<:Union{Real,AbstractVector} - if t==0 - return log(norm(x-y)) - else - return (norm(x-y))^(-t) - end -end -Φₜ(t::Real, x::Vector{Float64}, y::SVector{N,Float64}) where N = Φₜ(t, x, Vector{Float64}(y)) - -zero_kernel(_, _) = zero(Complex{Float64}) - -function HelhmoltzGreen2D_Lipschitz_part(k::Number, x::T, y::T) where T<:Union{Real,AbstractVector} - if x == y - return im/4 -1/(2π)*(0.577215664901532 + log(k/2)) - else - return HelhmoltzGreen2D(k,x,y) + 1/(2π)*log(norm(x-y)) - end -end - -HelhmoltzGreen3D(k::Number,x::T,y::T) where T<:Union{Real,AbstractVector} = exp(im*k*norm(x-y))/(4π*norm(x-y)) -HelhmoltzGreen3D(k::Number,r::Real) = exp(im*k*r)/(4π*r) - -function HelhmoltzGreen3D_Lipschitz_part(k::Number, x::T, y::T) where T<:Union{Real,AbstractVector} - if x == y - return im*k/(4π) - else - return expm1(im*k*norm(x-y)) /(4π*norm(x-y))#HelhmoltzGreen3D(k,x,y) - 1.0 /(4π*norm(x-y)) - end -end - # get_spatial_dimension(Γ::FractalMeasure) """ SingleLayerOperatorLaplace(Γ::FractalMeasure, wavenumber::Real=0.0) diff --git a/src/screen_scattering.jl b/src/scattering_functionals.jl similarity index 86% rename from src/screen_scattering.jl rename to src/scattering_functionals.jl index 7a16750..612ca76 100644 --- a/src/screen_scattering.jl +++ b/src/scattering_functionals.jl @@ -80,15 +80,31 @@ function VolumePotential(Γ::FractalMeasure, k::Number)# where Ω <: FractalMeas end function SingleLayerPotentialHelmholtz(density::Projection, - k::T; ambient_dimension::Int64 = density.domain.spatial_dimension, + k::Number; ambient_dimension::Int64 = density.domain.spatial_dimension, h_quad::Float64 = 0.1/abs(k) - ) where T<:Number# where {V<:Union{Real,AbstractVector}, M<:Union{Real,AbstractMatrix}, T<:Number} + )# where {V<:Union{Real,AbstractVector}, M<:Union{Real,AbstractMatrix}, T<:Number} + + # choose appropriate Green's kernel + if ambient_dimension == 2 + K = (r::Float64)-> HelhmoltzGreen2D(k,r) + elseif ambient_dimension == 3 + K = (r::Float64)-> HelhmoltzGreen3D(k,r) + else + error("Cannot compute single layer potential for this number of spatial dimensions") + end + # return the potential function + return get_layer_potential(density, K, h_quad) +end +function SingleLayerPotentialLaplace(density::Projection; + ambient_dimension::Int64 = density.domain.spatial_dimension, + h_quad::Number = 0.1 + ) # choose appropriate Green's kernel if ambient_dimension == 2 - K = (r::Float64)-> HelhmoltzGreen2D(k::T,r) + K = (r::Float64)-> Φₜ(0.0, r)#HelhmoltzGreen2D(k::T,r) elseif ambient_dimension == 3 - K = (r::Float64)-> HelhmoltzGreen3D(k::T,r) + K = (r::Float64)-> Φₜ(1.0, r)#HelhmoltzGreen3D(k::T,r) else error("Cannot compute single layer potential for this number of spatial dimensions") end