Skip to content

Commit

Permalink
Refactored way to compute signed distance
Browse files Browse the repository at this point in the history
  • Loading branch information
ericneiva committed Nov 20, 2023
1 parent 82cfaad commit 221af49
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 11 deletions.
55 changes: 50 additions & 5 deletions src/AlgoimUtils/AlgoimUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export init_bboxes
export fill_cpp_data
export fill_cpp_data_raw
export compute_closest_point_projections
export compute_displacement
export compute_normal_displacement
export compute_distance_fe_function
export delaunaytrian
Expand Down Expand Up @@ -290,7 +291,6 @@ function compute_closest_point_projections(model::AdaptedDiscreteModel,
limitstol::Float64=1.0e-8)
reffe = ReferenceFE(lagrangian,Float64,order)
rfespace = TestFESpace(model,reffe)
= φ.φ
_rφ = interpolate_everywhere.φ,rfespace)
= AlgoimCallLevelSetFunction(_rφ,(_rφ))
cdesc = get_cartesian_descriptor(get_model(model))
Expand Down Expand Up @@ -395,9 +395,54 @@ function compute_normal_displacement(
disps
end

_dist(x,y) = begin
sign = norm(x) > norm(y) ? -1 : 1
sign * ( (x[1]-y[1])^2 + (x[2]-y[2])^2 )

function compute_displacement(
cps::AbstractVector{<:Point},
phi::AlgoimCallLevelSetFunction,
fun,
dt::Float64,
Ω::Triangulation)
# Note that cps must be (scalar) DoF-numbered, not lexicographic-numbered
searchmethod = KDTreeSearch()
cache1 = _point_to_cell_cache(searchmethod,Ω)
x_to_cell(x) = _point_to_cell!(cache1, x)
point_to_cell = lazy_map(x_to_cell, cps)
cell_to_points, _ = make_inverse_table(point_to_cell, num_cells(Ω))
cell_to_xs = lazy_map(Broadcasting(Reindex(cps)), cell_to_points)
cell_point_xs = CellPoint(cell_to_xs, Ω, PhysicalDomain())
fun_xs = evaluate(fun,cell_point_xs)
∇φ_xs = evaluate(phi.∇φ,cell_point_xs)
cell_point_disp = lazy_map(Broadcasting(),fun_xs,∇φ_xs)
cache_vals = array_cache(cell_point_disp)
cache_ctop = array_cache(cell_to_points)
disps = zeros(Float64,length(cps))
for cell in 1:length(cell_to_points)
pts = getindex!(cache_ctop,cell_to_points,cell)
vals = getindex!(cache_vals,cell_point_disp,cell)
for (i,pt) in enumerate(pts)
val = vals[i]
disps[pt] = dt * val
end
end
disps
end

signed_distance::Function,x,y) = sign(φ(y))*norm(x-y)

signed_distance::T,x,y) where {T<:Number} = sign(φ)*norm(x-y)

function _compute_signed_distance(
φ::AlgoimCallLevelSetFunction{<:Function,<:Function},
cps::Vector{<:Point},cos::Matrix{<:Point})
_dist(x,y) = signed_distance.φ,x,y)
lazy_map(_dist,cps,cos)
end

function _compute_signed_distance(
φ::AlgoimCallLevelSetFunction{<:CellField,<:CellField},
cps::Vector{<:Point},cos::Matrix{<:Point})
φs = get_free_dof_values.φ)
lazy_map(signed_distance,φs,cps,cos)
end

