Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
523e528
Add __all__ to init.py
Aug 24, 2026
6599922
Fix __all__ so compiles
Aug 24, 2026
2be45cc
Add utils to import list
Aug 24, 2026
43c3bb5
Attempt to fix failing unit tests
Aug 28, 2026
213c7cf
Clean up changes in init file
Sep 1, 2026
5234fc9
Remove unnecessary lines
Sep 1, 2026
7ab998e
Adjust indentation
Sep 1, 2026
2b1fb07
Alter spacing to pass linting tests
Sep 1, 2026
c3c5760
Move utils import
Sep 1, 2026
cf4e29a
Remove duplicate objects imports - for sphix tests
Sep 1, 2026
23bc6f3
Add function to all
Sep 1, 2026
b579991
Add spiked module
Sep 2, 2026
d0ebdbb
Apply suggestion from @connorjward
nwng04 Sep 2, 2026
e427efb
Add utils as an import to tests and remove whitespacing
Sep 2, 2026
cbae918
Remove some duplicate modules from export lists
Sep 2, 2026
593a1a8
First attempt at fixing sphinx failurs, specifying module locations
Sep 2, 2026
9136b70
Fix some duplicate refs
connorjward Sep 3, 2026
068e134
apidoc improvements
connorjward Sep 3, 2026
7ed599e
Remove whitespaces in deprecation.py
Sep 3, 2026
340b496
Specify module locations in demos
Sep 3, 2026
ab5c790
Amend module locations
Sep 3, 2026
0f838f4
Update utils inport with complex_mode
Sep 5, 2026
68d753e
Fix imports in tests
Sep 5, 2026
e7f49f1
Further refine references to modules in firedrake
Sep 5, 2026
4e22b4e
fix vtk_output references
Sep 6, 2026
168b4c1
Comment out __all__ declarations in firedrake modules
Sep 6, 2026
4e3e9d8
Revert commenting of __all__ declarations
Sep 6, 2026
73849c3
Edit randomfunctiongen in __init__.py and specify refs.
Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions demos/adaptive_multigrid/adaptive_multigrid.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Adaptive Multigrid Methods
Contributed by Anurag Rao.

The purpose of this demo is to show how to use Firedrake's multigrid solver on a hierarchy of adaptively refined Netgen meshes.
A :func:`~.MeshHierarchy` is not restricted to uniform refinement: the same object records the parent child relations between adaptively refined meshes, and grows a level at a time as the solution is resolved.
A :func:`MeshHierarchy <firedrake.MeshHierarchy>` is not restricted to uniform refinement: the same object records the parent child relations between adaptively refined meshes, and grows a level at a time as the solution is resolved.
We will first have a look at how to construct such a hierarchy from Netgen meshes, then we will consider a solution to the Poisson problem on an L-shaped domain, and finally we will use the hierarchy to construct a scalable solver.
We begin by importing the necessary libraries ::

Expand All @@ -27,13 +27,13 @@ We begin with the L-shaped domain, which we build as the union of two rectangles
ngmsh = geo.GenerateMesh(maxh=0.5)
mesh = Mesh(ngmsh)

It is important to convert the initial Netgen mesh into a Firedrake mesh before constructing the :func:`~.MeshHierarchy`. To call the constructor to the hierarchy, we must pass the initial mesh. Our initial mesh looks like this:
It is important to convert the initial Netgen mesh into a Firedrake mesh before constructing the :func:`MeshHierarchy <firedrake.MeshHierarchy>`. To call the constructor to the hierarchy, we must pass the initial mesh. Our initial mesh looks like this:

.. figure:: initial_mesh.png
:align: center
:alt: Initial mesh.

We initialize the :func:`~.MeshHierarchy` here. The default of zero uniform refinement levels gives a hierarchy holding just the initial mesh, which we will grow adaptively below; passing a positive number instead would start us off with that many uniformly refined levels, and the adaptive levels would stack on top of them just the same: ::
We initialize the :func:`MeshHierarchy <firedrake.MeshHierarchy>` here. The default of zero uniform refinement levels gives a hierarchy holding just the initial mesh, which we will grow adaptively below; passing a positive number instead would start us off with that many uniformly refined levels, and the adaptive levels would stack on top of them just the same: ::

mh = MeshHierarchy(mesh)

