Flux reconstruction and visualization for the Laplace operator
We demonstrate the reconstruction of the gradient vector field from the solution of the Laplace operator and its visualization.
begin
import Pkg as _Pkg
haskey(ENV, "PLUTO_PROJECT") && _Pkg.activate(ENV["PLUTO_PROJECT"])
using Revise
using Test
using SimplexGridFactory, Triangulate, ExtendableGrids, VoronoiFVM
using PlutoUI, GridVisualize
using CairoMakie
CairoMakie.activate!(; type = "png", visible = false)
GridVisualize.default_plotter!(CairoMakie)
end;
Grid
Define a "Swiss cheese domain" with punched-out holes, where each hole boundary corresponds to a different boundary condition.
function swiss_cheese_2d()
function circlehole!(builder, center, radius; n = 20)
points = [point!(builder, center[1] + radius * sin(t), center[2] + radius * cos(t))
for t in range(0, 2π; length = n)]
for i = 1:(n - 1)
facet!(builder, points[i], points[i + 1])
end
facet!(builder, points[end], points[1])
holepoint!(builder, center)
end
builder = SimplexGridBuilder(; Generator = Triangulate)
cellregion!(builder, 1)
maxvolume!(builder, 0.1)
regionpoint!(builder, 0.1, 0.1)
p1 = point!(builder, 0, 0)
p2 = point!(builder, 10, 0)
p3 = point!(builder, 10, 10)
p4 = point!(builder, 0, 10)
facetregion!(builder, 1)
facet!(builder, p1, p2)
facet!(builder, p2, p3)
facet!(builder, p3, p4)
facet!(builder, p4, p1)
holes = [1.0 2.0
8.0 9.0
2.0 8.0
8.0 4.0
9.0 1.0
3.0 4.0
4.0 6.0
7.0 9.0
4.0 7.0
7.0 5.0
2.0 1.0
4.0 1.0
4.0 8.0
3.0 6.0
4.0 9.0
6.0 9.0
3.0 5.0
1.0 4.0]'
radii = [
0.15,
0.15,
0.1,
0.35,
0.2,
0.3,
0.1,
0.4,
0.1,
0.4,
0.2,
0.2,
0.2,
0.35,
0.15,
0.25,
0.15,
0.25,
]
for i = 1:length(radii)
facetregion!(builder, i + 1)
circlehole!(builder, holes[:, i], radii[i])
end
simplexgrid(builder)
end
swiss_cheese_2d (generic function with 1 method)
grid = swiss_cheese_2d()
ExtendableGrids.ExtendableGrid{Float64, Int32} dim = 2 nnodes = 1434 ncells = 2443 nbfaces = 459
System + solution
mutable struct Params
val11::Float64
end
params = Params(5)
Params(5.0)
Simple flux function for Laplace operator
flux(y, u, edge, data) = y[1] = u[1, 1] - u[1, 2];
At hole #11, the value will be bound to a slider defined below
function bc(y, u, bnode, data)
boundary_dirichlet!(y, u, bnode; region = 2, value = 10.0)
boundary_dirichlet!(y, u, bnode; region = 3, value = 0.0)
boundary_dirichlet!(y, u, bnode; region = 11, value = data.val11)
end
bc (generic function with 1 method)
Define a finite volume system with Dirichlet boundary conditions at some of the holes
system = VoronoiFVM.System(grid; flux = flux, species = 1, bcondition = bc, data = params)
VoronoiFVM.System{Float64, Float64, Int32, Int64, Matrix{Int32}}( grid = ExtendableGrids.ExtendableGrid{Float64, Int32}(dim=2, nnodes=1434, ncells=2443, nbfaces=459), physics = Physics(data=Main.var"workspace#3".Params, flux=flux, storage=default_storage, breaction=bc, ), num_species = 1)
Solve, and trigger solution upon boundary value change
begin
params.val11 = val11
sol = solve(system)
end;
@test params.val11 != 5.0 || isapprox(sum(sol), 7842.2173682050525; rtol = 1.0e-12)
Test Passed
Flux reconstruction
Reconstruct the node flux. It is a \(d\times n_{spec}\times n_{nodes}\) tensor. nf[:,ispec,:]
then is a vector function representing the flux density of species ispec
in each node of the domain. This readily can be fed into GridVisualize.vectorplot
.
The reconstruction is based on the "magic formula" R. Eymard, T. Gallouet, R. Herbin, IMA Journal of Numerical Analysis (2006) 26, 326−353 (Arxive version), Lemma 2.4 .
nf = nodeflux(system, sol)
2×1×1434 Array{Float64, 3}: [:, :, 1] = 0.05468367090633706 -0.05468367090633706 [:, :, 2] = 0.01852257911924369 0.014818063295393813 [:, :, 3] = 0.0 0.0 ;;; … [:, :, 1432] = 0.020523328431052094 0.036034112502081016 [:, :, 1433] = 0.028906869669800477 0.012529162794698063 [:, :, 1434] = 0.03545781788403497 0.0342143068249023
@test params.val11 != 5.0 || isapprox(sum(nf), 978.000534849034; rtol = 1.0e-14)
Test Passed
vis = GridVisualizer(; dim = 2, resolution = (400, 400))
GridVisualizer(Plotter=CairoMakie)
\(v_{11}:\)
Joint plot of solution and flux reconstruction
begin
scalarplot!(vis, grid, sol[1, :]; levels = 9, colormap = :summer, clear = true)
vectorplot!(vis, grid, nf[:, 1, :]; clear = false, vscale = 1.5)
reveal(vis)
end
The 1D case
src(x) = exp(-x^2 / 0.01)
src (generic function with 1 method)
source1d(y, node, data) = y[1] = src(node[1])
source1d (generic function with 1 method)
flux1d(y, u, edge, data) = y[1] = u[1, 1]^2 - u[1, 2]^2
flux1d (generic function with 1 method)
function bc1d(y, u, bnode, data)
boundary_dirichlet!(y, u, bnode; region = 1, value = 0.01)
boundary_dirichlet!(y, u, bnode; region = 2, value = 0.01)
end
bc1d (generic function with 1 method)
grid1d = simplexgrid(-1:0.01:1)
ExtendableGrids.ExtendableGrid{Float64, Int32} dim = 1 nnodes = 201 ncells = 200 nbfaces = 2
sys1d = VoronoiFVM.System(grid1d;
flux = flux1d,
bcondition = bc1d,
source = source1d,
species = [1],)
VoronoiFVM.System{Float64, Float64, Int32, Int64, Matrix{Int32}}( grid = ExtendableGrids.ExtendableGrid{Float64, Int32}(dim=1, nnodes=201, ncells=200, nbfaces=2), physics = Physics(flux=flux1d, storage=default_storage, source=source1d, breaction=bc1d, ), num_species = 1)
sol1d = solve(sys1d; inival = 0.1)
1×201 VoronoiFVM.DenseSolutionArray{Float64, 2}: 0.01 0.0314043 0.0432719 0.0525231 … 0.0525231 0.0432719 0.0314043 0.01
nf1d = nodeflux(sys1d, sol1d)
1×1×201 Array{Float64, 3}: [:, :, 1] = -0.08862269254527583 [:, :, 2] = -0.08862269254527581 [:, :, 3] = -0.08862269254527581 ;;; … [:, :, 199] = 0.08862269254527581 [:, :, 200] = 0.08862269254527581 [:, :, 201] = 0.08862269254527583
let
vis1d = GridVisualizer(; dim = 1, resolution = (500, 250), legend = :lt)
scalarplot!(vis1d, grid1d, map(src, grid1d); label = "rhs", color = :blue)
scalarplot!(vis1d, grid1d, sol1d[1, :]; label = "solution", color = :red, clear = false)
vectorplot!(vis1d, grid1d, nf1d[:, 1, :]; label = "flux", clear = false, color = :green)
reveal(vis1d)
end
@test nf1d[1, 1, 101] ≈ 0.0
Test Passed
@test nf1d[1, 1, 1] ≈ -nf1d[1, 1, end]
Test Passed
Built with Julia 1.11.1 and
CairoMakie 0.12.16ExtendableGrids 1.9.2
GridVisualize 1.7.0
Pkg 1.11.0
PlutoUI 0.7.60
Revise 3.5.18
SimplexGridFactory 2.2.1
Test 1.11.0
Triangulate 2.3.4
VoronoiFVM 1.25.1