Skip to content

Commit 5868837

Browse files
committed
Quadrature docs
1 parent 3fbf1f5 commit 5868837

File tree

5 files changed

+106
-58
lines changed

5 files changed

+106
-58
lines changed

docs/source/element_list.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from finat.ufl.elementlist import ufl_elements
2-
# ~ from ufl.finiteelement.elementlist import ufl_elements
32
from finat.element_factory import supported_elements
43
import csv
54

docs/source/extruded-meshes.rst

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ supports a more general syntax:
304304
305305
V = FunctionSpace(mesh, element)
306306
307-
where ``element`` is a UFL :py:class:`~ufl.finiteelement.finiteelement.FiniteElement` object. This
307+
where ``element`` is a UFL :py:class:`~finat.ufl.finiteelement.FiniteElement` object. This
308308
requires generation and manipulation of ``FiniteElement`` objects.
309309

310310
Geometrically, an extruded mesh cell is the *product* of a base, "horizontal",
@@ -319,7 +319,7 @@ The ``TensorProductElement`` operator
319319
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
320320

321321
To create an element compatible with an extruded mesh, one should use
322-
the :py:class:`~ufl.finiteelement.tensorproductelement.TensorProductElement`
322+
the :py:class:`~finat.ufl.tensorproductelement.TensorProductElement`
323323
operator. For example,
324324

325325
.. code-block:: python3
@@ -359,7 +359,7 @@ but is piecewise constant horizontally.
359359

360360
A more complicated element, like a Mini horizontal element with linear
361361
variation in the vertical direction, may be built using the
362-
:py:class:`~ufl.finiteelement.enrichedelement.EnrichedElement` functionality
362+
:py:class:`~finat.ufl.enrichedelement.EnrichedElement` functionality
363363
in either of the following ways:
364364

365365
.. code-block:: python3
@@ -392,7 +392,7 @@ The ``HDivElement`` and ``HCurlElement`` operators
392392
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
393393

394394
For moderately complicated vector-valued elements,
395-
:py:class:`~ufl.finiteelement.tensorproductelement.TensorProductElement`
395+
:py:class:`~finat.ufl.tensorproductelement.TensorProductElement`
396396
does not give enough information to unambiguously produce the desired
397397
space. As an example, consider the lowest-order *Raviart-Thomas* element on a
398398
quadrilateral. The degrees of freedom live on the facets, and consist of
@@ -417,7 +417,7 @@ However, this is only scalar-valued. There are two natural vector-valued
417417
elements that can be generated from this: one of them preserves tangential
418418
continuity between elements, and the other preserves normal continuity
419419
between elements. To obtain the Raviart-Thomas element, we must use the
420-
:py:class:`~ufl.finiteelement.hdivcurl.HDivElement` operator:
420+
:py:class:`~finat.ufl.hdivcurl.HDivElement` operator:
421421

422422
.. code-block:: python3
423423
@@ -433,7 +433,7 @@ between elements. To obtain the Raviart-Thomas element, we must use the
433433
:align: center
434434

435435
The RT quadrilateral element, requiring the use
436-
of :py:class:`~ufl.finiteelement.hdivcurl.HDivElement`
436+
of :py:class:`~finat.ufl.hdivcurl.HDivElement`
437437

438438
Another reason to use these operators is when expanding a vector into a
439439
higher dimensional space. Consider the lowest-order Nedelec element of the
@@ -453,7 +453,7 @@ the product of this with a continuous element on an interval:
453453
454454
This element still only has two components. To expand this into a
455455
three-dimensional curl-conforming element, we must use the
456-
:py:class:`~ufl.finiteelement.hdivcurl.HCurlElement` operator; the syntax is:
456+
:py:class:`~finat.ufl.hdivcurl.HCurlElement` operator; the syntax is:
457457

458458
.. code-block:: python3
459459

docs/source/manual.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Manual
1919
duals
2020
interpolation
2121
point-evaluation
22+
quadrature
2223
external_operators
2324
adjoint
2425
visualisation

