Skip to content

Commit e2d2419

Browse files
committed
begin working towards local_bdim
1 parent 3b2d94a commit e2d2419

File tree

4 files changed

+106
-89
lines changed

4 files changed

+106
-89
lines changed

src/adaptive.jl

+5-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ function adaptive_correction(iop::IntegralOperator; tol, maxdist = nothing, maxs
4242
else
4343
maxdist
4444
end
45-
dict_near = near_interaction_list(X, Y; tol = maxdist)
45+
dict_near = elements_to_near_targets(X, Y; tol = maxdist)
4646
T = eltype(iop)
4747
msh = mesh(Y)
4848
correction = (I = Int[], J = Int[], V = T[])
@@ -166,14 +166,14 @@ function adaptive_integration_singular(f, τ̂::ReferenceLine, x̂ₛ; kwargs...
166166
end
167167
end
168168

169-
function near_interaction_list(QX::Quadrature, QY::Quadrature; tol)
169+
function elements_to_near_targets(QX::Quadrature, QY::Quadrature; tol)
170170
X = [coords(q) for q in QX]
171171
msh = mesh(QY)
172-
return near_interaction_list(X, msh; tol)
172+
return elements_to_near_targets(X, msh; tol)
173173
end
174-
function near_interaction_list(X, QY::Quadrature; tol)
174+
function elements_to_near_targets(X, QY::Quadrature; tol)
175175
msh = mesh(QY)
176-
return near_interaction_list(X, msh; tol)
176+
return elements_to_near_targets(X, msh; tol)
177177
end
178178

179179
"""

src/bdim.jl

+15-15
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ function local_bdim_correction(
196196
m, n = length(target), length(source)
197197
msh = source.mesh
198198
qnodes = source.qnodes
199-
neighbors = topological_neighbors(msh)
199+
# neighbors = topological_neighbors(msh)
200200
dict_near = etype_to_nearest_points(target, source; maxdist)
201201
# find first an appropriate set of source points to center the monopoles
202202
qmax = sum(size(mat, 1) for mat in values(source.etype2qtags)) # max number of qnodes per el
@@ -268,20 +268,20 @@ function local_bdim_correction(
268268
# quadrature for auxiliary surface. In global dim, this is the same
269269
# as the source quadrature, and independent of element. In local
270270
# dim, this is constructed for each element using its neighbors.
271-
function translate(q::QuadratureNode, x, s)
272-
return QuadratureNode(coords(q) + x, weight(q), s * normal(q))
273-
end
274-
nei = neighbors[(E, n)]
275-
qtags_nei = Int[]
276-
for (E, n) in nei
277-
append!(qtags_nei, source.etype2qtags[E][:, n])
278-
end
279-
qnodes_nei = source.qnodes[qtags_nei]
280-
jac = jacobian(el, 0.5)
281-
ν = _normal(jac)
282-
h = sum(qnodes[i].weight for i in jglob)
283-
qnodes_op = map(q -> translate(q, h * ν, -1), qnodes_nei)
284-
a, b = external_boundary()
271+
# function translate(q::QuadratureNode, x, s)
272+
# return QuadratureNode(coords(q) + x, weight(q), s * normal(q))
273+
# end
274+
# nei = neighbors[(E, n)]
275+
# qtags_nei = Int[]
276+
# for (E, n) in nei
277+
# append!(qtags_nei, source.etype2qtags[E][:, n])
278+
# end
279+
# qnodes_nei = source.qnodes[qtags_nei]
280+
# jac = jacobian(el, 0.5)
281+
# ν = _normal(jac)
282+
# h = sum(qnodes[i].weight for i in jglob)
283+
# qnodes_op = map(q -> translate(q, h * ν, -1), qnodes_nei)
284+
# a, b = external_boundary()
285285
# qnodes_aux = source.qnodes[jglob]
286286
qnodes_aux = source.qnodes # this is the global dim
287287
for i in near_list[n]

src/mesh.jl

+34-69
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ function connectivity(msh::SubMesh, E::DataType)
515515
end
516516

517517
"""
518-
near_interaction_list(X,Y::AbstractMesh; tol)
518+
elements_to_near_targets(X,Y::AbstractMesh; tol)
519519
520520
For each element `el` of type `E` in `Y`, return the indices of the points in
521521
`X` which are closer than `tol` to the `center` of `el`.
@@ -526,7 +526,7 @@ fifth element of type `E`.
526526
527527
If `tol` is a `Dict`, then `tol[E]` is the tolerance for elements of type `E`.
528528
"""
529-
function near_interaction_list(
529+
function elements_to_near_targets(
530530
X::AbstractVector{<:SVector{N}},
531531
Y::AbstractMesh{N};
532532
tol,
@@ -538,17 +538,47 @@ function near_interaction_list(
538538
for E in element_types(Y)
539539
els = elements(Y, E)
540540
tol_ = isa(tol, Number) ? tol : tol[E]
541-
idxs = _near_interaction_list(balltree, els, tol_)
541+
idxs = _elements_to_near_targets(balltree, els, tol_)
542542
dict[E] = idxs
543543
end
544544
return dict
545545
end
546546

547-
@noinline function _near_interaction_list(balltree, els, tol)
547+
@noinline function _elements_to_near_targets(balltree, els, tol)
548548
centers = map(center, els)
549549
return inrange(balltree, centers, tol)
550550
end
551551

552+
"""
553+
target_to_near_elements(X::AbstractVector{<:SVector{N}}, Y::AbstractMesh{N};
554+
tol)
555+
556+
For each target `x` in `X`, return a vector of tuples `(E, i)` where `E` is the
557+
type of the element in `Y` and `i` is the index of the element in `Y` such that
558+
`x` is closer than `tol` to the center of the element.
559+
"""
560+
function target_to_near_elements(
561+
X::AbstractVector{<:SVector{N}},
562+
Y::AbstractMesh{N};
563+
tol,
564+
) where {N}
565+
@assert isa(tol, Number) || isa(tol, Dict) "tol must be a number or a dictionary mapping element types to numbers"
566+
dict = Dict{Int,Vector{Tuple{DataType,Int}}}()
567+
balltree = BallTree(X)
568+
for E in element_types(Y)
569+
els = elements(Y, E)
570+
tol_ = isa(tol, Number) ? tol : tol[E]
571+
idxs = _target_to_near_elements(balltree, els, tol_)
572+
for (i, idx) in enumerate(idxs)
573+
dict[i] = get!(dict, i, Vector{Tuple{DataType,Int}}())
574+
for j in idx
575+
push!(dict[i], (E, j))
576+
end
577+
end
578+
end
579+
return dict
580+
end
581+
552582
"""
553583
topological_neighbors(msh::LagrangeMesh, k=1)
554584
@@ -586,68 +616,3 @@ function topological_neighbors(msh::LagrangeMesh, k = 1)
586616
#TODO: for k > 1, recursively compute the neighbors from the one-neighbors
587617
return one_neighbors
588618
end
589-
590-
"""
591-
element_to_near_targets(X,Y::AbstractMesh; tol)
592-
593-
For each element `el` of type `E` in `Y`, return the indices of the points in
594-
`X` which are closer than `tol` to the `center` of `el`.
595-
596-
This function returns a dictionary where e.g. `dict[E][5] --> Vector{Int}` gives
597-
the indices of points in `X` which are closer than `tol` to the center of the
598-
fifth element of type `E`.
599-
600-
If `tol` is a `Dict`, then `tol[E]` is the tolerance for elements of type `E`.
601-
"""
602-
function element_to_near_targets(
603-
X::AbstractVector{<:SVector{N}},
604-
Y::AbstractMesh{N};
605-
tol,
606-
) where {N}
607-
@assert isa(tol, Number) || isa(tol, Dict) "tol must be a number or a dictionary mapping element types to numbers"
608-
# for each element type, build the list of targets close to a given element
609-
dict = Dict{DataType,Vector{Vector{Int}}}()
610-
balltree = BallTree(X)
611-
for E in element_types(Y)
612-
els = elements(Y, E)
613-
tol_ = isa(tol, Number) ? tol : tol[E]
614-
idxs = _element_to_near_targets(balltree, els, tol_)
615-
dict[E] = idxs
616-
end
617-
return dict
618-
end
619-
620-
@noinline function _element_to_near_targets(balltree, els, tol)
621-
centers = map(center, els)
622-
return inrange(balltree, centers, tol)
623-
end
624-
625-
"""
626-
target_to_near_elements(X::AbstractVector{<:SVector{N}}, Y::AbstractMesh{N};
627-
tol)
628-
629-
For each target `x` in `X`, return a vector of tuples `(E, i)` where `E` is the
630-
type of the element in `Y` and `i` is the index of the element in `Y` such that
631-
`x` is closer than `tol` to the center of the element.
632-
"""
633-
function target_to_near_elements(
634-
X::AbstractVector{<:SVector{N}},
635-
Y::AbstractMesh{N};
636-
tol,
637-
) where {N}
638-
@assert isa(tol, Number) || isa(tol, Dict) "tol must be a number or a dictionary mapping element types to numbers"
639-
dict = Dict{Int,Vector{Tuple{DataType,Int}}}()
640-
balltree = BallTree(X)
641-
for E in element_types(Y)
642-
els = elements(Y, E)
643-
tol_ = isa(tol, Number) ? tol : tol[E]
644-
idxs = _target_to_near_elements(balltree, els, tol_)
645-
for (i, idx) in enumerate(idxs)
646-
dict[i] = get!(dict, i, Vector{Tuple{DataType,Int}}())
647-
for j in idx
648-
push!(dict[i], (E, j))
649-
end
650-
end
651-
end
652-
return dict
653-
end

test/ldim_test.jl

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using Test
2+
using LinearAlgebra
3+
using Inti
4+
using Random
5+
6+
include("test_utils.jl")
7+
8+
Random.seed!(1)
9+
10+
atol = 5e-2
11+
12+
N = 2
13+
t = :interior
14+
pde = Inti.Laplace(; dim = N)
15+
Inti.clear_entities!()
16+
Ω, msh = gmsh_disk(; center = [0.0, 0.0], rx = 1.0, ry = 1.0, meshsize = 0.2)
17+
Γ = Inti.external_boundary(Ω)
18+
quad = Inti.Quadrature(view(msh, Γ); qorder = 3)
19+
σ = t == :interior ? 1 / 2 : -1 / 2
20+
xs = t == :interior ? ntuple(i -> 3, N) : ntuple(i -> 0.1, N)
21+
T = Inti.default_density_eltype(pde)
22+
c = rand(T)
23+
u = (qnode) -> Inti.SingleLayerKernel(pde)(qnode, xs) * c
24+
dudn = (qnode) -> Inti.AdjointDoubleLayerKernel(pde)(qnode, xs) * c
25+
γ₀u = map(u, quad)
26+
γ₁u = map(dudn, quad)
27+
γ₀u_norm = norm(norm.(γ₀u, Inf), Inf)
28+
γ₁u_norm = norm(norm.(γ₁u, Inf), Inf)
29+
# single and double layer
30+
G = Inti.SingleLayerKernel(pde)
31+
S = Inti.IntegralOperator(G, quad)
32+
Smat = Inti.assemble_matrix(S)
33+
dG = Inti.DoubleLayerKernel(pde)
34+
D = Inti.IntegralOperator(dG, quad)
35+
Dmat = Inti.assemble_matrix(D)
36+
e0 = norm(Smat * γ₁u - Dmat * γ₀u - σ * γ₀u, Inf) / γ₀u_norm
37+
38+
green_multiplier = fill(-0.5, length(quad))
39+
# δS, δD = Inti.bdim_correction(pde, quad, quad, Smat, Dmat; green_multiplier)
40+
δS, δD = Inti.local_bdim_correction(pde, quad, quad, Smat, Dmat; green_multiplier)
41+
Sdim = Smat + δS
42+
Ddim = Dmat + δD
43+
# Sdim, Ddim = Inti.single_double_layer(;
44+
# pde,
45+
# target = quad,
46+
# source = quad,
47+
# compression = (method = :none,),
48+
# correction = (method = :ldim,),
49+
# )
50+
e1 = norm(Sdim * γ₁u - Ddim * γ₀u - σ * γ₀u, Inf) / γ₀u_norm
51+
@show norm(e0, Inf)
52+
@show norm(e1, Inf)

0 commit comments

Comments
 (0)