The major difference between deriving variational formulations in 2D and 3D compared to 1D is the rule for integrating by parts. A typical second-order term in a PDE may be written in dimension-independent notation as

\[\nabla^2 u \quad\hbox{or}\quad \nabla\cdot\left( a(\boldsymbol{x})\nabla u\right)
{\thinspace .}\]

The explicit forms in a 2D problem become

\[\nabla^2 u = \nabla\cdot\nabla u =
\frac{\partial^2 u}{\partial x^2} +
\frac{\partial^2 u}{\partial y^2},\]

and

\[\nabla\cdot\left( a(\boldsymbol{x})\nabla u\right) =
\frac{\partial}{\partial x}\left( a(x,y)\frac{\partial u}{\partial x}\right) +
\frac{\partial}{\partial y}\left( a(x,y)\frac{\partial u}{\partial y}\right)
{\thinspace .}\]

We shall continue with the latter operator as the form arises from just setting \(a=1\).

The general rule for integrating by parts is often referred to as Green’s first identity:

(1)\[ -\int_{\Omega} \nabla\cdot (a(\boldsymbol{x})\nabla u) v{\, \mathrm{d}x} =
\int_{\Omega} a(\boldsymbol{x})\nabla u\cdot\nabla v {\, \mathrm{d}x} -
\int_{\partial\Omega} a\frac{\partial u}{\partial n} v {\, \mathrm{d}s},\]

where \(\partial\Omega\) is the boundary of \(\Omega\) and \(\partial u/\partial n = \boldsymbol{n}\cdot\nabla u\) is the derivative of \(u\) in the outward normal direction, \(\boldsymbol{n}\) being an outward unit normal to \(\partial\Omega\). The integrals \(\int_\Omega (){\, \mathrm{d}x}\) are area integrals in 2D and volume integrals in 3D, while \(\int_{\partial\Omega} (){\, \mathrm{d}s}\) is a line integral in 2D and a surface integral in 3D.

Let us divide the boundary into two parts:

- \(\partial\Omega_N\), where we have Neumann conditions \(-a\frac{\partial u}{\partial n} = g\), and
- \(\partial\Omega_D\), where we have Dirichlet conditions \(u = u_0\).

The test functions \(v\) are required to vanish on \(\partial\Omega_D\).

**Example.**
Here is a quite general, stationary, linear PDE arising in many problems:

\[\boldsymbol{v}\cdot\nabla u + \alpha u = \nabla\cdot\left( a\nabla u\right) + f,
\quad\boldsymbol{x}\in\Omega,\]

\[u = u_0,\quad\boldsymbol{x}\in\partial\Omega_D,\]

\[-a\frac{\partial u}{\partial n} = g,\quad\boldsymbol{x}\in\partial\Omega_N
{\thinspace .}\]

The vector field \(\boldsymbol{v}\) and the scalar functions \(a\), \(\alpha\), \(f\), \(u_0\), and \(g\) may vary with the spatial coordinate \(\boldsymbol{x}\) and must be known.

Such a second-order PDE needs exactly one boundary condition at each point of the boundary, so \(\partial\Omega_N\cup\partial\Omega_D\) must be the complete boundary \(\partial\Omega\).

Assume that the boundary function \(u_0(\boldsymbol{x})\) is defined for all \(\boldsymbol{x}\in\Omega\). The unknown function can then be expanded as

\[u = B + \sum_{j\in{\mathcal{I}_s}} c_j{\psi}_j,\quad B = u_0 {\thinspace .}\]

The variational formula is obtained from Galerkin’s method, which technically implies multiplying the PDE by a test function \(v\) and integrating over \(\Omega\):

\[\int_{\Omega} (\boldsymbol{v}\cdot\nabla u + \alpha u)v{\, \mathrm{d}x} =
\int_{\Omega} \nabla\cdot\left( a\nabla u\right){\, \mathrm{d}x} + \int_{\Omega}fv {\, \mathrm{d}x}
{\thinspace .}\]

The second-order term is integrated by parts, according to

\[\int_{\Omega} \nabla\cdot\left( a\nabla u\right)v {\, \mathrm{d}x} =
-\int_{\Omega} a\nabla u\cdot\nabla v{\, \mathrm{d}x}
+ \int_{\partial\Omega} a\frac{\partial u}{\partial n} v{\, \mathrm{d}s}
{\thinspace .}\]

The variational form now reads

\[\int_{\Omega} (\boldsymbol{v}\cdot\nabla u + \alpha u)v{\, \mathrm{d}x} =
-\int_{\Omega} a\nabla u\cdot\nabla v{\, \mathrm{d}x}
+ \int_{\partial\Omega} a\frac{\partial u}{\partial n} v{\, \mathrm{d}s}
+ \int_{\Omega} fv {\, \mathrm{d}x}
{\thinspace .}\]