Expand All @@ -45,7 +45,7 @@ Now we can define a simple Poisson problem

- \nabla^2 u = f \text{ in } \Omega, \quad u = 0 \text{ on } \partial \Omega.

Our approach strongly follows the similar problem in this `lecture course <https://github.com/pefarrell/icerm2024>`_. We define the function ``solve_poisson``. The first lines correspond to finding a solution in the CG1 space. The right-hand side is set to be the constant function equal to 1. Since we want Dirichlet boundary conditions, we construct the :class:`~.DirichletBC` object and apply it to the entire boundary: ::
Our approach strongly follows the similar problem in this `lecture course <https://github.com/pefarrell/icerm2024>`_. We define the function ``solve_poisson``. The first lines correspond to finding a solution in the CG1 space. The right-hand side is set to be the constant function equal to 1. Since we want Dirichlet boundary conditions, we construct the :class:`DirichletBC <firedrake.DirichletBC>` object and apply it to the entire boundary: ::

def solve_poisson(mesh, params):
V = FunctionSpace(mesh, "CG", 1)
Expand Down Expand Up @@ -173,14 +173,14 @@ With these helper functions complete, we can solve the system iteratively. In th
if level != refinements - 1:
mh.adapt(eta, theta)

To perform Dörfler marking, refine the current mesh, and add the mesh to the hierarchy, we use the :meth:`~.HierarchyBase.adapt` method. In this method the input is the recently computed error estimator ``eta`` and the Dörfler marking parameter ``theta``. The method always performs this on the current fine mesh in the hierarchy.
To mark cells by some other criterion, refine the finest mesh yourself and add the result, which is all that :meth:`~.HierarchyBase.adapt` does once it has marked:
To perform Dörfler marking, refine the current mesh, and add the mesh to the hierarchy, we use the :meth:`HierarchyBase.adapt <firedrake.HierarchyBase.adapt>` method. In this method the input is the recently computed error estimator ``eta`` and the Dörfler marking parameter ``theta``. The method always performs this on the current fine mesh in the hierarchy.
To mark cells by some other criterion, refine the finest mesh yourself and add the result, which is all that :meth:`HierarchyBase.adapt <firedrake.HierarchyBase.adapt>` does once it has marked:

.. code-block:: python

mh.add_mesh(mh[-1].refine_marked_elements(markers))

Here ``markers`` is a DG0 function whose value on each cell is the number of times to refine it. If the mesh was instead produced by some procedure Firedrake cannot trace the parent child relations through, pass those cell maps to :meth:`~.HierarchyBase.add_mesh` explicitly.
Here ``markers`` is a DG0 function whose value on each cell is the number of times to refine it. If the mesh was instead produced by some procedure Firedrake cannot trace the parent child relations through, pass those cell maps to :meth:`HierarchyBase.add_mesh <firedrake.HierarchyBase.add_mesh>` explicitly.
The meshes now refine according to the error estimator. The error estimators at levels 3,5, and 15 are shown below. Zooming into the vertex of the L-shape at level 15 shows the error indicator remains strongest there. Further refinements will focus on that area.

+-------------------------------+-------------------------------+-------------------------------+
Expand Down
4 changes: 2 additions & 2 deletions demos/boussinesq/boussinesq.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ and the (strongly enforced) Dirichlet boundary conditions on :math:`u` are enfor

bc_u = DirichletBC(Z.sub(0), 0, "on_boundary")

At this point we could form and solve a :class:`~.NonlinearVariationalProblem`
At this point we could form and solve a :class:`NonlinearVariationalProblem <firedrake.NonlinearVariationalProblem>`
using :code:`F` and :code:`bc_u`. However, the resultant problem has a nullspace of
dimension 2, corresponding to (i) shifting :math:`p` by a constant :math:`C_1`
and (ii) shifting :math:`l` by a constant :math:`C_2` while simultaneuosly shifting
:math:`T_{\textrm{aux}}` by :math:`-C_2`.