docs/source/quadrature.rst

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
.. only:: html
2+
3+
.. contents::
4+
5+
Quadrature rules
6+
================
7+
8+
To numerically compute the integrals in the variational formulation,
9+
a quadrature rule is required.
10+
By default, Firedrake obtains a quadrature rule by estimating the polynomial
11+
degree of the integrands within a :py:class:`ufl.Form`. Sometimes
12+
this estimate might be quite large, and a warning like this one will be raised:
13+
14+
.. code-block::
15+
16+
tsfc:WARNING Estimated quadrature degree 13 more than tenfold greater than any argument/coefficient degree (max 1)
17+
18+
Sometimes the estimated quadrature degree might be even in the hundreds or thousands,
19+
rendering the integration prohibitively expensive.
20+
21+
Specifying the quadrature rule
22+
------------------------------
23+
24+
To manually override the default, the
25+
quadrature degree can be prescribed on each integral :py:class:`~ufl.measure.Measure`,
26+
27+
.. code-block::
28+
29+
inner(sin(u)**4, v) * dx(degree=4)
30+
31+
Setting ``degree=4`` means that the quadrature rule will be exact only for integrands
32+
of total polynomial degree up to 4. This, of course, will introduce a greater numerical error than the default.
33+
34+
The default quadrature degree estimation may be overridden by setting the ``"quadrature_degree"`` in
35+
the ``form_compiler_parameters`` dictionary passed on to
36+
:py:func:`~.solve`, :py:func:`~.project`, or :py:class:`~.NonlinearVariationalProblem`.
37+
38+
.. code-block::
39+
40+
F = inner(grad(u), grad(v))*dx(degree=0) + inner(exp(u), v)*dx - inner(1, v)*dx
41+
42+
solve(F == 0, u, form_compiler_parameters={"quadrature_degree": 4})
43+
44+
In the example above, only the integrals with unspecified quadrature degree
45+
will be computed on a quadrature rule that exactly integrates polynomials of
46+
the degree set in ``form_compiler_parameters``.
47+
48+
Another way to specify the quadrature rule is through the ``scheme`` keyword. This could be
49+
either a :py:class:`~finat.quadrature.QuadratureRule`, or a string. Supported string values
50+
are ``"default"``, ``"canonical"``, and ``"lump"``. For more details see
51+
:py:func:`~FIAT.quadrature_schemes.create_quadrature`.
52+
53+
Lumped quadrature schemes
54+
-------------------------
55+
56+
Spectral elements, such as Gauss-Legendre-Lobatto and KMV, may be used with
57+
lumped quadrature schemes to produce a diagonal mass matrix.
58+
59+
.. code-block::
60+
61+
degree = 3
62+
V = FunctionSpace(mesh, "KMV", degree)
63+
u = TrialFunction(V)
64+
v = TestFunction(V)
65+
66+
inner(u, v) * dx(scheme="lump", degree=degree)
67+
68+
.. Note::
69+
70+
To obtain the lumped mass matrix with ``scheme="lump"``,
71+
the ``degree`` argument should match the degree of the :py:class:`~finat.ufl.finiteelement.FiniteElement`.
72+
73+
74+
The Quadrature Space
75+
--------------------
76+
77+
It is possible to define a finite element :py:class:`~.Function` on a quadrature rule.
78+
The ``"Quadrature"`` and ``"Boundary Quadrature"`` spaces are useful to
79+
interpolate data at quadrature points on cell interiors and cell boundaries,
80+
respectively.
81+
82+
.. code-block::
83+
84+
Q = FunctionSpace(mesh, "Quadrature", degree=quad_degree, quad_scheme=quad_scheme)
85+
86+
The ``quad_scheme`` keyword argument again may be either
87+
:py:class:`~finat.quadrature.QuadratureRule` or a string.
88+
If a :py:class:`~.Function` in the ``"Quadrature"`` space appears within an
89+
integral, Firedrake will automatically select the quadrature rule that corresponds
90+
to ``dx(degree=quad_degree, scheme=quad_scheme)`` to match the one associated
91+
with the quadrature space.

docs/source/variational-problems.rst

