Skip to content

Commit 642c969

Browse files
committed
Improved new tutorials
1 parent 3d4f777 commit 642c969

6 files changed

Lines changed: 204 additions & 162 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ GridapDistributed = "0.4"
4141
GridapGmsh = "0.7"
4242
GridapP4est = "0.3"
4343
GridapPETSc = "0.5"
44-
GridapSolvers = "0.5.0"
44+
GridapSolvers = "0.6"
4545
MPI = "0.20"
4646
SpecialFunctions = "1"
4747
julia = "1.6"

deps/build.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ files = [
2626
"Topology optimization"=>"TopOptEMFocus.jl",
2727
"Poisson on unfitted meshes"=>"poisson_unfitted.jl",
2828
"Poisson with AMR"=>"poisson_amr.jl",
29+
"Poisson with HDG"=>"poisson_hdg.jl",
30+
"Poisson with HHO on polytopal meshes"=>"poisson_hho.jl",
31+
"Block assembly and solvers: Incompressible Stokes example"=>"stokes_blocks.jl",
2932
"Lagrange multipliers" => "lagrange_multipliers.jl",
3033
"Low-level API - Poisson equation"=>"poisson_dev_fe.jl",
3134
"Low-level API - Geometry" => "geometry_dev.jl",

docs/make.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@ for (i,(title,filename)) in enumerate(Tutorials.files)
6060
end
6161

6262
makedocs(
63-
sitename = "Gridap tutorials",
64-
format = Documenter.HTML(),
65-
pages = pages
63+
sitename = "Gridap tutorials",
64+
format = Documenter.HTML(),
65+
pages = pages
6666
)
6767

6868
# Documenter can also automatically deploy documentation to gh-pages.
6969
# See "Hosting Documentation" and deploydocs() in the Documenter manual
7070
# for more information.
7171

7272
deploydocs(
73-
repo = "github.com/gridap/Tutorials.git"
73+
repo = "github.com/gridap/Tutorials.git"
7474
)

src/poisson_hdg.jl

Lines changed: 54 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
# # [Tutorial: Hybridizable Discontinuous Galerkin Method for the Poisson equation]
2-
#
31
# In this tutorial, we will implement a Hybridizable Discontinuous Galerkin (HDG) method
42
# for solving the Poisson equation. The HDG method is an efficient variant of DG methods
5-
# that introduces an auxiliary variable λ on mesh interfaces to reduce the global system size.
3+
# that introduces an auxiliary variable m on mesh interfaces to reduce the global system size.
64
#
7-
# ## The Poisson Problem
5+
# ## HDG Discretization
86
#
97
# We consider the Poisson equation with Dirichlet boundary conditions:
108
#
@@ -15,29 +13,28 @@
1513
# \end{aligned}
1614
# ```
1715
#
18-
# ## HDG Discretization
19-
#
2016
# The HDG method first rewrites the problem as a first-order system:
2117
#
2218
# ```math
2319
# \begin{aligned}
2420
# \boldsymbol{q} + \nabla u &= \boldsymbol{0} \quad \text{in} \quad \Omega\\
25-
# \nabla \cdot \boldsymbol{q} &= -f \quad \text{in} \quad \Omega\\
21+
# \nabla \cdot \boldsymbol{q} &= f \quad \text{in} \quad \Omega\\
2622
# u &= g \quad \text{on} \quad \partial\Omega
2723
# \end{aligned}
2824
# ```
2925
#
3026
# The HDG discretization introduces three variables:
3127
# - ``\boldsymbol{q}_h``: the approximation to the flux ``\boldsymbol{q}``
3228
# - ``u_h``: the approximation to the solution ``u``
33-
# - ``\lambda_h``: the approximation to the trace of ``u`` on element faces
29+
# - ``m_h``: the approximation to the trace of ``u`` on element faces
3430
#
35-
# The method is characterized by:
36-
# 1. Local discontinuous approximation for ``(\boldsymbol{q}_h,u_h)`` in each element
37-
# 2. Continuous approximation for ``\lambda_h`` on element faces
38-
# 3. Numerical flux ``\widehat{\boldsymbol{q}}_h = \boldsymbol{q}_h + \tau(u_h - \lambda_h)\boldsymbol{n}``
31+
# Numerical fluxes are defindes as
3932
#
40-
# where τ is a stabilization parameter.
33+
# ```math
34+
# \widehat{\boldsymbol{q}}_h = \boldsymbol{q}_h + \tau(u_h - m_h)\boldsymbol{n}
35+
# ```
36+
#
37+
# where $\tau$ is a stabilization parameter.
4138
#
4239
# First, let's load the required Gridap packages:
4340

@@ -54,108 +51,105 @@ using Gridap.CellData
5451

5552
u(x) = sin(2*π*x[1])*sin(2*π*x[2])
5653
q(x) = -(u)(x) # Define the flux q = -∇u
57-
f(x) = (∇ q)(x) # Source term f = -Δu = -∇⋅(∇u)
54+
f(x) = (∇ q)(x) # Source term f = -Δu = -∇⋅(∇u)$
5855

59-
# ## Mesh Generation
56+
# ## Geometry
6057
#
61-
# Create a 3D simplicial mesh from a Cartesian grid:
58+
# We generate a D-dimensional simplicial mesh from a Cartesian grid:
6259

6360
D = 2 # Problem dimension
6461
nc = Tuple(fill(8, D)) # 4 cells in each direction
6562
domain = Tuple(repeat([0, 1], D)) # Unit cube domain
6663
model = simplexify(CartesianDiscreteModel(domain,nc))
6764

68-
# ## Volume and Interface Triangulations
65+
# From this mesh, we will require two triangulations where to define our HDG spaces:
6966
#
70-
# HDG methods require two types of meshes:
71-
# 1. Volume mesh for element interiors
72-
# 2. Skeleton mesh for element interfaces
67+
# 1. A cell triangulation $\Omega$, for the volume variables
68+
# 2. A face triangulation $\Gamma$, for the skeleton variables
7369
#
74-
# We also need patch-wise triangulations for local computations:
70+
# These are given by
7571

7672
Ω = Triangulation(ReferenceFE{D}, model) # Volume triangulation
7773
Γ = Triangulation(ReferenceFE{D-1}, model) # Skeleton triangulation
7874

75+
# ## PatchTopology and PatchTriangulation
76+
#
77+
# A key aspect of hybrid methods is the use of static condensation, which is the
78+
# elimination of cell unknowns to reduce the size of the global system.
79+
# To achieve this, we need to be able to assemble and solve local problems on each cell, that
80+
# involve
81+
# - contributions from the cell itself
82+
# - contributions from the cell faces
83+
# To this end, Gridap provides a general framework for patch-assembly and solves. The idea
84+
# is to define a patch decomposition of the mesh (in this case, a patch is a cell and its sourrounding
85+
# faces). We can then gather contributions for each patch, solve the local problems, and
86+
# assemble the results into the global system.
87+
#
88+
# The following code creates the required `PatchTopology` for the problem at hand. We then
89+
# take d-dimensional slices of it by the means of `PatchTriangulation` and `PatchBoundaryTriangulation`.
90+
# These are the `Triangulation`s we will integrate our weakform over.
91+
7992
ptopo = Geometry.PatchTopology(model)
8093
Ωp = Geometry.PatchTriangulation(model,ptopo) # Patch volume triangulation
8194
Γp = Geometry.PatchBoundaryTriangulation(model,ptopo) # Patch skeleton triangulation
8295

83-
# ## Reference Finite Elements
96+
# ## FESpaces
8497
#
8598
# HDG uses three different finite element spaces:
86-
# 1. Vector-valued space for the flux q (Q)
87-
# 2. Scalar space for the solution u (V)
88-
# 3. Scalar space for the interface variable λ (M)
99+
# 1. A vector-valued space for the flux q (Q)
100+
# 2. A scalar space for the solution u (V)
101+
# 3. A scalar space for the interface variable m (M)
102+
#
103+
# We then define discontinuous finite element spaces of the approppriate order, locally $\mathbb{P}^k$.
104+
# Note that only the skeletal space has Dirichlet boundary conditions.
89105

90106
order = 1 # Polynomial order
91107
reffe_Q = ReferenceFE(lagrangian, VectorValue{D, Float64}, order; space=:P)
92108
reffe_V = ReferenceFE(lagrangian, Float64, order; space=:P)
93109
reffe_M = ReferenceFE(lagrangian, Float64, order; space=:P)
94110

95-
# ## Test and Trial Spaces
96-
#
97-
# Create discontinuous cell spaces for volume variables (q,u) and
98-
# a discontinous face space for the interface variable λ:
99-
100-
# Test spaces
101111
V = TestFESpace(Ω, reffe_V; conformity=:L2) # Discontinuous vector space
102112
Q = TestFESpace(Ω, reffe_Q; conformity=:L2) # Discontinuous scalar space
103113
M = TestFESpace(Γ, reffe_M; conformity=:L2, dirichlet_tags="boundary") # Interface space
104-
105-
# Only the skeleton space has Dirichlet BC
106114
N = TrialFESpace(M, u)
107115

108116
# ## MultiField Structure
109117
#
110-
# Group the spaces for q, u, and λ using MultiField:
118+
# Since we are doing static condensation, we need assemble by blocks. In particular, the
119+
# `StaticCondensationOperator` expects the variables to be groupped in two blocks:
120+
# - The eliminated variables (in this case, the volume variables q and u)
121+
# - The retained variables (in this case, the interface variable m)
122+
# We will assemble by blocks using the `BlockMultiFieldStyle` API.
111123

112-
mfs = MultiField.BlockMultiFieldStyle(2,(2,1)) # Special blocking for efficient static condensation
113-
X = MultiFieldFESpace([V, Q, N];style=mfs)
124+
mfs = BlockMultiFieldStyle(2,(2,1)) # Special blocking for efficient static condensation
125+
X = MultiFieldFESpace([V, Q, N]; style=mfs)
114126

115-
# ## Integration Setup
127+
# ## Weak Form and integration
116128
#
117-
# Define measures for volume and face integrals:
118129

119130
degree = 2*(order+1) # Integration degree
120-
dΩp = Measure(Ωp,degree) # Volume measure
121-
dΓp = Measure(Γp,degree) # Surface measure
122-
123-
# ## HDG Parameters
124-
#
125-
# The stabilization parameter τ affects the stability and accuracy of the method:
131+
dΩp = Measure(Ωp,degree) # Volume measure, on the patch triangulation
132+
dΓp = Measure(Γp,degree) # Surface measure, on the patch boundary triangulation
126133

127134
τ = 1.0 # HDG stabilization parameter
128135

129-
# ## Weak Form
130-
#
131-
# The HDG weak form consists of three equations coupling q, u, and λ.
132-
# We need operators to help define the weak form:
133-
134136
n = get_normal_vector(Γp) # Face normal vector
135137
Πn(u) = un # Normal component
136138
Π(u) = change_domain(u,Γp,DomainStyle(u)) # Project to skeleton
137139

138-
# The bilinear and linear forms are:
139-
# 1. Volume integrals for flux and primal equations
140-
# 2. Interface integrals for hybridization
141-
# 3. Stabilization terms with parameter τ
142-
143140
a((uh,qh,sh),(vh,wh,lh)) = ( qhwh - uh*(∇wh) - qh(vh) )dΩp + (sh*Πn(wh))dΓp +
144141
((Πn(qh) + τ*(Π(uh) - sh))*(Π(vh) + lh))dΓp
145142
l((vh,wh,lh)) = ( f*vh )dΩp
146143

147144
# ## Static Condensation and Solution
148145
#
149-
# A key feature of HDG is static condensation - eliminating volume variables
150-
# to get a smaller system for λ only:
146+
# With all these ingredients, we can now build our statically-condensed operator ans
147+
# solve the problem. Note that we are solving a scatically-condensed system. We can
148+
# retrieve the internal `AffineFEOperator` from `op.sc_op`.
151149

152150
op = MultiField.StaticCondensationOperator(ptopo,X,a,l)
153151
uh, qh, sh = solve(op)
154152

155-
# ## Error Analysis
156-
#
157-
# Compute the L2 error between numerical and exact solutions:
158-
159153
= Measure(Ω,degree)
160154
eh = uh - u
161155
l2_uh = sqrt(sum((eheh)*dΩ))

0 commit comments

Comments
 (0)