Skip to content

Commit

Permalink
new Example207 (advection equation + upwind DG); some small improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
chmerdon committed Feb 12, 2024
1 parent a2b6fbc commit f1e5ba4
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 16 deletions.
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function make_all(; with_examples::Bool = true, run_examples::Bool = true, run_n
"Example204_LaplaceEVProblem.jl",
"Example205_HeatEquation.jl",
"Example206_CoupledSubGridProblems.jl",
"Example207_AdvectionUpwindDG.jl",
"Example210_LshapeAdaptivePoissonProblem.jl",
"Example211_LshapeAdaptiveEQPoissonProblem.jl",
"Example220_ReactionConvectionDiffusion.jl",
Expand Down
15 changes: 7 additions & 8 deletions examples/Example206_CoupledSubGridProblems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,15 @@ end

generateplots = default_generateplots(Example206_CoupledSubGridProblems, "example206.svg") #hide


function jump_l2norm!(result, u, qpinfo)
result[1] = (u[1] - u[2])^2
end
function jump_l2norm!(result, u, qpinfo) #hide
result[1] = (u[1] - u[2])^2 #hide
end #hide
function runtests() #hide
## test if jump at interface vanishes for large penalty
## test if jump at interface vanishes for large penalty #hide
sol, plt = main(; τ = 1e9, nrefs = 2, order = 2) #hide
jump_integrator = ItemIntegrator(jump_l2norm!, [id(1), id(2)]; entities = ON_BFACES, regions = [5], resultdim = 1, quadorder = 4)
jump_error = sqrt(sum(evaluate(jump_integrator, sol)))
@info "||[u_1 - u_2]|| = $(jump_error)"
jump_integrator = ItemIntegrator(jump_l2norm!, [id(1), id(2)]; entities = ON_BFACES, regions = [5], resultdim = 1, quadorder = 4) #hide
jump_error = sqrt(sum(evaluate(jump_integrator, sol))) #hide
@info "||[u_1 - u_2]|| = $(jump_error)" #hide
@test jump_error < 1e-8 #hide
end #hide
end #module
182 changes: 182 additions & 0 deletions examples/Example207_AdvectionUpwindDG.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#=
# 207 : Advection Upwind-DG
([source code](@__SOURCE_URL__))
This example computes the solution ``u`` of the two-dimensional advection equation
```math
\begin{aligned}
\mathrm{div} (\beta u) & = 0 \quad \text{in } \Omega
\end{aligned}
```
with some given (divergence-free) advection field ``\beta`` and inhomogeneous
Dirichlet boundary conditions at the inflow boundary
(where ``\beta \cdot n < 0`` with ``n`` being the outer normal vector).
In the example below the field ``\beta(x,y) = (-y, x)`` and the inflow data
```math
u(x,y) =
\begin{cases}
1 & \text{for } x \in [0,r] \& y = 0,\\
0 & \text{for } x \in (r,1] \& y = 0,\\
0 & \text{for } x = 1 \& y \in [0,1].
\end{cases}
```
is employed. The expected solution is a piecewise constant function
that assumes the value one in the circle of radius ``r`` and zero elsewhere.
Moreover, the upwind discontinuous Galerkin method for arbitrary polynomial degree
is used for the discretization of the problem, but the continuous Galerkin
method can be switched on with dg = false for comparison. For piecewise constants
the DG method satisfies the maximum principle.
The grid (which is heavily refined along the interface of the circle) and the
computed solution looks like this:
![](example207.svg)
=#

module Example207_AdvectionUpwindDG

using ExtendableFEM
using ExtendableGrids
using Symbolics
using LinearAlgebra
using SimplexGridFactory
using Triangulate
using Test #hide

## wind = advection field β
function β!(result, qpinfo)
x = qpinfo.x
result[1] = - x[2]
result[2] = x[1]
end

## exact solution
function exact_u!(result, qpinfo)
x = qpinfo.x
r = qpinfo.params[1]
result[1] = sqrt(x[1]^2 + x[2]^2) <= r ? 1 : 0
end

## integrand of the advection bilinearform
function advection_kernel!(result, input, qpinfo)
β!(result, qpinfo) # evaluate wind β
result .*= input[1] # multiply with u_h
end

function outflow_kernel!(xgrid)
facenormals = xgrid[FaceNormals]
beta = zeros(Float64, 2)
function closure(result, input, qpinfo)
face = qpinfo.item
β!(beta, qpinfo)
result[1] = dot(beta, view(facenormals, :, face)) * input[1]
end
end

function upwind_kernel!(xgrid)
facenormals = xgrid[FaceNormals]
beta = zeros(Float64, 2)
function closure(result, input, qpinfo)
face = qpinfo.item
β!(beta, qpinfo)
result[1] = dot(beta, view(facenormals, :, face))
if result[1] > 0 ## wind blows this -> other
result[1] *= input[1] # upwind value = this
else ## wind blows this <- other
result[1] *= input[2] # upwind value = other
end
end
end

## prepare error calculation
function exact_error!(result, u, qpinfo)
exact_u!(result, qpinfo)
result[1] = (result[1] - u[1])^2
end

function main(; nref = 4, order = 0, r = 0.5, dg = true, Plotter = nothing, kwargs...)

## grid
xgrid = make_grid(nref, r)

## problem description
PD = ProblemDescription("advection equation")
u = Unknown("u"; name = "species")
assign_unknown!(PD, u)

## advection operator
assign_operator!(PD, BilinearOperator(advection_kernel!, [grad(u)], [id(u)]; factor = -1, bonus_quadorder = 1, kwargs...))
if dg
assign_operator!(PD, BilinearOperatorDG(upwind_kernel!(xgrid), [jump(id(u))], [this(id(u)), other(id(u))]; entities = ON_IFACES, bonus_quadorder = 1, kwargs...))
end

## outflow boundary (regions [3,4]) and inflow boundary (regions [5,6])
assign_operator!(PD, BilinearOperator(outflow_kernel!(xgrid), [id(u)]; entities = ON_BFACES, regions = [3,4]))
assign_operator!(PD, InterpolateBoundaryData(u, exact_u!; regions = [5,6], params = [r], kwargs...))
assign_operator!(PD, HomogeneousBoundaryData(u; regions = [1,2], kwargs...))

## solve
FES = FESpace{order == 0 ? L2P0{1} : H1Pk{1, 2, order}}(xgrid; broken = dg)
sol = solve(PD, FES; kwargs...)

## calculate L2 error and min/max value
ErrorIntegrator = ItemIntegrator(exact_error!, [id(u)]; quadorder = 2 * order, params = [r], kwargs...)
L2error = sqrt(sum(view(evaluate(ErrorIntegrator, sol), 1, :)))
@info "L2 error = $L2error"
@info "extrema = $(extrema(sol.entries))"

## plot
plt = plot([grid(u), id(u)], sol; Plotter = Plotter)

return sol, plt
end

## grid generator script using SimplexGridBuilder/Triangulate
function make_grid(nref = 4, radius = 0.5)
builder = SimplexGridBuilder(Generator = Triangulate)

## define outer boundary nodes and regions
p1 = point!(builder, 0, 0)
p12 = point!(builder, radius, 0)
p2 = point!(builder, 1, 0)
p3 = point!(builder, 1, 1)
p4 = point!(builder, 0, 1)
p41 = point!(builder, 0, radius)

facetregion!(builder, 5)
facet!(builder, p1, p12)
facetregion!(builder, 1)
facet!(builder, p12, p2)
facetregion!(builder, 2)
facet!(builder, p2, p3)
facetregion!(builder, 3)
facet!(builder, p3, p4)
facetregion!(builder, 4)
facet!(builder, p4, p41)
facetregion!(builder, 6)
facet!(builder, p41, p1)

## add interior interface (quarter circle)
n = 4^(nref+1)
points = [point!(builder, radius * sin(t), radius * cos(t)) for t in range(0, π/2, length = n)]
facetregion!(builder, 7)
for i 2:n-2
facet!(builder, points[i], points[i+1])
end
facet!(builder, p41, points[1])
facet!(builder, points[end], p12)

## generate
simplexgrid(builder, maxvolume = 1)
end

generateplots = default_generateplots(Example207_AdvectionUpwindDG, "example207.svg") #hide
function runtests() #hide
## test if P0-DG solution stays within bounds #hide
sol, ~ = main(; order = 0, nrefs = 2) #hide
@test norm(extrema(sol.entries) .- (0,1)) < 1e-13 #hide
end #hide
end # module
12 changes: 6 additions & 6 deletions examples/Example240_SVRTEnrichment.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function prepare_data(; μ = 1)
@variables x y

## stream function ξ
ξ = -sin(2 * pi * x) * cos(2 * pi * y) / (2 * pi)
ξ = -sin(2 * pi * x) * cos(2 * pi * y)

## velocity u = curl ξ
∇ξ = Symbolics.gradient(ξ, [x, y])
Expand Down Expand Up @@ -120,7 +120,7 @@ function kernel_stokes_standard!(result, u_ops, qpinfo)
return nothing
end

function main(; nrefs = 5, μ = 1, order = 2, Plotter = nothing, enrich = true, reduce = true, time = 0.5, bonus_quadorder = 5, kwargs...)
function main(; nrefs = 5, μ = 1, α = 1, order = 2, Plotter = nothing, enrich = true, reduce = true, time = 0.5, bonus_quadorder = 5, kwargs...)

## prepare problem data
f_eval, u_eval, ∇u_eval, p_eval = prepare_data(; μ = μ)
Expand Down Expand Up @@ -152,7 +152,7 @@ function main(; nrefs = 5, μ = 1, order = 2, Plotter = nothing, enrich = true,
result .= result .^ 2
end
ErrorIntegratorExact = ItemIntegrator(exact_error!, [id(u), grad(u)]; quadorder = 2 * (order + 1), kwargs...)
ErrorIntegratorPressure = ItemIntegrator(exact_error_p!, [id(pfull)]; quadorder = 2 * (order + 1), kwargs...)
ErrorIntegratorPressure = ItemIntegrator(exact_error_p!, [order == 1 ? id(p0) : id(pfull)]; quadorder = 2 * (order + 1), kwargs...)
L2NormIntegratorE = L2NormIntegrator([id(uR)]; quadorder = 2 * order)
function kernel_div!(result, u, qpinfo)
result .= sum(u) .^ 2
Expand Down Expand Up @@ -203,7 +203,7 @@ function main(; nrefs = 5, μ = 1, order = 2, Plotter = nothing, enrich = true,
AR = FEMatrix(FES_enrich)
BR = FEMatrix(FES[p], FES_enrich)
bR = FEVector(FES_enrich)
assemble!(AR, BilinearOperator([div(1)]; lump = true, factor = μ, kwargs...))
assemble!(AR, BilinearOperator([div(1)]; lump = true, factor = α*μ, kwargs...))
for bface in xgrid[BFaceFaces]
AR.entries[bface, bface] = 1e60
end
Expand Down Expand Up @@ -454,7 +454,7 @@ end
generateplots = default_generateplots(Example240_SVRTEnrichment, "example240.svg") #hide
function runtests(;) #hide
Results, plt = main(; nrefs = 2) #hide
@test Results[end,1] 0.015279978191548282 #hide
@test Results[end,5] < 2e-10 #hide
@test Results[end,1] 0.09600693353585522 #hide
@test Results[end,5] < 1e-9 #hide
end #hide
end # module
1 change: 1 addition & 0 deletions src/common_operators/homogeneousdata_operator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ function assemble!(O::HomogeneousData{UT, AT}, FES = O.FES; offset = 0, kwargs..
else
for item 1:nitems
if itemregions[item] in regions
ndofs4item = num_targets(itemdofs, item)
for k 1:ndofs4item
dof = itemdofs[k, item]
push!(bdofs, dof + offset)
Expand Down
2 changes: 0 additions & 2 deletions src/common_operators/item_integrator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ function build_assembler!(O::ItemIntegrator{Tv}, FE_args::Array{<:FEVectorBlock,
visit_region .= true
end

## prepare parameters

## prepare operator infos
op_lengths_args = [size(O.BE_args[1][j].cvals, 1) for j 1:nargs]

Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function run_examples()
"Example203_PoissonProblemDG.jl",
#"Example204_LaplaceEVProblem.jl",
"Example205_HeatEquation.jl",
"Example207_AdvectionUpwindDG.jl",
"Example210_LshapeAdaptivePoissonProblem.jl",
"Example211_LshapeAdaptiveEQPoissonProblem.jl",
"Example220_ReactionConvectionDiffusion.jl",
Expand Down

0 comments on commit f1e5ba4

Please sign in to comment.