002: check edge reaction
module Example002_EdgeReaction
using Printf
using VoronoiFVM
using ExtendableGrids
using ExtendableSparse
using GridVisualize
using LinearAlgebra
using SimplexGridFactory
using Triangulate
function main(; nref = 0, dim = 2, Plotter = nothing, verbose = "and", case = :compare_max, assembly = :edgewise)
X = 0:(0.25 * 2.0^-nref):1
i0::Int = 0
i1::Int = 0
if dim == 1
grid = simplexgrid(X)
i0 = 1
i1 = 2
elseif dim == 2
b = SimplexGridBuilder(; Generator = Triangulate)
p00 = point!(b, 0, 0)
p10 = point!(b, 1, 0)
p11 = point!(b, 1, 1)
p01 = point!(b, 0, 1)
pxx = point!(b, 0.3, 0.3)
facetregion!(b, 1)
facet!(b, p00, p10)
facetregion!(b, 2)
facet!(b, p10, p11)
facetregion!(b, 3)
facet!(b, p11, p01)
facetregion!(b, 4)
facet!(b, p01, p00)
grid = simplexgrid(b; maxvolume = 0.01 * 4.0^(-nref))
i0 = 1
i1 = 3
elseif dim == 3
grid = simplexgrid(X, X, X)
i0 = 5
i1 = 6
end
function storage!(y, u, node, data)
y[1] = u[1]
end
function flux!(y, u, edge, data)
y[1] = u[1, 1] - u[1, 2]
end
Three ways to give a constant reaction term. As a consequence, these need to yield the same solution. 1: classical node reaction, multiplied by control volume size
function reaction!(y, u, node, data)
y[1] = -1
end
2: Edge reaction. Here we give it as a constant, and wie need to turn the multiplication with σ/h into a multiplication with the half diamond volume.
Half diamond volume calculation /|
/ |
/ |s
–––- h A=sh/2d . Our formfactor: σ=s/h => A=σh^2
- make transfer area to volume
τ=1/h v= sh/2d = σh^2/2d
function edgereaction!(y, u, edge, data)
h = meas(edge)
y[1] = -1 * h^2 / (2 * dim)
end
3: "Joule heat:" |∇ϕ|^2=1 after 3.17 in Bradji/Herbin Here we divide twice by "h" to get the constant squared gradient. The multiplication with dim in 3.17 compensates the division we had before
ϕ = grid[Coordinates][1, :]
function edgereaction2!(y, u, edge, data)
ϕK = ϕ[edge.node[1]]
ϕL = ϕ[edge.node[2]]
y[1] = -(ϕK - ϕL) * (ϕK - ϕL) / 2
end
if case == :compare_max
function bcondition!(y, u, node, data)
boundary_dirichlet!(y, u, node; species = 1, region = 1, value = 0)
boundary_dirichlet!(y, u, node; species = 1, region = 2, value = 0)
boundary_dirichlet!(y, u, node; species = 1, region = 3, value = 0)
boundary_dirichlet!(y, u, node; species = 1, region = 4, value = 0)
boundary_dirichlet!(y, u, node; species = 1, region = 5, value = 0)
boundary_dirichlet!(y, u, node; species = 1, region = 6, value = 0)
end
sys_noderea = VoronoiFVM.System(grid; bcondition = bcondition!, flux = flux!,
reaction = reaction!, storage = storage!,
species = [1], is_linear = true, assembly)
sys_edgerea = VoronoiFVM.System(grid; bcondition = bcondition!, flux = flux!,
edgereaction = edgereaction!, storage = storage!,
species = [1], is_linear = true, assembly)
sys_edgerea2 = VoronoiFVM.System(grid; bcondition = bcondition!, flux = flux!,
edgereaction = edgereaction2!, storage = storage!,
species = [1], is_linear = true, assembly)
sol_noderea = solve(sys_noderea; verbose)
sol_edgerea = solve(sys_edgerea; verbose)
sol_edgerea2 = solve(sys_edgerea2; verbose)
vis = GridVisualizer(; Plotter, layout = (2, 2))
scalarplot!(vis[1, 1], grid, sol_noderea[1, :]; title = "node reaction",
colormap = :hot)
scalarplot!(vis[2, 1], grid, sol_edgerea[1, :]; title = "edgerea1", colormap = :hot)
scalarplot!(vis[1, 2], grid, sol_edgerea2[1, :]; title = "edgerea2",
colormap = :hot)
reveal(vis)
return maximum.([sol_noderea, sol_edgerea, sol_edgerea2])
end
if case == :compare_flux
function bcondition2!(y, u, node, data)
boundary_dirichlet!(y, u, node; species = 1, region = i1, value = 0)
end
sys2_noderea = VoronoiFVM.System(grid; bcondition = bcondition2!, flux = flux!,
reaction = reaction!, storage = storage!,
species = [1], is_linear = true)
sys2_edgerea = VoronoiFVM.System(grid; bcondition = bcondition2!, flux = flux!,
edgereaction = edgereaction!, storage = storage!,
species = [1], is_linear = true)
sys2_edgerea2 = VoronoiFVM.System(grid; bcondition = bcondition2!, flux = flux!,
edgereaction = edgereaction2!, storage = storage!,
species = [1], is_linear = true)
sol2_noderea = solve(sys2_noderea; verbose)
sol2_edgerea = solve(sys2_edgerea; verbose)
sol2_edgerea2 = solve(sys2_edgerea2; verbose)
tfac2_noderea = TestFunctionFactory(sys2_noderea)
tfc2_noderea = testfunction(tfac2_noderea, [i0], [i1])
tfac2_edgerea = TestFunctionFactory(sys2_edgerea)
tfc2_edgerea = testfunction(tfac2_edgerea, [i0], [i1])
tfac2_edgerea2 = TestFunctionFactory(sys2_edgerea2)
tfc2_edgerea2 = testfunction(tfac2_edgerea2, [i0], [i1])
vis = GridVisualizer(; Plotter, layout = (2, 2))
scalarplot!(vis[1, 1], grid, sol2_noderea[1, :]; title = "node reaction",
colormap = :hot)
scalarplot!(vis[2, 1], grid, sol2_edgerea[1, :]; title = "edgerea1",
colormap = :hot)
scalarplot!(vis[1, 2], grid, sol2_edgerea2[1, :]; title = "edgerea2",
colormap = :hot)
reveal(vis)
I_noderea = integrate(sys2_noderea, tfc2_noderea, sol2_noderea)
I_edgerea = integrate(sys2_edgerea, tfc2_edgerea, sol2_edgerea)
I_edgerea2 = integrate(sys2_edgerea2, tfc2_edgerea2, sol2_edgerea2)
return I_noderea, I_edgerea, I_edgerea2
end
end
using Test
function runtests()
res = fill(false, 3)
for dim = 1:3
result_max = main(; case = :compare_max, assembly = :cellwise)
result_flux = main(; case = :compare_flux, assembly = :cellwise)
res[dim] = isapprox(result_max[1], result_max[2]; atol = 1.0e-6) &&
isapprox(result_max[1], result_max[3]; atol = 1.0e-3) &&
isapprox(result_flux[1], result_flux[2]; atol = 1.0e-10) &&
isapprox(result_flux[1], result_flux[3]; atol = 1.0e-10)
end
res1 = all(a -> a, res)
res = fill(false, 3)
for dim = 1:3
result_max = main(; case = :compare_max, assembly = :edgwise)
result_flux = main(; case = :compare_flux, assembly = :edgwise)
res[dim] = isapprox(result_max[1], result_max[2]; atol = 1.0e-6) &&
isapprox(result_max[1], result_max[3]; atol = 1.0e-3) &&
isapprox(result_flux[1], result_flux[2]; atol = 1.0e-10) &&
isapprox(result_flux[1], result_flux[3]; atol = 1.0e-10)
end
res2 = all(a -> a, res)
@test res1 && res2
end
end
This page was generated using Literate.jl.