The boundary term can be developed further by noticing that \(v\neq 0\) only on \(\partial\Omega_N\),

\[\int_{\partial\Omega} a\frac{\partial u}{\partial n} v{\, \mathrm{d}s}
= \int_{\partial\Omega_N} a\frac{\partial u}{\partial n} v{\, \mathrm{d}s},\]

and that on \(\partial\Omega_N\), we have the condition \(a\frac{\partial u}{\partial n}=-g\), so the term becomes

\[-\int_{\partial\Omega_N} gv{\, \mathrm{d}s}{\thinspace .}\]

The variational form is then

\[\int_{\Omega} (\boldsymbol{v}\cdot\nabla u + \alpha u)v{\, \mathrm{d}x} =
-\int_{\Omega} a\nabla u\cdot\nabla v {\, \mathrm{d}x}
- \int_{\partial\Omega_N} g v{\, \mathrm{d}s}
+ \int_{\Omega} fv {\, \mathrm{d}x}
{\thinspace .}\]

Instead of using the integral signs we may use the inner product notation:

\[(\boldsymbol{v}\cdot\nabla u, v) + (\alpha u,v) =
- (a\nabla u,\nabla v) - (g,v)_{N} + (f,v)
{\thinspace .}\]

The subscript \(\,{}_N\) in \((g,v)_{N}\) is a notation for a line or surface integral over \(\partial\Omega_N\).

Inserting the \(u\) expansion results in

\[\begin{split}\sum_{j\in{\mathcal{I}_s}} ((\boldsymbol{v}\cdot\nabla {\psi}_j, {\psi}_i) &+ (\alpha {\psi}_j ,{\psi}_i) + (a\nabla {\psi}_j,\nabla {\psi}_i))c_j = \\
& (g,{\psi}_i)_{N} + (f,{\psi}_i) -
(\boldsymbol{v}\cdot\nabla u_0, {\psi}_i) + (\alpha u_0 ,{\psi}_i) +
(a\nabla u_0,\nabla {\psi}_i)
{\thinspace .}\end{split}\]

This is a linear system with matrix entries

\[A_{i,j} = (\boldsymbol{v}\cdot\nabla {\psi}_j, {\psi}_i) + (\alpha {\psi}_j ,{\psi}_i) + (a\nabla {\psi}_j,\nabla {\psi}_i)\]

and right-hand side entries

\[b_i = (g,{\psi}_i)_{N} + (f,{\psi}_i) -
(\boldsymbol{v}\cdot\nabla u_0, {\psi}_i) + (\alpha u_0 ,{\psi}_i) +
(a\nabla u_0,\nabla {\psi}_i),\]

for \(i,j\in{\mathcal{I}_s}\).

In the finite element method, we usually express \(u_0\) in terms of basis functions and restrict \(i\) and \(j\) to run over the degrees of freedom that are not prescribed as Dirichlet conditions. However, we can also keep all the \(c_j\), \(j\in{\mathcal{I}_s}\), as unknowns drop the \(u_0\) in the expansion for \(u\), and incorporate all the known \(c_j\) values in the linear system. This has been explained in detail in the 1D case.

We consider an integral of the type

\[\int_{{\Omega}^{(e)}} a(\boldsymbol{x})\nabla{\varphi}_i\cdot\nabla{\varphi}_j{\, \mathrm{d}x},\]

where the \({\varphi}_i\) functions are finite element basis functions in 2D or 3D, defined in the physical domain. Suppose we want to calculate this integral over a reference cell, denoted by \(\tilde\Omega^r\), in a coordinate system with coordinates \(\boldsymbol{X} = (X_0, X_1)\) (2D) or \(\boldsymbol{X} = (X_0, X_1, X_2)\) (3D). The mapping between a point \(\boldsymbol{X}\) in the reference coordinate system and the corresponding point \(\boldsymbol{x}\) in the physical coordinate system is given by a vector relation \(\boldsymbol{x}(\boldsymbol{X})\). The corresponding Jacobian, \(J\), of this mapping has entries

\[J_{i,j}=\frac{\partial x_j}{\partial X_i}{\thinspace .}\]

