1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
# The first step is to define the variational problem at hand. We define
# the variational problem in UFL terms in a separate form file. We begin
# by defining the finite element:
from basix.ufl import element
from ufl import (
CellDiameter,
Coefficient,
Constant,
FacetNormal,
FunctionSpace,
Mesh,
TestFunction,
TrialFunction,
avg,
div,
dS,
dx,
grad,
inner,
jump,
)
e = element("Lagrange", "triangle", 2)
# The first argument to :py:class:`FiniteElement` is the finite element
# family, the second argument specifies the domain, while the third
# argument specifies the polynomial degree. Thus, in this case, our
# element `element` consists of second-order, continuous Lagrange basis
# functions on triangles (or in order words, continuous piecewise linear
# polynomials on triangles).
#
# Next, we use this element to initialize the trial and test functions
# ($u$ and $v$) and the coefficient function $f$:
coord_element = element("Lagrange", "triangle", 1, shape=(2,))
mesh = Mesh(coord_element)
V = FunctionSpace(mesh, e)
u = TrialFunction(V)
v = TestFunction(V)
f = Coefficient(V)
# Next, the outward unit normal to cell boundaries and a measure of the
# cell size are defined. The average size of cells sharing a facet will
# be used (`h_avg`). The UFL syntax `('+')` and `('-')` restricts a
# function to the `('+')` and `('-')` sides of a facet, respectively.
# The penalty parameter `alpha` is made a :cpp:class:`Constant` so
# that it can be changed in the program without regenerating the code.
# Normal component, mesh size and right-hand side
n = FacetNormal(mesh)
h = CellDiameter(mesh)
h_avg = (h("+") + h("-")) / 2
alpha = Constant(mesh)
# Finally, we define the bilinear and linear forms according to the
# variational formulation of the equations. Integrals over
# internal facets are indicated by `*dS`.
# Bilinear form
a = (
inner(div(grad(u)), div(grad(v))) * dx
- inner(avg(div(grad(u))), jump(grad(v), n)) * dS
- inner(jump(grad(u), n), avg(div(grad(v)))) * dS
+ alpha / h_avg * inner(jump(grad(u), n), jump(grad(v), n)) * dS
)
# Linear form
L = inner(f, v) * dx
|