function compute_distance_fe_function(
Expand All @@ -411,7 +456,7 @@ function compute_distance_fe_function(
rmodel = refine(bgmodel,order)
cos = get_node_coordinates(rmodel)
cos = node_to_dof_order(cos,fespace,rmodel,order)
dists = lazy_map(_dist,cps,cos)
dists = _compute_signed_distance,cps,cos)
FEFunction(fespace,dists)
end

Expand Down
1 change: 1 addition & 0 deletions src/Exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ end
@publish AlgoimUtils fill_cpp_data
@publish AlgoimUtils fill_cpp_data_raw
@publish AlgoimUtils compute_closest_point_projections
@publish AlgoimUtils compute_displacement
@publish AlgoimUtils compute_normal_displacement
@publish AlgoimUtils compute_distance_fe_function
@publish AlgoimUtils delaunaytrian
Expand Down
2 changes: 1 addition & 1 deletion test/AlgoimUtilsTests/DualQuadraturesTests.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module AlgoimInterfaceTests
module DualQuadraturesTests

using Test
using Gridap
Expand Down
215 changes: 210 additions & 5 deletions test/AlgoimUtilsTests/TwoPhaseStokesAlgoimTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ using GridapPardiso
using SparseMatricesCSR
using Test

function main(n::Int,w::Float64,νˡ::Float64,νˢ::Float64::Float64)
function steady_state(n::Int,w::Float64,νˡ::Float64,νˢ::Float64::Float64)

pmin = Point(-1.5,-1.0)
pmax = Point( 4.5, 1.0)
Expand Down Expand Up @@ -147,14 +147,219 @@ function main(n::Int,w::Float64,νˡ::Float64,νˢ::Float64,γ::Float64)

end

n = 80
w = 1.0e-1
function dynamic(n::Int,w::Float64,νˡ::Float64,νˢ::Float64::Float64,Δt₀::Float64)

pmin = Point(-1.5,-2.5)
pmax = Point( 3.5, 2.5)
partition = (n,n)

model = CartesianDiscreteModel(pmin,pmax,partition)
Ω = Triangulation(model)
dp = pmax - pmin
h = dp[2]/n

order = 2
degree = order == 1 ? 3 : 2*order

R = 0.12
φ(x) = 1.0 - ( ( x[1]*x[1] + x[2]*x[2] ) / R^2 )
reffeᵠ = ReferenceFE(lagrangian,Float64,order+1)
Vbg = TestFESpace(Ω,reffeᵠ)

# Buffer of active model and integration objects
buffer = Ref{Any}((Ωˡ=nothing,Ωˢ=nothing,
dΩˡ=nothing,dΩˢ=nothing,
=nothing,n_Γ=nothing,
aggsˡ=nothing,aggsˢ=nothing,
φ₋=nothing,cp₋=nothing,t=nothing))

function update_buffer!(t,dt,v₋₂)

if buffer[].t == t
return true
else

if buffer[].φ₋ === nothing
__φ₋ = AlgoimCallLevelSetFunction(φ,(φ))
_φ₋ = compute_distance_fe_function(model,Vbg,__φ₋,order+1,cppdegree=3)
else
cp₋₂ = buffer[].cp₋
φ₋₂ = buffer[].φ₋
ϕ₋ = compute_displacement(cp₋₂,φ₋₂,v₋₂,dt,Ω)
ϕ₋ = get_free_dof_values(φ₋₂.φ) - ϕ₋
_φ₋ = FEFunction(Vbg,ϕ₋)
end

φ₋ = AlgoimCallLevelSetFunction(_φ₋,(_φ₋))
cp₋ = compute_closest_point_projections(Vbg,φ₋,order+1,cppdegree=3)

lquad = Quadrature(algoim,φ₋,degree,phase=IN)
Ωˡ,dΩˡ,cell_to_is_liquid = TriangulationAndMeasure(Ω,lquad)

squad = Quadrature(algoim,φ₋,degree,phase=OUT)
Ωˢ,dΩˢ,cell_to_is_solid = TriangulationAndMeasure(Ω,squad)

iquad = Quadrature(algoim,φ₋,degree)
_,dΓ,cell_to_is_cut = TriangulationAndMeasure(Ω,iquad)
n_Γ = normal(φ₋,Ω) # Exterior to liquid

aggsˡ = aggregate(Ω,cell_to_is_liquid,cell_to_is_cut,IN)
aggsˢ = aggregate(Ω,cell_to_is_solid,cell_to_is_cut,OUT)

buffer[] = (Ωˡ=Ωˡ,Ωˢ=Ωˢ,dΩˡ=dΩˡ,dΩˢ=dΩˢ,
=dΓ,n_Γ=n_Γ,aggsˡ=aggsˡ,aggsˢ=aggsˢ,
φ₋=φ₋,cp₋=cp₋,t=t)
return true

end

end

reffeᵘ = ReferenceFE(lagrangian,VectorValue{2,Float64},order)
reffeˢ = ReferenceFE(lagrangian,VectorValue{2,Float64},order,space=:S)
reffeᵖ = ReferenceFE(lagrangian,Float64,order-1,space=:P)

labels = get_face_labeling(model)
add_tag_from_tags!(labels,"inlet",[7])

function update_all!(t::Real,dt::Real,disp)

update_buffer!(t,dt,disp)

Ωˡ = buffer[].Ωˡ
Ωˢ = buffer[].Ωˢ

dΩˡ = buffer[].dΩˡ
dΩˢ = buffer[].dΩˢ

= buffer[].
n_Γ = buffer[].n_Γ

aggsˡ = buffer[].aggsˡ
aggsˢ = buffer[].aggsˢ

Vˡstd = TestFESpace(Ωˡ,reffeᵘ,dirichlet_tags=["inlet"])
Vˡser = TestFESpace(Ωˡ,reffeˢ,conformity=:L2)
Qˡstd = TestFESpace(Ωˡ,reffeᵖ)

Vˢstd = TestFESpace(Ωˢ,reffeᵘ)
Vˢser = TestFESpace(Ωˢ,reffeˢ,conformity=:L2)
Qˢstd = TestFESpace(Ωˢ,reffeᵖ)

= AgFEMSpace(Vˡstd,aggsˡ,Vˡser)
= AgFEMSpace(Qˡstd,aggsˡ)
= AgFEMSpace(Vˢstd,aggsˢ,Vˢser)
= AgFEMSpace(Qˢstd,aggsˢ)
K = ConstantFESpace(model)

uᵢ(x) = VectorValue(w*(1.0-x[2]*x[2]),0.0)
= TrialFESpace(Vˡ,[uᵢ])
= TrialFESpace(Qˡ)
= TrialFESpace(Vˢ)
= TrialFESpace(Qˢ)
L = TrialFESpace(K)

Y = MultiFieldFESpace([Vˡ,Qˡ,K,Vˢ,Qˢ,K])
X = MultiFieldFESpace([Uˡ,Pˡ,L,Uˢ,Pˢ,L])

X,Y,dΩˡ,dΩˢ,Ωˡ,Ωˢ,dΓ,n_Γ

end

t₀ = 0.0
Δt = Δt₀

X,Y,dΩˡ,dΩˢ,Ωˡ,Ωˢ,dΓ,n_Γ = update_all!(t₀,Δt,VectorValue(0.0,0.0))

= CellField(νˢ/(νˡ+νˢ),Ω)
= CellField(νˡ/(νˡ+νˢ),Ω)
νᵞ = 2*νˡ*νˢ/(νˡ+νˢ)

jumpᵘ(uˡ,uˢ) =-
σ(ε,ν) = 2*ν*ε
τ(ε) = one(ε)
meanᵗ(uˡ,pˡ,νˡ,uˢ,pˢ,νˢ) =
*(σ(ε(uˡ),νˡ))-*(ε(uˡ))) +
*(σ(ε(uˢ),νˢ))-*(ε(uˢ)))

