Skip to content

Commit 5353c7d

Browse files
committed
Final drivers
1 parent 76e67e5 commit 5353c7d

3 files changed

Lines changed: 178 additions & 141 deletions

File tree

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
module DarcyBGPflux
2+
# Darcy problem: BGP stabilisation with flux boundary conditions (pure pressure trace).
3+
# A Lagrange multiplier fixes the mean pressure to close the system.
4+
#
5+
# Ref: Badia, Boschman, Martín, Nilsson, Ruiz-Baier, Zahedi (2026)
6+
# "Divergence-free unfitted finite element discretisations for the Darcy problem"
7+
# arXiv:2603.26212
8+
9+
using Test
10+
using Gridap
11+
using GridapEmbedded
12+
using Gridap.Geometry, Gridap.Arrays
13+
using Gridap.FESpaces, Gridap.CellData
14+
15+
function get_aggregates(cutgeo)
16+
geo = get_geometry(cutgeo)
17+
strategy = AggregateAllCutCells()
18+
aggregates = aggregate(strategy,cutgeo,geo)
19+
return Table(filter(agg -> length(agg) > 1, inverse_table(aggregates)))
20+
end
21+
22+
function projection_operator(ptopo, V, W, Ω, dΩ)
23+
Π(u,Ω) = change_domain(u,Ω,DomainStyle(u))
24+
mass(u,v) = (uΠ(v,Ω))dΩ
25+
P = LocalOperator(
26+
LocalSolveMap(), ptopo, W, V, mass, mass
27+
)
28+
return P
29+
end
30+
31+
function div_projection_operator(ptopo, V, W, Ω, dΩ)
32+
Π(u,Ω) = change_domain(u,Ω,DomainStyle(u))
33+
lhs(u,v) = (uΠ(v,Ω))dΩ
34+
rhs(u,v) = ((∇u)Π(v,Ω))dΩ
35+
P = LocalOperator(
36+
LocalSolveMap(), ptopo, W, V, lhs, rhs
37+
)
38+
return P
39+
end
40+
41+
function generate_mesh(n,R=0.4,x0=0.835)
42+
geo1 = disk(R;x0=Point(0.5,0.5),name="disk")
43+
geo2 = plane(x0=Point(x0,0.5),v=Point(1.0,0.0),name="plane")
44+
geo = intersect(geo1,geo2,name="domain")
45+
46+
bgmodel = CartesianDiscreteModel((0,1,0,1),(n,n))
47+
cutgeo = cut(bgmodel,geo)
48+
return cutgeo
49+
end
50+
51+
function driver(n,order,u_exact,p_exact,η=1.0=10.0=1.0)
52+
cutgeo = generate_mesh(n)
53+
bgmodel = get_background_model(cutgeo)
54+
qdegree = 2*(order+1)
55+
56+
Ω_ac = Triangulation(cutgeo,ACTIVE)
57+
V = FESpace(Ω_ac,ReferenceFE(raviart_thomas,Float64,order); conformity=:Hdiv)
58+
Q = FESpace(Ω_ac,ReferenceFE(lagrangian,Float64,order); conformity=:L2)
59+
Λ = ConstantFESpace(Ω_ac)
60+
X = MultiFieldFESpace([V,Q,Λ])
61+
62+
ptopo = PatchTopology(get_grid_topology(bgmodel), get_aggregates(cutgeo))
63+
Ωp = PatchTriangulation(bgmodel, ptopo)
64+
65+
Ω = Triangulation(cutgeo,PHYSICAL)
66+
Γu = EmbeddedBoundary(cutgeo)
67+
68+
= Measure(Ω, qdegree)
69+
dΩp = Measure(Ωp, qdegree)
70+
dΓu = Measure(Γu, 2*qdegree)
71+
72+
Wd = FESpaces.PatchFESpace(bgmodel,Ωp,Float64,order;space=:RT)
73+
Πd = projection_operator(ptopo, V, Wd, Ωp, dΩp)
74+
W0 = FESpaces.PatchFESpace(bgmodel,Ωp,Float64,order;space=:Q)
75+
Π0 = projection_operator(ptopo, Q, W0, Ωp, dΩp)
76+
Π0div = div_projection_operator(ptopo, V, W0, Ωp, dΩp)
77+
78+
f(x) = η*u_exact(x) + (p_exact)(x)
79+
g(x) = -(∇u_exact)(x)
80+
81+
h = γ/n
82+
n_Γu = get_normal_vector(Γu)
83+
a(u,v) = *(uv))dΩ + (h*(un_Γu)*(vn_Γu))dΓu
84+
b(u,q) = (-(∇u)*q)dΩ
85+
btilde(u,q) = b(u,q) + ((un_Γu)*q)dΓu
86+
c(λ,q) = *q)dΩ
87+
l((v,q,μ)) = (vf + gq)dΩ + (h*(vn_Γu)(u_exactn_Γu))dΓu + c(μ,p_exact)
88+
89+
sd(u,v) = *(uv))dΩp
90+
s0(p,q) = *(p*q))dΩp
91+
92+
function weakform(x,y)
93+
u, p, λ = x
94+
v, q, μ = y
95+
Πu, Πv = Πd(u), Πd(v)
96+
Πp, Πq = Π0(p), Π0(q)
97+
divu, divv =u, ∇v
98+
Πdivu, Πdivv = Π0div(u), Π0div(v)
99+
Xp = FESpaces.PatchFESpace(X,ptopo)
100+
data = FESpaces.collect_and_merge_cell_matrix_and_vector(
101+
(X, X , a(u,v) + btilde(v,p) + b(u,q) + c(λ,q) + c(μ,p) + sd(u,v) - s0(divu,q) - s0(divv,p), l(y)),
102+
(X, Xp , s0(divu,Πq) + s0(Πdivv,p) - sd(u,Πv), DomainContribution()),
103+
(Xp, X , s0(Πdivu,q) + s0(divv,Πp) - sd(Πu,v), DomainContribution()),
104+
(Xp, Xp, sd(Πu,Πv) - s0(Πdivu,Πq) - s0(Πdivv,Πp), DomainContribution()),
105+
)
106+
assem = SparseMatrixAssembler(X,X)
107+
A, B = assemble_matrix_and_vector(assem,data)
108+
return AffineFEOperator(X,X,A,B)
109+
end
110+
111+
op = weakform(get_trial_fe_basis(X),get_fe_basis(X))
112+
uh, ph, λh = solve(op)
113+
114+
eu = uh-u_exact
115+
ep = ph-p_exact
116+
l2_err_u = sqrt(sum(( eu eu )dΩ))
117+
l2_err_p = sqrt(sum(( ep ep )dΩ))
118+
119+
return cutgeo, uh, ph, l2_err_u, l2_err_p
120+
end
121+
122+
function convergence(ns,order,u_exact,p_exact)
123+
l2_u = zeros(Float64,length(ns))
124+
l2_p = zeros(Float64,length(ns))
125+
for (i,n) in enumerate(ns)
126+
_, _, _, l2_u[i], l2_p[i] = driver(n,order,u_exact,p_exact)
127+
end
128+
slope_u = log.(l2_u[1:end-1]./l2_u[2:end]) ./ log.(ns[2:end]./ns[1:end-1])
129+
slope_p = log.(l2_p[1:end-1]./l2_p[2:end]) ./ log.(ns[2:end]./ns[1:end-1])
130+
return l2_u, l2_p, slope_u, slope_p
131+
end
132+
133+
# Manufactured solution
134+
u_exact(x) = VectorValue(x[1], -x[2])
135+
p_exact(x) = x[1] + x[2]
136+
cutgeo, uh, ph, l2_err_u, l2_err_p = driver(8,1,u_exact,p_exact)
137+
@test l2_err_u < 1.e-10
138+
@test l2_err_p < 1.e-10
139+
140+
u_conv(x) = VectorValue(x[1] + sin*x[2]), -x[2] + sin*x[1]))
141+
p_conv(x) = sin*x[1]) - sin*x[2])
142+
l2_u, l2_p, su, sp = convergence([8,16,32,64],1,u_conv,p_conv)
143+
144+
writevtk(
145+
Ω, "darcy_BGP_flux"; append=false,
146+
cellfields=[
147+
"uh"=>uh,"ph"=>ph,"u_exact"=>u_exact,"p_exact"=>p_exact,
148+
"eu"=>uh-u_exact,"ep"=>ph-p_exact
149+
],
150+
)
151+
152+
cell_to_agg = flatten_partition(get_aggregates(cutgeo),num_cells(bgmodel))
153+
writevtk(
154+
Triangulation(bgmodel), "aggregates"; append=false,
155+
celldata = ["agg"=>cell_to_agg]
156+
)
157+
158+
function normal_at_centroid(Γ)
159+
n = get_normal_vector(Γ)
160+
x = CellPoint(map(mean,get_cell_coordinates(Γ)),Γ,PhysicalDomain())
161+
return n(x)
162+
end
163+
164+
Γu = EmbeddedBoundary(cutgeo)
165+
writevtk(
166+
Γu, "boundary_u"; append=false, celldata=["n"=>normal_at_centroid(Γu)]
167+
)
168+
169+
end # module
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
module DarcyBGPmixed
2+
# Darcy problem: BGP stabilisation with mixed boundary conditions (flux + pressure traces
3+
# imposed on different parts of the unfitted boundary).
4+
#
5+
# Ref: Badia, Boschman, Martín, Nilsson, Ruiz-Baier, Zahedi (2026)
6+
# "Divergence-free unfitted finite element discretisations for the Darcy problem"
7+
# arXiv:2603.26212
18

29
using Test
310
using Gridap
@@ -163,3 +170,5 @@ writevtk(
163170
writevtk(
164171
Γp, "boundary_p"; append=false, celldata=["n"=>normal_at_centroid(Γp)]
165172
)
173+
174+
end # module

test/darcy_BGP_flux.jl

Lines changed: 0 additions & 141 deletions
This file was deleted.

0 commit comments

Comments
 (0)