One way of dealing with nullspaces in Firedrake is to pass a :code:`nullspace` and
:code:`transpose_nullspace` to :class:`~.NonlinearVariationalSolver`. However, sometimes
:code:`transpose_nullspace` to :class:`NonlinearVariationalSolver <firedrake.NonlinearVariationalSolver>`. However, sometimes
this approach may not be practical. First, for nonlinear problems with Jacobians that
are not symmetric, it may not obvious what the :code:`transpose_nullspace` is. A second
reason is that, when using customised PETSc linear solvers, it may be desirable
Expand Down
16 changes: 8 additions & 8 deletions demos/camassa-holm/camassaholm.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,23 @@ We then set the parameters for the scheme. ::
dt = 0.1
Dt = Constant(dt)

These are set with type :class:`~.Constant` so that the values can be
These are set with type :class:`constant <firedrake.Constant>` so that the values can be
changed without needing to regenerate code.

We use a :func:`periodic mesh <.PeriodicIntervalMesh>` of width 40
We use a :func:`periodic mesh <firedrake.PeriodicIntervalMesh>` of width 40
with 100 cells, ::

n = 100
mesh = PeriodicIntervalMesh(n, 40.0)

and build a :class:`mixed function space <.MixedFunctionSpace>` for the
and build a :class:`mixed function space <firedrake.MixedFunctionSpace>` for the
two variables. ::

V = FunctionSpace(mesh, "CG", 1)
W = MixedFunctionSpace((V, V))

We construct a :class:`~.Function` to store the two variables at time
level ``n``, and :attr:`~.Function.subfunctions` it so that we can
We construct a :class:`function <firedrake.Function>` to store the two variables at time
level ``n``, and :attr:`subfunctions <firedrake.Function.subfunctions>` it so that we can
interpolate the initial condition into the two components. ::

w0 = Function(W)
Expand Down Expand Up @@ -130,7 +130,7 @@ solver since the problem is one dimensional). ::

Next we build the weak form of the timestepping algorithm. This is expressed
as a mixed nonlinear problem, which must be written as a bilinear form
that is a function of the output :class:`~.Function` ``w1``. ::
that is a function of the output :class:`function <firedrake.Function>` ``w1``. ::

p, q = TestFunctions(W)

Expand All @@ -140,7 +140,7 @@ that is a function of the output :class:`~.Function` ``w1``. ::
m0, u0 = split(w0)

Note the use of :func:`split(w1) <ufl.split_functions.split>` here, which splits up a
:class:`~.Function` so that it may be inserted into a UFL
:class:`function <firedrake.Function>` so that it may be inserted into a UFL
expression. ::

mh = 0.5*(m1 + m0)
Expand All @@ -161,7 +161,7 @@ rather than blocked system. ::
'ksp_type': 'preonly',
'pc_type': 'lu'})

Next we use the other form of :attr:`~.Function.subfunctions`, ``w0.subfunctions``,
Next we use the other form of :attr:`subfunctions <firedrake.Function.subfunctions>`, ``w0.subfunctions``,
which is the way to split up a Function in order to access its data
e.g. for output. ::

Expand Down
2 changes: 1 addition & 1 deletion demos/deflation/deflation.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ We implement the usual weak formulation of the equation in Firedrake as standard
bcs = DirichletBC(V, 0, "on_boundary")
problem = NonlinearVariationalProblem(F, u, bcs)

Applying deflation requires two ingredients: the :class:`~.DeflatedSNES` nonlinear solver, and a :class:`~.Deflation` object. The :class:`~.Deflation` object records the solutions to be deflated, and specifies the sense of distance to use in deflation. In this example we use the metric induced by the :math:`L^2(\Omega)` inner product: ::
Applying deflation requires two ingredients: the :class:`DeflatedSNES <firedrake.deflation.DeflatedSNES>` nonlinear solver, and a :class:`Deflation <firedrake.deflation.Deflation>` object. The :class:`Deflation <firedrake.deflation.Deflation>` object records the solutions to be deflated, and specifies the sense of distance to use in deflation. In this example we use the metric induced by the :math:`L^2(\Omega)` inner product: ::