Lines changed: 7 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ family such as ``"Raviart-Thomas"``. Secondly, you may use the
180180
family, which gives a vector-valued space where each component is
181181
identical to the appropriate scalar-valued
182182
:py:class:`~.FunctionSpace`. Thirdly, you can create a
183-
:py:class:`~ufl.classes.VectorElement` directly (which is itself
183+
:py:class:`~finat.ufl.mixedelement.VectorElement` directly (which is itself
184184
*vector-valued* and pass that to the :py:func:`~.FunctionSpace`
185185
constructor).
186186

@@ -275,7 +275,7 @@ Firedrake supports the use of the following finite elements.
275275
:file: element_list.csv
276276

277277
In addition, the
278-
:py:class:`~ufl.finiteelement.tensorproductelement.TensorProductElement`
278+
:py:class:`~finat.ufl.tensorproductelement.TensorProductElement`
279279
operator can be used to create product elements on extruded meshes.
280280

281281
Element variants
@@ -289,16 +289,17 @@ continuous elements these are the Gauss-Lobatto-Legendre points.
289289
For CG and DG spaces on simplices, Firedrake offers both equispaced points and
290290
the better conditioned recursive Legendre points from :cite:`Isaac2020` via the
291291
`recursivenodes`_ module. These are selected by passing ``variant="equispaced"``
292-
or ``variant="spectral"`` to the :py:class:`~ufl.classes.FiniteElement` or
292+
or ``variant="spectral"`` to the :py:class:`~finat.ufl.finiteelement.FiniteElement` or
293293
:py:func:`~.FunctionSpace` constructors. For example:
294294

295295
.. code-block:: python3
296296
297297
fe = FiniteElement("RTCE", quadrilateral, 2, variant="equispaced")
298298
299-
For CG and DG spaces, and most tensor-product elements, the default is the spectral variant.
299+
For CG and DG spaces, and most tensor-product elements, the default is ``variant="spectral"``.
300300

301-
Integral-type degrees of freedom are also available through ``variant="integral"``. For instance,
301+
Integral-type degrees of freedom are also available through ``variant="integral"``. These
302+
enable orthogonal bases for DG on any cell type:
302303

303304
.. code-block:: python3
304305
@@ -310,7 +311,7 @@ can be increased also through the variant option. For instance, ``variant="integ
310311
will use a quadrature that exactly evaluates the degrees of freedom on polynomials of
311312
4 degrees higher than that of the space.
312313

313-
The key role of integral-type degrees of freedom is to nearly preserve curl-free or
314+
Integral-type degrees of freedom are useful to nearly preserve curl-free or
314315
divergence-free functions when interpolating into the finite element space.
315316
H(curl) and H(div) elements, such as Nédélec, Brezzi-Douglas-Marini, and Raviart-Thomas,
316317
have ``variant="integral"`` as default. These elements also support ``variant="point"``,
@@ -710,50 +711,6 @@ we can write:
710711
c.assign(t)
711712
712713
713-
Specifying the quadrature rule
714-
------------------------------
715-
716-
To numerically compute the integrals in the variational formulation,
717-
a quadrature rule is required.
718-
By default, Firedrake obtains a quadrature rule by estimating the polynomial
719-
degree of the integrands within a :py:class:`ufl.Form`. Sometimes
720-
this estimate might be quite large, and a warning like this one will be raised:
721-
722-
.. code-block::
723-
724-
tsfc:WARNING Estimated quadrature degree 13 more than tenfold greater than any argument/coefficient degree (max 1)
725-
726-
This might increase memory and computational requirements. To manually override the default, the
727-
quadrature degree can be prescribed on each integral,
728-
729-
.. code-block::
730-
731-
inner(sin(u)**4, v) * dx(degree=4)
732-
733-
This, of course, will introduce a variational crime.
734-
735-
736-
Another way to specify the quadrature rule is through the ``scheme`` keyword. This could be
737-
either a :py:class:`~finat.quadrature.QuadratureRule`, or a string. Supported string values
738-
are ``"default"``, ``"canonical"``, and ``"lump"``. For more details see
739-
:py:func:`~FIAT.quadrature_schemes.create_quadrature`. Spectral elements, such as
740-
Gauss-Legendre-Lobatto and KMV, may be used with lumped quadrature schemes to
741-
produce a diagonal mass matrix.
742-
743-
.. code-block::
744-
745-
degree = 3
746-
V = FunctionSpace(mesh, "KMV", degree)
747-
u = TrialFunction(V)
748-
v = TestFunction(V)
749-
750-
inner(u, v) * dx(scheme="lump", degree=degree)
751-
752-
.. Note::
753-
754-
For ``scheme="lump"`` the ``degree`` argument is interpreted as the degree of :py:func:`~.FunctionSpace`.
755-
756-
757714
.. _more_complicated_forms:
758715

759716
More complicated forms

0 commit comments

Comments
 (0)