\chapter{Examples}
\label{sec:examples}
\index{examples}

The following examples illustrate basic usage of the form language for
the definition of a collection of standard multilinear forms. We
assume that \texttt{dx} has been declared as an integral over the
interior of $\Omega$ and that both \texttt{i} and \texttt{j} have
been declared as a free \texttt{Index}.

The examples presented below can all be found in the subdirectory
\texttt{src/demo} of the \ffc{} source tree together with numerous
other examples.

%------------------------------------------------------------------------------
\section{The mass matrix}
\index{mass matrix}

As a first example, consider the bilinear form corresponding to a
mass matrix,
\begin{equation}
  a(v, u) = \int_{\Omega} v \, u \dx,
\end{equation}
which can be implemented in \ffc{} as follows:
\begin{code}
element = FiniteElement("Lagrange", "triangle", 1)

v = TestFunction(element)
u = TrialFunction(element)
    
a = v*u*dx
\end{code}

This example is implemented in the file \texttt{Mass.form} in the
collection of demonstration forms included with the \ffc{} source
distribution.

%------------------------------------------------------------------------------
\section{Poisson's equation}
\index{Poisson's equation}

The bilinear and linear forms form for Poisson's equation,
\begin{eqnarray}
  a(v, u) &=& \int_{\Omega} \nabla v \cdot \nabla u \dx, \\
  L(v)    &=& \int_{\Omega} v \, f \dx,
\end{eqnarray}
can be implemented as follows:
\begin{code}
element = FiniteElement("Lagrange", "triangle", 1)

v = TestFunction(element)
u = TrialFunction(element)
f = Function(element)
  
a = dot(grad(v), grad(u))*dx
L = v*f*dx
\end{code}
Alternatively, index notation can be used to express the scalar
product:
\begin{code}
a = D(v, i)*D(u, i)*dx
\end{code}

This example is implemented in the file \texttt{Poisson.form} in the
collection of demonstration forms included with the \ffc{} source
distribution.

%------------------------------------------------------------------------------
\section{Vector-valued Poisson}
\index{vector-valued Poisson}

The bilinear and linear forms for a system of (independent) Poisson
equations,
\begin{eqnarray}
  a(v, u) &=& \int_{\Omega} \nabla v : \nabla u \dx, \\
  L(v)    &=& \int_{\Omega} v \cdot f \dx,
\end{eqnarray}
with $v$, $u$ and $f$ vector-valued can be implemented as follows:
\begin{code}
element = VectorElement("Lagrange", "triangle", 1)
  
v = TestFunction(element)
u = TrialFunction(element)
f = Function(element)
 
a = dot(grad(v), grad(u))*dx
L = dot(v, f)*dx
\end{code}
Alternatively, index notation may be used:
\begin{code}
a = D(v[i], j)*D(u[i], j)*dx
L = v[i]*f[i]*dx
\end{code}

This example is implemented in the file \texttt{PoissonSystem.form} in
the collection of demonstration forms included with the \ffc{} source
distribution.

%------------------------------------------------------------------------------
\section{The strain-strain term of linear elasticity}
\index{elasticity}
\index{linear elasticity}
\index{strain}

The strain-strain term of linear elasticity,
\begin{equation}
  a(v, u) = \int_{\Omega} \epsilon(v) : \epsilon(u) \dx,
\end{equation}
where
\begin{equation}
  \epsilon(v) = \frac{1}{2}(\nabla v + (\nabla v)^{\top})
\end{equation}
can be implemented as follows:
\begin{code}
element = VectorElement("Lagrange", "tetrahedron", 1)
  
v = TestFunction(element)
u = TrialFunction(element)
  
def epsilon(v):
    return 0.5*(grad(v) + transp(grad(v)))

a = dot(epsilon(v), epsilon(u))*dx
\end{code}
Alternatively, index notation can be used to define the form:
\begin{code}
a = 0.25*(D(v[i], j) + D(v[j], i))* \
         (D(u[i], j) + D(u[j], i))*dx
\end{code}

This example is implemented in the file \texttt{Elasticity.form} in
the collection of demonstration forms included with the \ffc{} source
distribution.

%------------------------------------------------------------------------------
\section{The nonlinear term of Navier--Stokes}
\index{Navier-Stokes}
\index{fixed-point iteration}

The bilinear form for fixed-point iteration on the nonlinear term of
the incompressible Navier--Stokes equations,
\begin{equation}
  a(v, u) = \int_{\Omega} v \cdot ((w \cdot \nabla) u) \dx,
\end{equation}
with $w$ the frozen velocity from a previous iteration, can be
conveniently implemented using index notation as follows:
\begin{code}
element = FiniteElement("Vector Lagrange", "tetrahedron", 1)
  
v = TestFunction(element)
u = TrialFunction(element)
w = Function(element)

a = v[i]*w[j]*D(u[i], j)*dx
\end{code}

This example is implemented in the file \texttt{NavierStokes.form} in
the collection of demonstration forms included with the \ffc{} source
distribution.

%------------------------------------------------------------------------------
\section{The heat equation}
\index{heat equation}
\index{time-stepping}
\index{backward Euler}

Discretizing the heat equation,
\begin{equation}
  \dot{u} - \nabla \cdot (c \nabla u) = f,
\end{equation}
in time using the $\mathrm{dG}(0)$ method (backward Euler), we
obtain the following variational problem for the discrete solution $u_h
= u_h(x, t)$: Find $u_h^n = u_h(\cdot, t_n)$ with
$u_h^{n-1} = u_h(\cdot, t_{n-1})$ given such that
\begin{equation}
  \frac{1}{k_n} \int_{\Omega} v \, (u_h^n - u_h^{n-1}) \dx +
  \int_{\Omega} c \, \nabla v \cdot \nabla u_h^n \dx =
  \int_{\Omega} v \, f^n \dx
\end{equation}
for all test functions $v$, where $k = t_n - t_{n-1}$ denotes the time
step . In the example below, we implement this variational problem
with piecewise linear test and trial functions, but other choices are
possible (just choose another finite element).

Rewriting the variational problem in the standard form $a(v, u_h) =
L(v)$ for all $v$, we obtain the following pair of bilinear and linear
forms:
\begin{eqnarray}
  a(v, u_h^n) &=& \int_{\Omega} v \, u_h^n \dx +
  k_n \int_{\Omega} c \, \nabla v \cdot \nabla u_h^n \dx, \\
  L(v) &=& \int_{\Omega} v \, u_h^{n-1} \dx + k_n \int_{\Omega} v \, f^n \dx,
\end{eqnarray}
which can be implemented as follows:
\begin{code}
element = FiniteElement("Lagrange", "triangle", 1)

v  = TestFunction(element)  # Test function
u1 = TrialFunction(element) # Value at t_n
u0 = Function(element)      # Value at t_n-1
c  = Function(element)      # Heat conductivity
f  = Function(element)      # Heat source
k  = Constant("triangle")   # Time step

a = v*u1*dx + k*c*dot(grad(v), grad(u1))*dx
L = v*u0*dx + k*v*f*dx
\end{code}

%------------------------------------------------------------------------------
\section{Mixed formulation of Stokes}
\index{Stokes' equations}
\index{mixed formulation}
\index{Taylor-Hood element}

To solve Stokes' equations,
\begin{eqnarray}
  - \Delta u + \nabla p &=& f, \\
  \nabla \cdot u &=& 0,
\end{eqnarray}
we write the variational problem in standard form
$a(v, u) = L(v)$ for all $v$ to obtain the following pair of bilinear
and linear forms:
\begin{eqnarray}
  a((v, q), (u, p)) &=& \int_{\Omega} \nabla v : \nabla u - (\nabla \cdot v) \, p +
  q \, (\nabla \cdot u) \dx, \\
  L((v, q)) &=& \int_{\Omega} v \cdot f \dx.
\end{eqnarray}
Using a mixed formulation with Taylor-Hood elements, this can be
implemented as follows:
\begin{code}
P2 = FiniteElement("Vector Lagrange", "triangle", 2)
P1 = FiniteElement("Lagrange", "triangle", 1)
TH = P2 + P1

(v, q) = TestFunctions(TH)
(u, p) = TrialFunctions(TH)
 
f = Function(P2)
 
a = (dot(grad(v), grad(u)) - div(v)*P + q*div(u))*dx
L = dot(v, f)*dx
\end{code}

This example is implemented in the file \texttt{Heat.form} in the
collection of demonstration forms included with the \ffc{} source
distribution.

%------------------------------------------------------------------------------
\section{Mixed formulation of Poisson}
\index{mixed Poisson}
\index{BDM elements}
\index{Brezzi--Douglas--Marini elements}

We next consider the following formulation of Poisson's equation as a
pair of first order equations for $\sigma \in H(\mathrm{div})$
and $u \in L_2$:
\begin{eqnarray}
    \sigma + \nabla u &= 0, \\
    \nabla \cdot \sigma &= f.
\end{eqnarray}
We multiply the two equations by a pair of test functions $\tau$ and
$w$ and integrate by parts to obtain the following variational
problem: Find $(\sigma, u) \in V = H(\mathrm{div}) \times L_2$ such that
\begin{equation}
  a((\tau, w), (\sigma, u)) = L((\tau, w)) \quad \forall \, (\tau, w) \in V,
\end{equation}
where
\begin{eqnarray}
  a((\tau, w), (\sigma, u)) &=& \int_{\Omega} \tau \cdot \sigma - \nabla \cdot \tau \, u + w \nabla \cdot \sigma \dx, \\
  L((\tau, w)) &=& \int_{\Omega} w \cdot f \dx.
\end{eqnarray}

We may implement the corresponding forms in the \ffc{} form language
using first order BDM $H(\mathrm{div})$-conforming
elements for $\sigma$ and piecewise constant $L_2$-conforming elements
for $u$ as follows:
\begin{code}
BDM1 = FiniteElement("Brezzi-Douglas-Marini", "triangle", 1)
DG0  = FiniteElement("Discontinuous Lagrange", "triangle", 0)

element = BDM1 + DG0

(tau, w) = TestFunctions(element)
(sigma, u) = TrialFunctions(element)

f = Function(DG0)

a = (dot(tau, sigma) - div(tau)*u + w*div(sigma))*dx
L = w*f*dx
\end{code}

This example is implemented in the file \texttt{MixedPoisson.form} in
the collection of demonstration forms included with the \ffc{} source
distribution.

%------------------------------------------------------------------------------
\section{Poisson's equation with DG elements}
\index{Discontinuous Galerkin}

We consider again Poisson's equation, but now in an (interior penalty)
discontinuous Galerkin formulation: Find $u \in V = L_2$ such that
\begin{displaymath}
  a(v, u) = L(v) \quad \forall v \in V,
\end{displaymath}
where
\begin{equation}
  \begin{split}
    a(v, u) &= \int_{\Omega} \nabla v \cdot \nabla u \dx \\
    &+ \sum_S \int_S 
    - \langle \nabla v \rangle \cdot \llbracket u \rrbracket_n
    - \llbracket v \rrbracket_n \cdot \langle \nabla u \rangle
    + (\alpha/h) \llbracket v \rrbracket_n \cdot \llbracket u \rrbracket_n \dS \\
    &+ \int_{\partial\Omega}
    - \nabla v \cdot \llbracket u \rrbracket_n - \llbracket v \rrbracket_n \cdot \nabla u
    + (\gamma/h) v u \ds \\
    L(v) &= \int_{\Omega} v f \dx + \int_{\partial\Omega} v g \ds.
  \end{split}
\end{equation}
The corresponding finite element variational problem for discontinuous
first order elements may be implemented as follows:
\begin{code}
DG1 = FiniteElement("Discontinuous Lagrange", "triangle", 1)

v = TestFunction(DG1)
u = TrialFunction(DG1)

f = Function(DG1)
g = Function(DG1)
n = FacetNormal("triangle")
h = MeshSize("triangle")

a = dot(grad(v), grad(u))*dx \
  - dot(avg(grad(v)), jump(u, n))*dS \
  - dot(jump(v, n), avg(grad(u)))*dS \
  + alpha/h('+')*dot(jump(v, n), jump(u, n))*dS \
  - dot(grad(v), jump(u, n))*ds \
  - dot(jump(v, n),\ grad(u))*ds \
  + gamma/h*v*u*ds
L = v*f*dx + v*g*ds
\end{code}

This example is implemented in the file \texttt{PoissonDG.form} in the
collection of demonstration forms included with the \ffc{} source
distribution.

%------------------------------------------------------------------------------
\section{Quadrature elements}
\index{FE and QE}

We consider here a nonlinear version of the Poisson's equation to illustrate
the main difference between the \texttt{FiniteElement} and
\texttt{QuadratureElement}.
%
The strong equation looks as follows:
%
\begin{equation}
  - \nabla \cdot (1+u^2)\nabla u = f.
\end{equation}
%
The linearised bilinear and linear forms for this equation,
%
\begin{eqnarray}
  a(v, u) &=& \int_{\Omega} (1+u_{0}^2) \nabla v \cdot \nabla u \dx + \int_{\Omega} 2u_0 u \nabla v \cdot \nabla u_0 \dx, \\
  L(v)    &=& \int_{\Omega} v \, f \dx - \int_{\Omega} (1+u_{0}^2) \nabla v \cdot \nabla u_0 \dx,
\end{eqnarray}
%
can be implemented in a single form file as follows:
%
\small
\begin{code}
# NonlinearPoisson.form
element = FiniteElement("Lagrange", "triangle", 1)

v = TestFunction(element)
u = TrialFunction(element)
u0= Function(element)
f = Function(element)

a = (1+u0*u0)*dot(grad(v), grad(u))*dx \
  + 2*u0*u*dot(grad(v), grad(u0))*dx 
L = v*f*dx - (1+u0*u0)*dot(grad(v), grad(u0))*dx
\end{code}
\normalsize
%
Here, $u_0$ represents the solution from the previous Newton-Raphson iteration.

The above form will be denoted REF1 and serve as our reference implementation for
linear elements. A similar form (REF2) using quadratic elements will serve as a
reference for quadratic elements.

Now, assume that we want to treat the quantities $C = (1+u_{0}^2)$
and $\sigma_0 = (1+u_{0}^2) \nabla u_0$ as given functions (to be computed elsewhere). Substituting
into bilinear linear forms, we obtain
%
\begin{eqnarray}
  a(v, u) &=& \int_{\Omega} \text{C} \nabla v \cdot \nabla u \dx + \int_{\Omega} 2u_0 u \nabla v \cdot \nabla u_0 \dx, \\
  L(v)    &=& \int_{\Omega} v \, f \dx - \int_{\Omega} \nabla v \cdot \sigma_0 \dx.
\end{eqnarray}
%
Then, two additional forms are created to compute the tangent C and
the gradient of $u_0$. This situation shows up in plasticity and other
problems where certain quantities need to be computed elsewhere (in
user-defined functions).
%
The 3 forms using the standard \texttt{FiniteElement} (linear elements) can
then be implemented as:
%
\small
\begin{code}
# FE1NonlinearPoisson.form
element = FiniteElement("Lagrange", "triangle", 1)
DG = FiniteElement("Discontinuous Lagrange", "triangle", 0)
sig = VectorElement("Discontinuous Lagrange", "triangle", 0)

v    = TestFunction(element)
u    = TrialFunction(element)
u0   = Function(element)
C    = Function(DG)
sig0 = Function(sig)
f    = Function(element)

a = v.dx(i)*C*u.dx(i)*dx + v.dx(i)*2*u0*u*u0.dx(i)*dx
L = v*f*dx - dot(grad(v), sig0)*dx
\end{code}
\normalsize
%
\small
\begin{code}
# FE1Tangent.form
element = FiniteElement("Lagrange", "triangle", 1)
DG = FiniteElement("Discontinuous Lagrange", "triangle", 0)

v = TestFunction(DG)
u = TrialFunction(DG)
u0= Function(element)

a = v*u*dx
L = v*(1.0 + u0*u0)*dx
\end{code}
\normalsize
%
\small
\begin{code}
# FE1Gradient.form
element = FiniteElement("Lagrange", "triangle", 1)
DG = VectorElement("Discontinuous Lagrange", "triangle", 0)

v = TestFunction(DG)
u = TrialFunction(DG)
u0= Function(element)

a = dot(v,u)*dx
L = dot(v,grad(u0))*dx
\end{code}
\normalsize

The 3 forms can be implemented using the \texttt{QuadratureElement} in a similar
fashion in which only the element declaration is different:
%
\small
\begin{code}
# QE1NonlinearPoisson.form
element = FiniteElement("Lagrange", "triangle", 1)
QE = QuadratureElement("triangle", 2)
sig = VectorQuadratureElement("triangle", 2)
\end{code}
\normalsize
%
\small
\begin{code}
# QE1Tangent.form
element = FiniteElement("Lagrange", "triangle", 1)
QE = QuadratureElement("triangle", 2)
\end{code}
\normalsize
%
\small
\begin{code}
# QE1Gradient.form
element = FiniteElement("Lagrange", "triangle", 1)
QE = VectorQuadratureElement("triangle", 2)
\end{code}
\normalsize

Note that we use 2 points when declaring the \texttt{QuadratureElement}. This is
because the RHS of the \texttt{Tangent.form} is 2$^{\text{nd}}$ order and
therefore we need 2 points for exact integration. Due to consistency issues,
when passing functions around between the forms, we also need to use 2 points
when declaring the \texttt{QuadratureElement} in the other forms.

Typical values of the relative residual for each Newton iteration for all 3
approaches are shown in Table~\ref{tab:convergence1}. It is noted that the
convergence rate is quadratic as it should be for all 3 methods.

\begin{table}[H]
\label{tab:convergence1}
\linespread{1.2}\selectfont
  \begin{center}
    \begin{tabular}{|c|c|c|c|}
      \hline
      Iteration & REF1 & FE1 & QE1 \\
      \hline
      \hline
      1 & 6.342e-02 & 6.342e-02 & 6.342e-02 \\
      \hline
      2 & 5.305e-04 & 5.305e-04 & 5.305e-04 \\
      \hline
      3 & 3.699e-08 & 3.699e-08 & 3.699e-08 \\
      \hline
      4 & 2.925e-16 & 2.925e-16 & 2.475e-16 \\
      \hline
    \end{tabular}
    \caption{Relative residuals for each approach for linear elements.}
  \end{center}
\end{table}

However, if quadratic elements are used to interpolate the unknown field $u$,
the order of all elements in the above forms is increased by 1. This influences
the convergence rate as seen in Table~\ref{tab:convergence2}. Clearly, using
the standard \texttt{FiniteElement} leads to a poor convergence whereas
the \texttt{QuadratureElement} still leads to quadratic convergence.
%
\begin{table}[H]
\label{tab:convergence2}
\linespread{1.2}\selectfont
  \begin{center}
    \begin{tabular}{|c|c|c|c|}
      \hline
      Iteration & REF2 & FE2 & QE2 \\
      \hline
      \hline
      1 & 2.637e-01 & 3.910e-01 & 2.644e-01 \\
      \hline
      2 & 1.052e-02 & 4.573e-02 & 1.050e-02 \\
      \hline
      3 & 1.159e-05 & 1.072e-02 & 1.551e-05 \\
      \hline
      4 & 1.081e-11 & 7.221e-04 & 9.076e-09 \\
      \hline
    \end{tabular}
    \caption{Relative residuals for each approach for quadratic elements.}
  \end{center}
\end{table}