sp = {"snes_type": "python",
"snes_python_type": "firedrake.DeflatedSNES",
Expand Down
28 changes: 14 additions & 14 deletions demos/fast_diagonalisation/fast_diagonalisation_poisson.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The fast diagonalisation method produces a basis of discrete eigenfunctions.
These are polynomials, and can be efficiently computed on tensor
product-elements by solving an eigenproblem on the interval. Therefore, we will
require quadrilateral or hexahedral meshes. Currently, the solver only supports
extruded hexahedral meshes, so we must create an :func:`~.ExtrudedMesh`. ::
extruded hexahedral meshes, so we must create an :func:`ExtrudedMesh <firedrake.ExtrudedMesh>`. ::

from firedrake import *

Expand All @@ -33,14 +33,14 @@ Defining the problem: the Poisson equation

Having defined the mesh we now need to set up our problem. The crucial step
for fast diagonalisation is a special choice of basis functions. We obtain them
by passing ``variant="fdm"`` to the :func:`~.FunctionSpace` constructor. The
by passing ``variant="fdm"`` to the :func:`function space <firedrake.FunctionSpace>` constructor. The
solvers in this demo work also with other element variants, but each iteration
would involve an additional a basis transformation. To stress-test the solver,
we prescribe a random :class:`~.Cofunction` as right-hand side.
we prescribe a random :class:`Cofunction <firedrake.Cofunction>` as right-hand side.

We'll demonstrate a few different sets of solver parameters, so let's define a
function that takes in set of parameters and uses them on a
:class:`~.LinearVariationalSolver`. ::
:class:`linear variational solver <firedrake.LinearVariationalSolver>`. ::


def run_solve(degree, parameters):
Expand All @@ -65,8 +65,8 @@ Specifying the solver
The solver avoids the assembly of a matrix with dense element submatrices, and
instead applies a matrix-free conjugate gradient method with a preconditioner
obtained by assembling a sparse matrix. This is done through the python type
preconditioner :class:`~.FDMPC`. We define a function that enables us to
compose :class:`~.FDMPC` with an inner relaxation. ::
preconditioner :class:`FDMPC <firedrake.FDMPC>`. We define a function that enables us to
compose :class:`FDMPC <firedrake.FDMPC>` with an inner relaxation. ::


def fdm_params(relax):
Expand All @@ -93,16 +93,16 @@ using a sparse direct LU factorization. ::


.. note::
On this Cartesian mesh, the sparse operator constructed by :class:`~.FDMPC`
On this Cartesian mesh, the sparse operator constructed by :class:`FDMPC <firedrake.FDMPC>`
corresponds to the original operator. This is no longer the case with non-Cartesian
meshes or more general PDEs, as the FDM basis only diagonalises very specific
problems. For such cases, :class:`~.FDMPC` will produce a sparse
problems. For such cases, :class:`FDMPC <firedrake.FDMPC>` will produce a sparse
approximation of the original operator.

Moving on to a more complicated solver, we'll employ a two-level solver with
the lowest-order coarse space via :class:`~.P1PC`. As the fine level
the lowest-order coarse space via :class:`P1PC <firedrake.P1PC>`. As the fine level
relaxation we define an additive Schwarz method on vertex-star patches
implemented via :class:`~.ASMExtrudedStarPC` as we have an extruded mesh.
implemented via :class:`ASMExtrudedStarPC <firedrake.ASMExtrudedStarPC>` as we have an extruded mesh.
In addition we specify `"use_coloring"` to group non-overlapping subsets of
patches into sparse block-diagonal matrices via a mesh coloring, which reduces
the overhead of calling many KSP solves for each patch.::
Expand Down Expand Up @@ -143,17 +143,17 @@ We observe degree-independent iteration counts:
Static condensation
-------------------

Finally, we construct :class:`~.FDMPC` solver parameters using static
Finally, we construct :class:`FDMPC <firedrake.FDMPC>` solver parameters using static
condensation. The fast diagonalisation basis diagonalises the operator on cell
interiors. So we define a solver that splits the interior and facet degrees of
freedom via :class:`~.FacetSplitPC` and fieldsplit options. We set the option
``fdm_static_condensation`` to tell :class:`~.FDMPC` to assemble a 2-by-2 block
freedom via :class:`FacetSplitPC <firedrake.FacetSplitPC>` and fieldsplit options. We set the option
``fdm_static_condensation`` to tell :class:`FDMPC <firedrake.FDMPC>` to assemble a 2-by-2 block
preconditioner where the lower-right block is replaced by the Schur complement
resulting from eliminating the interior degrees of freedom. The Krylov
solver is posed on the full set of degrees of freedom, and the preconditioner
applies a symmetrized multiplicative sweep on the interior and the facet
degrees of freedom. In general, we are not able to fully eliminate the
interior, as the sparse operator constructed by :class:`~.FDMPC` is only an
interior, as the sparse operator constructed by :class:`FDMPC <firedrake.FDMPC>` is only an
approximation on non-Cartesian meshes. We apply point-Jacobi on the interior
block, and the two-level additive Schwarz method on the facets. ::

Expand Down
4 changes: 2 additions & 2 deletions demos/linear-wave-equation/linear_wave_equation.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Output the initial conditions::
outfile.write(phi)

We next establish a boundary condition object. Since we have time-dependent
boundary conditions, we first create a :class:`.Constant` to hold the
boundary conditions, we first create a :class:`Constant <firedrake.Constant>` to hold the
value and use that::

bcval = Constant(0.0)
Expand Down Expand Up @@ -128,7 +128,7 @@ Step forward :math:`\phi` by the second half timestep::
phi -= dt / 2 * p

Advance time and output as appropriate, note how we pass the current
timestep value into the :meth:`~.VTKFile.write` method, so that when
timestep value into the :meth:`write <firedrake.VTKFile.write>` method, so that when
visualising the results Paraview will use it::

t += dt
Expand Down
2 changes: 1 addition & 1 deletion demos/ma-demo/ma-demo.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ We then combine them together in a mixed function space. ::
W = V*Sigma

Next, we set up the source function, which must integrate to the area
of the domain. Note how in the integration of the :class:`~.Constant`
of the domain. Note how in the integration of the :class:`constant <firedrake.Constant>`
one, we must explicitly specify the domain we wish to integrate over. ::

x, y = SpatialCoordinate(mesh)
Expand Down
2 changes: 1 addition & 1 deletion demos/matrix_free/navier_stokes.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ in a ``try/except`` block. ::
else:
raise e

Now we'll show an example using the :class:`~.PCDPC` preconditioner
Now we'll show an example using the :class:`PCDPC <firedrake.PCDPC>` preconditioner
that implements the pressure convection-diffusion approximation to the
pressure Schur complement. We'll need more solver parameters this
time, so again we'll set those up in a dictionary. ::
Expand Down
2 changes: 1 addition & 1 deletion demos/matrix_free/poisson.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ unassembled operator using the ``"mat_type"`` solver parameter.::
"pc_type": "none",
"ksp_monitor": None})

