Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/bases/timebasis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,13 @@ function assemblydata(tbf::TimeBasisFunction)
els = [ simplex(point((i-1)*Δt),point(i*Δt)) for i in 1:num_cells ]

for k in 1 : numfunctions(tbf)
tk = (k-1) * Δt
tk = k * Δt
for i in 1 : numintervals(tbf)
# Focus on interval [(i-2)Δt,(i-1)Δt]
p = tbf.polys[i]
q = substitute(p,t-tk)

c = k + i - 2
c = k + i - 1
1 <= c <= num_cells || continue
for d = 0 : degree(q)
r = d + 1
Expand Down Expand Up @@ -301,10 +301,10 @@ function assemblydata(tbf::TimeBasisDelta)
num_funcs = zeros(Int, num_cells, num_refs)
data = fill((0,z), max_num_funcs, num_refs, num_cells)

els = [ simplex(point((i-0)*Δt),point((i+1)*Δt)) for i in 1:num_cells ]
els = [ simplex(point((i-1)*Δt),point(i*Δt)) for i in 1:num_cells ]

for k in 1 : numfunctions(tbf)-1
data[1,1,k] = (k+1,w)
for k in 1 : numfunctions(tbf)
data[1,1,k] = (k,w)
end

return els, AssemblyData(data)
Expand Down
48 changes: 48 additions & 0 deletions src/maxwell/mwops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ struct MWSingleLayer3D{T,U} <: MaxwellOperator3D{T,U}
β::U
end

struct MWStaticExtractedHyperSingular{T,U} <: MaxwellOperator3D{T,U}
gamma::T
β::U
end

# Maxwell hypersingular operator, with its static kernel removed, can be assembled using basis functions other than div-conforming ones
MWStaticExtractedHyperSingular(gamma) = MWStaticExtractedHyperSingular(gamma, -1/(gamma))

defaultquadstrat(op::MWStaticExtractedHyperSingular, tfs::RTRefSpace, bfs::RTRefSpace) = DoubleNumSauterQstrat(6,7,5,5,4,3)

gamma(op::MWSingleLayer3D{Val{0}, U}) where {U} = zero(U)

scalartype(op::MWSingleLayer3D{T,U}) where {T,U} = promote_type(T,U)
Expand Down Expand Up @@ -137,6 +147,44 @@ function (igd::Integrand{<:MWSingleLayer3DReg})(x,y,f,g)
end
end

# MWStaticExtractedHyperSingular operator, discretized and tested by RT. Integration-by-parts is performed
function (igd::Integrand{<:MWStaticExtractedHyperSingular, <:RTRefSpace, <:RTRefSpace})(x,y,f,g)
β = igd.operator.β
γ = igd.operator.gamma

r = cartesian(x) - cartesian(y)
R = norm(r)
iR = 1/R
γR = γ*R

green = expm1(-γR) * (i4pi * iR) + γ * i4pi
βG = β * green

_integrands(f,g) do fi,gj
βG * dot(fi.divergence, gj.divergence)
end
end

# MWStaticExtractedHyperSingular operator, discretized by RT and tested by other functions. Integration-by-parts is not performed. Instead, grad of regularized Green's function is used
function (igd::Integrand{<:MWStaticExtractedHyperSingular, <:RefSpace, <:RTRefSpace})(x,y,f,g)
β = igd.operator.β
γ = igd.operator.gamma

r = cartesian(x) - cartesian(y)
R = norm(r)
iR = 1/R
γR = γ*R

gradgreen = -(expm1(-γR) * (1 + γR) + γR) * (i4pi * iR^3) * r

# Minus sign is because integration-by-part is not performed
βgG = -β * gradgreen

_integrands(f,g) do fi,gj
dot(fi.value, βgG*gj.divergence)
end
end


function (igd::Integrand{<:MWDoubleLayer3D})(x,y,f,g)

Expand Down
11 changes: 9 additions & 2 deletions src/utils/specialfns.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,23 @@ end
function fouriertransform(a::Array, dt, t0, dim=1)
n = size(a,dim)
dω = 2π / (n*dt)
b = fftshift(fft(a, dim), dim) * dt / sqrt(2π)
ω0 = -dω * div(n,2)
ω = ω0 .+ dω .* (0:n-1)