a((uˡ,pˡ,lˡ,uˢ,pˢ,lˢ),(vˡ,qˡ,kˡ,vˢ,qˢ,kˢ)) =
( 2*νˡ*(ε(uˡ)ε(vˡ)) -*(∇uˡ) - (∇vˡ)*pˡ )dΩˡ +
( 2*νˢ*(ε(uˢ)ε(vˢ)) -*(∇uˢ) - (∇vˢ)*pˢ )dΩˢ +
( pˡ*kˡ )dΩˡ + ( qˡ*lˡ )dΩˡ +
( pˢ*kˢ )dΩˢ + ( qˢ*lˢ )dΩˢ +
( (γ*νᵞ/h)*(jumpᵘ(uˡ,uˢ)jumpᵘ(vˡ,vˢ)) -
(jumpᵘ(vˡ,vˢ)(n_Γmeanᵗ(uˡ,pˡ,νˡ,uˢ,pˢ,νˢ))) -
((n_Γmeanᵗ(vˡ,qˡ,νˡ,vˢ,qˢ,νˢ))jumpᵘ(uˡ,uˢ)) )dΓ

l((vˡ,qˡ,kˡ,vˢ,qˢ,kˢ)) = 0.0

assem = SparseMatrixAssembler(SymSparseMatrixCSR{1,Float64,Int},Vector{Float64},X,Y)
op = AffineFEOperator(a,l,X,Y,assem)