Finally, we demonstrate the use of a :class:`.AssembledPC`
Finally, we demonstrate the use of a :class:`AssembledPC <firedrake.AssembledPC>`
preconditioner. This uses matrix-free actions but preconditions the
Krylov iterations with an incomplete LU factorisation of the assembled
operator.::
Expand Down
2 changes: 1 addition & 1 deletion demos/matrix_free/rayleigh-benard.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Now for the solve. ::
Finally, we'll demonstrate recursive fieldsplitting. We'll use the
same multiplicative fieldsplit preconditioner for the
velocity-pressure and temperature blocks, but we'll precondition the
Navier-Stokes part with :class:`~.PCDPC` using a lower Schur
Navier-Stokes part with :class:`PCDPC <firedrake.PCDPC>` using a lower Schur
complement factorisation, and approximately invert the temperature
block using algebraic multigrid. There are lots of parameters here,
so let's run through them. Since there are many options here, in
Expand Down
4 changes: 2 additions & 2 deletions demos/matrix_free/stokes.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ the configured Krylov solver object.::
"pc_fieldsplit_schur_fact_type": "diag",

Next we configure the solvers for the blocks. For the velocity block,
we use an :class:`.AssembledPC` and approximate the inverse of the
we use an :class:`AssembledPC <firedrake.AssembledPC>` and approximate the inverse of the
vector laplacian using a single multigrid V-cycle.::

"fieldsplit_0_ksp_type": "preonly",
Expand Down Expand Up @@ -132,7 +132,7 @@ file.::

VTKFile("stokes.pvd").write(u, p)

By default, the mass matrix is assembled in the :class:`~.MassInvPC`
By default, the mass matrix is assembled in the :class:`MassInvPC <firedrake.MassInvPC>`
preconditioner, however, this can be controlled using a ``mat_type``
argument. To do this, we must specify the ``mat_type`` inside the
preconditioner. We can use the previous set of parameters and just
Expand Down
Loading
Loading