b = fftshift(fft(a, dim), dim) * dt / sqrt(2π)
b .*= reshape(exp.(-im .* ω .* t0), ntuple(j -> j == dim ? n : 1, ndims(a)))

b, dω, ω0
end

function inversefouriertransform(a::Array, dω, ω0, dim=1)
n = size(a,dim)
dt = 2π/ (n*dω)
b = ifft(a,dim) * sqrt(2π) / dt
ω = ω0 .+ dω .* (0:n-1)
t0 = -dt * div(n,2)

b = ifft(ifftshift(a .* reshape(exp.(im .* ω .* t0), ntuple(j -> j == dim ? n : 1, ndims(a))), dim), dim) * sqrt(2π) / dt

b, dt, t0
end

Expand Down
83 changes: 83 additions & 0 deletions test/test_assemble_tdexcitation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
@testitem "testing TDFunctional" begin

using CompScienceMeshes

Γ = meshcuboid(1.0, 1.0, 1.0, 2.0; generator=:gmsh)
X = raviartthomas(Γ)

struct ConstFunctional{T} <: BEAST.Functional{T}
constant::T
end

function(f::ConstFunctional)(r)
f.constant * [1.0, 0.0, 0.0]
end

struct FuncXGaussian{T} <: BEAST.TDFunctional{T}
functional::ConstFunctional{T}
gaussian::BEAST.Gaussian{T}
end

function(f::FuncXGaussian)(r,t)
r = cartesian(r)
t = cartesian(t)[1]

f.functional(r) * f.gaussian(t)
end

Δt, Nt = 0.5, 20
duration = 4 * Δt
delay = 10 * Δt

func = ConstFunctional(1.0)
gaussian = creategaussian(duration, delay)
constxgaussian = FuncXGaussian(func, gaussian)


### Testing with Dirac delta
δ = timebasisdelta(Δt, Nt)
A = assemble(constxgaussian, X⊗δ)
# Analytically temporal testing
Ats = assemble(func, X) * gaussian.(Δt*[1:1:Nt;])'

@test maximum(abs.(A - Ats)) < 1e-12


### Testing with pulse functions
p = timebasiscxd0(Δt, Nt)
B = assemble(constxgaussian, X⊗p)
igaussian = integrate(gaussian)
Bts = assemble(func, X) * (igaussian.(Δt*[1:1:Nt;]) - igaussian.(Δt*[0:1:Nt-1;]))'

@test maximum(abs.(B - Bts)) < 1e-12


### Testing with hat functions
import SpecialFunctions: erf
function integratewithh(g::BEAST.Gaussian, ts, Δt)
A = g.scaling
t0 = g.delay
w = g.width

r = zeros(length(ts))

for i in ts
a = (i-1)*Δt
x = i*Δt
b = (i+1)*Δt

ua = 4*(a-t0)/w
ux = 4*(x-t0)/w
ub = 4*(b-t0)/w

r[i] = A/(2*Δt) * ((t0 - a)*(erf(ux) - erf(ua)) + (b - t0)*(erf(ub) - erf(ux))) + A*w/(8*√(π)*Δt)*(exp(-ua^2) + exp(-ub^2) - 2*exp(-ux^2))
end
return r
end

h = timebasisc0d1(Δt, Nt)
C = assemble(constxgaussian, X⊗h)
Cts = assemble(func, X) * integratewithh(gaussian, [1:1:Nt;], Δt)'

@test maximum(abs.(C - Cts)) < 1e-12
end
8 changes: 4 additions & 4 deletions test/test_tdrhs_scaling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ derive(gaussian2).(taxis2)[120]/sol2
@test all(derive(gaussian1).(taxis1)/sol1 .≈ derive(gaussian2).(taxis2)/sol2)

timeels1, timead1 = BEAST.assemblydata(U1)
@test timeels1[100][1][1] ≈ Δt1*100
@test timeels1[100][2][1] ≈ Δt1*101
@test timeels1[100][1][1] ≈ Δt1*99
@test timeels1[100][2][1] ≈ Δt1*100

timeels2, timead2 = BEAST.assemblydata(U2)
@test timeels2[100][1][1] ≈ Δt2*100
@test timeels2[100][2][1] ≈ Δt2*101
@test timeels2[100][1][1] ≈ Δt2*99
@test timeels2[100][2][1] ≈ Δt2*100

b1[120]/sol1
b2[120]/sol2
Expand Down
Loading