A = get_matrix(op)
b = get_vector(op)
x = similar(b)
msglvl = 0
# Customizing solver for real symmetric indefinite matrices
# See https://www.intel.com/content/www/us/en/develop/documentation/onemkl-developer-reference-c/top/sparse-solver-routines/onemkl-pardiso-parallel-direct-sparse-solver-iface/pardiso-iparm-parameter.html
iparm = new_iparm()
iparm[0+1] = 1 # Use default values (0 = enabled)
iparm[1+1] = 3 # Fill-in reducing ordering for the input matrix
iparm[9+1] = 8 # Pivoting perturbation
iparm[10+1] = 1 # Scaling vectors
iparm[12+1] = 1 # Improved accuracy using (non-) symmetric weighted matching
# Note that in the analysis phase (phase=11) you must provide the numerical values
# of the matrix A in array a in case of scaling and symmetric weighted matching.
iparm[17+1] = -1 # Report the number of non-zero elements in the factors.
iparm[18+1] = -1 # Report number of floating point operations (in 10^6 floating point operations) that are necessary to factor the matrix A.
iparm[20+1] = 1 # Pivoting for symmetric indefinite matrices.
ps = PardisoSolver(GridapPardiso.MTYPE_REAL_SYMMETRIC_INDEFINITE, iparm, msglvl)
ss = symbolic_setup(ps, A)
ns = numerical_setup(ss, A)
solve!(x, ns, b)
xh = FEFunction(X,x)
uhl, phl, _, uhs, phs, _ = xh

_A = get_matrix(op)
_b = get_vector(op)
_x = get_free_dof_values(xh)
_r = _A*_x - _b
nr = norm(_r)
nb = norm(_b)
nx = norm(_x)
# @show nr, nr/nb, nr/nx
tol_warn = 1.0e-10
if nr > tol_warn && nr/nb > tol_warn && nr/nx > tol_warn
@warn "Solver not accurate"
end

# colors = color_aggregates(aggsˡ,model)
# writevtk(Ω,"res_bg_l",celldata=["aggregate"=>aggsˡ,"color"=>colors])
# writevtk(Ω,"res_bg_s",celldata=["aggregate"=>aggsˢ,"color"=>colors])
writevtk(Ωˡ,"res_l",cellfields=["uhl"=>uhl,"phl"=>phl])
writevtk(dΩˢ,"res_s",cellfields=["uhs"=>uhs,"phs"=>phs])
writevtk(dΓ,"res_gam",cellfields=["uhl"=>uhl,"uhs"=>uhs],qhulltype=convexhull)
# nh = interpolate_everywhere(n_Γ,Vˡstd)
# σn = νˡ*(ε(uhl)⋅nh) # - phl*nh
# writevtk(dΓ,"res_gam",cellfields=["uhl"=>uhl,"phl"=>phl,"sn"=>σn],qhulltype=convexhull)

X,Y,dΩˡ,dΩˢ,Ωˡ,Ωˢ,dΓ,n_Γ = update_all!(t₀+Δt,Δt,uhs)

writevtk(Ωˡ,"res_l_2")
writevtk(dΩˢ,"res_s_2")
writevtk(dΓ,"res_gam_2",qhulltype=convexhull)

end

n = 80
w = 1.0e-1
νˡ = 1.0e-1
νˢ = 1.0e+2
γ = 1.0e-1 # Scale with νˢ
γ = 1.0e-1 # Scale with νˢ
Δt = 1.0

@info "Values: n = $n, w = $w, νˡ = $νˡ, νˢ = $νˢ, γ = "

main(n,w,νˡ,νˢ,γ)
dynamic(n,w,νˡ,νˢ,γ,Δt)

end # module

0 comments on commit 221af49

Please sign in to comment.