The change of variables requires \({\, \mathrm{d}x}\) to be replaced by \(\det J{\, \mathrm{d}X}\). The derivatives in the \(\nabla\) operator in the variational form are with respect to \(\boldsymbol{x}\), which we may denote by \(\nabla_{\boldsymbol{x}}\). The \({\varphi}_i(\boldsymbol{x})\) functions in the integral are replaced by local basis functions \({\tilde{\varphi}}_r(\boldsymbol{X})\) so the integral features \(\nabla_{\boldsymbol{x}}{\tilde{\varphi}}_r(\boldsymbol{X})\). We readily have \(\nabla_{\boldsymbol{X}}{\tilde{\varphi}}_r(\boldsymbol{X})\) from formulas for the basis functions in the reference cell, but the desired quantity \(\nabla_{\boldsymbol{x}}{\tilde{\varphi}}_r(\boldsymbol{X})\) requires some efforts to compute. All the details are provided below.

Let \(i=q(e,r)\) and consider two space dimensions. By the chain rule,

\[\frac{\partial {\tilde{\varphi}}_r}{\partial X} =
\frac{\partial {\varphi}_i}{\partial X} =
\frac{\partial {\varphi}_i}{\partial x}\frac{\partial x}{\partial X} +
\frac{\partial {\varphi}_i}{\partial y}\frac{\partial y}{\partial X},\]

and

\[\frac{\partial {\tilde{\varphi}}_r}{\partial Y} =
\frac{\partial {\varphi}_i}{\partial Y} =
\frac{\partial {\varphi}_i}{\partial x}\frac{\partial x}{\partial Y} +
\frac{\partial {\varphi}_i}{\partial y}\frac{\partial y}{\partial Y}
{\thinspace .}\]

We can write these two equations as a vector equation

\[\begin{split}\left[\begin{array}{c}
\frac{\partial {\tilde{\varphi}}_r}{\partial X}\\
\frac{\partial {\tilde{\varphi}}_r}{\partial Y}
\end{array}\right]
=
\left[\begin{array}{cc}
\frac{\partial x}{\partial X} & \frac{\partial y}{\partial X}\\
\frac{\partial x}{\partial Y} & \frac{\partial y}{\partial Y}
\end{array}\right]
\left[\begin{array}{c}
\frac{\partial {\varphi}_i}{\partial x}\\
\frac{\partial {\varphi}_i}{\partial y}
\end{array}\right]\end{split}\]

Identifying

\[\begin{split}\nabla_{\boldsymbol{X}}{\tilde{\varphi}}_r = \left[\begin{array}{c}
\frac{\partial {\tilde{\varphi}}_r}{\partial X}\\
\frac{\partial {\tilde{\varphi}}_r}{\partial Y}
\end{array}\right],
\quad
J =
\left[\begin{array}{cc}
\frac{\partial x}{\partial X} & \frac{\partial y}{\partial X}\\
\frac{\partial x}{\partial Y} & \frac{\partial y}{\partial Y}
\end{array}\right],
\quad
\nabla_{\boldsymbol{x}}{\varphi}_r =
\left[\begin{array}{c}
\frac{\partial {\varphi}_i}{\partial x}\\
\frac{\partial {\varphi}_i}{\partial y}
\end{array}\right],\end{split}\]

we have the relation

\[\nabla_{\boldsymbol{X}}{\tilde{\varphi}}_r = J\cdot\nabla_{\boldsymbol{x}}{\varphi}_i,\]

which we can solve with respect to \(\nabla_{\boldsymbol{x}}{\varphi}_i\):

\[\nabla_{\boldsymbol{x}}{\varphi}_i = J^{-1}\cdot\nabla_{\boldsymbol{X}}{\tilde{\varphi}}_r{\thinspace .}\]

On the reference cell, \({\varphi}_i(\boldsymbol{x}) = {\tilde{\varphi}}_r(\boldsymbol{X})\), so

\[\nabla_{\boldsymbol{x}}{\tilde{\varphi}}_r(\boldsymbol{X}) = J^{-1}(\boldsymbol{X})\cdot\nabla_{\boldsymbol{X}}{\tilde{\varphi}}_r(\boldsymbol{X}){\thinspace .}\]

This means that we have the following transformation of the integral in the physical domain to its counterpart over the reference cell:

\[\int_{\Omega}^{(e)} a(\boldsymbol{x})\nabla_{\boldsymbol{x}}{\varphi}_i\cdot\nabla_{\boldsymbol{x}}{\varphi}_j{\, \mathrm{d}x}
\int_{\tilde\Omega^r} a(\boldsymbol{x}(\boldsymbol{X}))(J^{-1}\cdot\nabla_{\boldsymbol{X}}{\tilde{\varphi}}_r)\cdot
(J^{-1}\cdot\nabla{\tilde{\varphi}}_s)\det J{\, \mathrm{d}X}\]

Integrals are normally computed by numerical integration rules. For multi-dimensional cells, various families of rules exist. All of them are similar to what is shown in 1D: \(\int f {\, \mathrm{d}x}\approx \sum_jw_if(\boldsymbol{x}_j)\), where \(w_j\) are weights and \(\boldsymbol{x}_j\) are corresponding points.

