3
3
# for solving the Poisson equation. HHO methods are a class of modern hybridizable finite element methods
4
4
# that provide optimal convergence rates while enabling static condensation for efficient solution.
5
5
#
6
+ # HHO is a mathematically complex method. This tutorial will **NOT** cover the method nor
7
+ # its mathematical foundations. You should be familiar with both before going into
8
+ # the tutorial itself.
9
+ # We also recommend going through the HDG tutorial first, which shares many of the
10
+ # same concepts but is simpler to understand.
11
+ #
6
12
# ## Problem statement
7
13
#
8
14
# We consider the Poisson equation with Dirichlet boundary conditions:
@@ -82,7 +88,6 @@ N = TrialFESpace(M,u)
82
88
mfs = MultiField. BlockMultiFieldStyle (2 ,(1 ,1 ))
83
89
X = MultiFieldFESpace ([V, N];style= mfs)
84
90
Y = MultiFieldFESpace ([V, M];style= mfs)
85
- Xp = FESpaces. PatchFESpace (X,ptopo)
86
91
87
92
# ## PatchTopology and PatchTriangulation
88
93
#
@@ -114,13 +119,26 @@ dΓp = Measure(Γp,qdegree)
114
119
# A key feature of HHO is the use of local solves to define local projections of our bulk and
115
120
# skeleton variables. Just like for static condensation, we will use patch assembly to
116
121
# gather the contributions from each patch and solve the local problems.
122
+ # The result is then an element of the space we are projecting to, given as a
123
+ # linear combination of the basis of that space. This whole abstraction is taken
124
+ # care of by the `LocalOperator` object.
125
+ #
126
+ # For the mixed-order Poisson problem, we require two local projections.
127
+ #
128
+ # ### L2 projection operator
117
129
#
118
- # For the mixed-order Poisson problem, we require two local projections:
119
- # - First, an L2 local projection operator onto the mesh faces.
120
- # - Second, the so-called reconstruction operator. This operator is highly tied to the
121
- # ellipic projector, and projects our bulk-skeleton variable pair onto a bulk
122
- # space of higher order.
123
- # The operators are defined as follows:
130
+ # First, an L2 local projection operator onto the mesh faces. This is the simplest
131
+ # operator we can define, such that given $u$ in some undefined space, we find $Pu \in V$ st
132
+ #
133
+ # $$(Pu,q) = (u,q) \forall q \in V$$
134
+ #
135
+ # This signature for the `LocalOperator` assumes that the rhs and lhs for each local problem
136
+ # are given by a single cell contribution (no patch assembly required).
137
+ # Note also the use of `FESpaceWithoutBCs`, which strips the boundary conditions from the
138
+ # space `V`. This is because we do not want to take into account boundary conditions
139
+ # when projecting onto the space.
140
+ # The local solve map is given by `LocalSolveMap`, which by default uses Julia's LU
141
+ # factorization to solve the local problem exactly.
124
142
125
143
function projection_operator (V, Ω, dΩ)
126
144
Π (u,Ω) = change_domain (u,Ω,DomainStyle (u))
@@ -132,6 +150,18 @@ function projection_operator(V, Ω, dΩ)
132
150
return P
133
151
end
134
152
153
+ # ### Reconstruction operator
154
+ #
155
+ # Finally, we build the so-called reconstruction operator. This operator is highly tied to the
156
+ # ellipic projector, and projects our bulk-skeleton variable pair onto a bulk space of higher order.
157
+ #
158
+ # It's definition can be found in HHO literature, and requires solving a constrained
159
+ # local problem on each cell and its faces. We therefore use patch assembly, and impose
160
+ # our constraint using an additional space `Λ` as a local Lagrange multiplier.
161
+ # Naturally, we want to eliminate the multiplier and return a solution in the reconstructed
162
+ # space `L`. This is taken care of by the `LocalPenaltySolveMap`, and the kwarg `space_out = L`
163
+ # which overrides the default behavior of returning a solution in the test space `Y`.
164
+
135
165
function reconstruction_operator (ptopo,order,X,Ω,Γp,dΩp,dΓp)
136
166
L = FESpaces. PolytopalFESpace (Ω, Float64, order+ 1 ; space= :P )
137
167
Λ = FESpaces. PolytopalFESpace (Ω, Float64, 0 ; space= :P )
153
183
PΓ = projection_operator (M, Γp, dΓp)
154
184
R = reconstruction_operator (ptopo,order,Y,Ωp,Γp,dΩp,dΓp)
155
185
156
- # ## Weakform
186
+ # ## Weakform and assembly
157
187
#
158
188
# We can now define:
159
189
# - The consistency term `a`
178
208
179
209
l ((vΩ,vΓ)) = ∫ (f⋅ vΩ)dΩp
180
210
181
- # ## Assembly without static condensation
211
+ # ### Patch-FESpaces
212
+ #
213
+ # An additional difficulty in HHO methods is that our reconstructed functions `R(u)` are
214
+ # hard to assemble. They are defined on the cells, but depend on skeleton degrees of freedom.
215
+ # We therefore cannot assemble them using the original FESpace `N`. Instead, we will create \
216
+ # view of the original space that is defined on the patches, and can be used to assemble
217
+ # the local contributions depending on `R`. It can be done by the means of `PatchFESpace`:
218
+
219
+ Xp = FESpaces. PatchFESpace (X,ptopo)
220
+
221
+ # ### Assembly without static condensation
222
+ #
223
+ # We can now proceed to evaluate and assemble all our contributions. Note that some of
224
+ # the contributions depend on the reconstructed variables, e.g `a(u,v)`, and need to
225
+ # be assembled using the `PatchFESpace` `Xp`, while others can be assembled using the original
226
+ # FESpace `X` (e.g. `s(u,v)` and `l(v)`).
227
+ # Assembly is therefore somewhat more complex than in the standard case. We need to
228
+ # collect the contributions for every (test,trial) pair, and then merge them into a single
229
+ # data structure that can be passed to the assembler.
230
+ # In the case of mixed-order HHO, we only have two combinations, (`Xp`, `Xp`) and (`X`, `X`),
231
+ # but the cross-terms appear also in the case of the original HHO formulation.
182
232
183
233
global_assem = SparseMatrixAssembler (X,Y)
184
234
@@ -199,7 +249,7 @@ eu = ui - u
199
249
l2u = sqrt (sum ( ∫ (eu * eu)dΩp))
200
250
h1u = l2u + sqrt (sum ( ∫ (∇ (eu) ⋅ ∇ (eu))dΩp))
201
251
202
- # ## Assembly with static condensation
252
+ # ### Assembly with static condensation
203
253
204
254
patch_assem = FESpaces. PatchAssembler (ptopo,X,Y)
205
255
0 commit comments