The file numint.py contains the functions
`quadrature_for_triangles(n)` and `quadrature_for_tetrahedra(n)`,
which returns lists of points and weights corresponding to integration
rules with `n` points over the reference triangle
with vertices \((0,0)\), \((1,0)\), \((0,1)\), and the reference tetrahedron
with vertices \((0,0,0)\), \((1,0,0)\), \((0,1,0)\), \((0,0,1)\),
respectively. For example, the first two rules for integration over
a triangle have 1 and 3 points:

```
>>> import numint
>>> x, w = numint.quadrature_for_triangles(num_points=1)
>>> x
[(0.3333333333333333, 0.3333333333333333)]
>>> w
[0.5]
>>> x, w = numint.quadrature_for_triangles(num_points=3)
>>> x
[(0.16666666666666666, 0.16666666666666666),
(0.66666666666666666, 0.16666666666666666),
(0.16666666666666666, 0.66666666666666666)]
>>> w
[0.16666666666666666, 0.16666666666666666, 0.16666666666666666]
```

Rules with 1, 3, 4, and 7 points over the triangle will exactly integrate polynomials of degree 1, 2, 3, and 4, respectively. In 3D, rules with 1, 4, 5, and 11 points over the tetrahedron will exactly integrate polynomials of degree 1, 2, 3, and 4, respectively.

We shall now provide some formulas for piecewise linear \({\varphi}_i\) functions
and their integrals *in the physical coordinate system*.
These formulas make it convenient to compute with P1 elements without
the need to work in the reference coordinate system and deal with mappings
and Jacobians.
A lot of computational and algorithmic details are hidden by this approach.

Let \(\Omega^{(e)}\) be cell number \(e\), and let the three vertices have global vertex numbers \(I\), \(J\), and \(K\). The corresponding coordinates are \((x_{I},y_{I})\), \((x_{J},y_{J})\), and \((x_{K},y_{K})\). The basis function \({\varphi}_I\) over \(\Omega^{(e)}\) have the explicit formula

(2)\[ {\varphi}_I (x,y) = \frac{1}{2}\Delta \left( \alpha_I + \beta_Ix
+ \gamma_Iy\right),\]

where

(3)\[ \alpha_I = x_{J}y_{K} - x_{K}y_{J},\]

(4)\[ \beta_I = y_{J} - y_{K},\]

(5)\[ \gamma_I = x_{K} - x_{J},\]

\[2\Delta = \det\left(\begin{array}{rrr}
1 x_{I} y_{I}\]

\[1 x_{J} y_{J}\]

(6)\[ 1 x_{K} y_{K} \end{array}\right)
{\thinspace .}\]

The quantity \(\Delta\) is the area of the cell.

The following formula is often convenient when computing element matrices and vectors:

(7)\[ \int_{\Omega^{(e)}} {\varphi}_I^{p}{\varphi}_J^{q}{\varphi}_K^{r} dx dy =
{p!q!r!\over (p+q+r+2)!}2\Delta\]\[ {\thinspace .}\]

(Note that the \(q\) in this formula is not to be mixed with the \(q(e,r)\) mapping of degrees of freedom.)

As an example, the element matrix entry \(\int_{\Omega^{(e)}} {\varphi}_I{\varphi}_J{\, \mathrm{d}x}\) can be computed by setting \(p=q=1\) and \(r=0\), when \(I\neq J\), yielding \(\Delta/12\), and \(p=2\) and \(q=r=0\), when \(I=J\), resulting in \(\Delta/6\). We collect these numbers in a local element matrix:

\[\begin{split}\frac{\Delta}{12}
\left[\begin{array}{ccc}
2 & 1 & 1\\
1 & 2 & 1\\
1 & 1 & 2
\end{array}\right]\end{split}\]

The common element matrix entry \(\int_{\Omega^{(e)}} \nabla{\varphi}_I\cdot\nabla{\varphi}_J{\, \mathrm{d}x}\), arising from a Laplace term \(\nabla^2u\), can also easily be computed by the formulas above. We have

\[\nabla{\varphi}_I\cdot\nabla{\varphi}_J =
\frac{\Delta^2}{4}(\beta_I\beta_J + \gamma_I\gamma_J) = \hbox{const},\]

so that the element matrix entry becomes \(\frac{1}{4}\Delta^3(\beta_I\beta_J + \gamma_I\gamma_J)\).

From an implementational point of view, one will work with local vertex numbers \(r=0,1,2\), parameterize the coefficients in the basis functions by \(r\), and look up vertex coordinates through \(q(e,r)\).

Similar formulas exist for integration of P1 elements in 3D.