Skip to content

Commit

Permalink
Drop lint ignores except in demos (#266)
Browse files Browse the repository at this point in the history
  • Loading branch information
jwallwork23 authored Dec 24, 2024
1 parent 3f50662 commit 0bedd17
Show file tree
Hide file tree
Showing 38 changed files with 376 additions and 362 deletions.
22 changes: 12 additions & 10 deletions demos/burgers-goal_oriented.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Burgers equation with Goal-oriented mesh adaptation
# ===================================================

# In the `Hessian-based adaptation <./burgers-hessian.py.html>`__, we applied a Hessian-based
# mesh adaptation to the time-dependent Burgers equation. Here, we alternatively consider
# a goal-oriented error estimation to drive the mesh adaptation. Again, we will
# choose to partition the problem over multiple subintervals and hence multiple meshes
# to adapt. We also chose to apply a QoI which integrates in time as well as space.
# In the `Hessian-based adaptation <./burgers-hessian.py.html>`__, we applied a
# Hessian-based mesh adaptation to the time-dependent Burgers equation. Here, we
# alternatively consider a goal-oriented error estimation to drive the mesh adaptation.
# Again, we will choose to partition the problem over multiple subintervals and hence
# multiple meshes to adapt. We also chose to apply a QoI which integrates in time as
# well as space.
#
# We copy over the setup as before. The only difference is that we import from
# ``goalie_adjoint`` rather than ``goalie``. ::
Expand Down Expand Up @@ -115,8 +116,8 @@ def time_integrated_qoi(t):

# Compared to the previous `Hessian-based adaptation <./burgers-hessian.py.html>`__,
# this adaptor depends on adjoint solution data as well as forward solution data.
# For simplicity, we begin by using :meth:`~.RiemannianMetric.compute_isotropic_metric()`.
# ::
# For simplicity, we begin by using
# :meth:`~.RiemannianMetric.compute_isotropic_metric()`. ::


def adaptor(mesh_seq, solutions=None, indicators=None):
Expand Down Expand Up @@ -257,7 +258,8 @@ def adaptor(mesh_seq, solutions=None, indicators=None):
# (See documentation for details.) To use it, we just need to define
# a different adaptor function. The same error indicator is used as
# for the isotropic approach. Additionally, the Hessian of the forward
# solution is estimated as in the `Hessian-based adaptation <./burgers-hessian.py.html>`__
# solution is estimated as in the
# `Hessian-based adaptation <./burgers-hessian.py.html>`__
# to give anisotropy to the metric.
#
# For this driver, normalisation is handled differently than for
Expand Down Expand Up @@ -351,8 +353,8 @@ def adaptor(mesh_seq, solutions=None, indicators=None):
fig.savefig(f"burgers-anisotropic_mesh{iteration + 1}.jpg")
plt.close()

# Since we have multiple subintervals, we should check if the target complexity has been
# (approximately) reached on each subinterval
# Since we have multiple subintervals, we should check if the target complexity has
# been (approximately) reached on each subinterval
continue_unconditionally = np.array(complexities) < 0.90 * target
return continue_unconditionally

Expand Down
1 change: 1 addition & 0 deletions demos/burgers-hessian.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from animate.adapt import adapt
from animate.metric import RiemannianMetric
from firedrake import *
from firedrake.__future__ import interpolate

from goalie import *

Expand Down
17 changes: 9 additions & 8 deletions demos/burgers_ee.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,15 @@ def end_time_qoi():
qoi_type="end_time",
)

# Given the description of the PDE problem in the form of a :class:`GoalOrientedMeshSeq`,
# Goalie is able to extract all of the relevant information to automatically compute
# error estimators. During the computation, we solve the forward and adjoint equations
# over the mesh sequence, as before. In addition, we solve the adjoint problem again
# in an *enriched* finite element space. Currently, Goalie supports uniform refinement
# of the meshes (:math:`h`-refinement) or globally increasing the polynomial order
# (:math:`p`-refinement). Choosing one (or both) of these as the ``"enrichment_method"``,
# we are able to compute error indicator fields as follows. ::
# Given the description of the PDE problem in the form of a
# :class:`GoalOrientedMeshSeq`, Goalie is able to extract all of the relevant
# information to automatically compute error estimators. During the computation, we
# solve the forward and adjoint equations over the mesh sequence, as before. In
# addition, we solve the adjoint problem again in an *enriched* finite element space.
# Currently, Goalie supports uniform refinement of the meshes (:math:`h`-refinement) or
# globally increasing the polynomial order (:math:`p`-refinement). Choosing one (or
# both) of these as the ``"enrichment_method"``, we are able to compute error indicator
# fields as follows. ::

solutions, indicators = mesh_seq.indicate_errors(
enrichment_kwargs={"enrichment_method": "h"}
Expand Down
3 changes: 2 additions & 1 deletion demos/burgers_oo.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ def time_integrated_qoi(t):
enrichment_kwargs={"enrichment_method": "h"}
)

# Plotting this, we find that the results are consistent with those generated previously. ::
# Plotting this, we find that the results are consistent with those generated
# previously. ::

fig, axes, tcs = plot_indicator_snapshots(indicators, time_partition, "u", levels=50)
fig.savefig("burgers-oo_ee.jpg")
Expand Down
56 changes: 25 additions & 31 deletions demos/burgers_time_integrated.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
# Adjoint Burgers equation with a time integrated QoI
# ======================================================
#
# So far, we only considered a quantity of interest
# corresponding to a spatial integral at the end time.
# For some problems, it is more suitable to have a QoI
# which integrates in time as well as space.
# So far, we only considered a quantity of interest corresponding to a spatial integral
# at the end time. For some problems, it is more suitable to have a QoI which integrates
# in time as well as space.
#
# Begin by importing from Goalie and the first Burgers demo. ::
# Begin by importing from Firedrake and Goalie. Note that we use the *future* version
# Firedrake's `interpolate` function: :function:`firedrake.__future__.interpolate`. ::

from firedrake import *
from firedrake.__future__ import interpolate

from goalie_adjoint import *

# Redefine the ``get_initial_condition`` and ``get_function_spaces``,
# functions as in the first Burgers demo. ::
# Redefine the ``get_initial_condition`` and ``get_function_spaces``, functions as in
# the first Burgers demo. ::


def get_function_spaces(mesh):
Expand All @@ -26,14 +27,12 @@ def get_initial_condition(mesh_seq):
return {"u": assemble(interpolate(as_vector([sin(pi * x), 0]), fs))}


# The solver needs to be modified slightly in order to take
# account of time dependent QoIs. The Burgers solver
# uses backward Euler timestepping. The corresponding
# quadrature routine is like the midpoint rule, but takes
# the value from the next timestep, rather than the average
# between that and the current value. As such, the QoI may
# be computed by simply incrementing the :attr:`J` attribute
# of the :class:`AdjointMeshSeq` as follows. ::
# The solver needs to be modified slightly in order to take account of time dependent
# QoIs. The Burgers solver uses backward Euler timestepping. The corresponding
# quadrature routine is like the midpoint rule, but takes the value from the next
# timestep, rather than the average between that and the current value. As such, the QoI
# may be computed by simply incrementing the :attr:`J` attribute of the
# :class:`AdjointMeshSeq` as follows. ::


def get_solver(mesh_seq):
Expand Down Expand Up @@ -69,17 +68,15 @@ def solver(index):
return solver


# The QoI is effectively just a time-integrated version
# of the one previously seen.
# The QoI is effectively just a time-integrated version of the one previously seen.
#
# .. math::
# J(u) = \int_0^{T_{\mathrm{end}}} \int_0^1
# \mathbf u(1,y,t) \cdot \mathbf u(1,y,t)
# \;\mathrm dy\;\mathrm dt.
#
# Note that in this case we multiply by the timestep.
# It is wrapped in a :class:`Function` from `'R'` space to avoid
# recompilation if the value is changed. ::
# Note that in this case we multiply by the timestep. It is wrapped in a
# :class:`Function` from `'R'` space to avoid recompilation if the value is changed. ::


def get_qoi(mesh_seq, i):
Expand All @@ -106,9 +103,8 @@ def time_integrated_qoi(t):
end_time, num_subintervals, dt, ["u"], num_timesteps_per_export=1
)

# The only difference when defining the :class:`AdjointMeshSeq`
# is that we specify ``qoi_type="time_integrated"``, rather than
# ``qoi_type="end_time"``. ::
# The only difference when defining the :class:`AdjointMeshSeq` is that we specify
# ``qoi_type="time_integrated"``, rather than ``qoi_type="end_time"``. ::

mesh_seq = AdjointMeshSeq(
time_partition,
Expand All @@ -128,14 +124,12 @@ def time_integrated_qoi(t):
# :figwidth: 90%
# :align: center
#
# With a time-integrated QoI, the adjoint problem
# has a source term at the right-hand boundary, rather
# than a instantaneous pulse at the terminal time. As such,
# the adjoint solution field accumulates at the right-hand
# boundary, as well as propagating westwards.
# With a time-integrated QoI, the adjoint problem has a source term at the right-hand
# boundary, rather than a instantaneous pulse at the terminal time. As such, the adjoint
# solution field accumulates at the right-hand boundary, as well as propagating
# westwards.
#
# In the `next demo <./burgers_oo.py.html>`__, we solve
# the Burgers problem one last time, but using an
# object-oriented approach.
# In the `next demo <./burgers_oo.py.html>`__, we solve the Burgers problem one last
# time, but using an object-oriented approach.
#
# This demo can also be accessed as a `Python script <burgers_time_integrated.py>`__.
10 changes: 6 additions & 4 deletions demos/mantle_convection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
# involve a time derivative. Those are clearly *time-dependent* equations. However,
# time-dependent equations need not involve a time derivative. For example, they might
# include fields that vary with time. Examples of where this might happen are
# in continuous pressure projection approaches, ice sheet and glaciological modelling, and
# mantle convection modelling. In this demo, we illustrate how Goalie can be used
# in continuous pressure projection approaches, ice sheet and glaciological modelling,
# and mantle convection modelling. In this demo, we illustrate how Goalie can be used
# to solve such problems.

# We consider the problem of a mantle convection in a 2D unit square domain. The
Expand All @@ -19,8 +19,10 @@
#
# .. math::
# \begin{align}
# \nabla \cdot \mu \left[\nabla \mathbf{u} + (\nabla \mathbf{u})^T \right] - \nabla p + \mathrm{Ra}\,T\,\mathbf{k} &= 0, \\
# \frac{\partial T}{\partial t} \cdot \mathbf{u}\cdot\nabla T - \nabla \cdot (\kappa\nabla T) &= 0,
# \nabla \cdot \mu \left[\nabla \mathbf{u} + (\nabla \mathbf{u})^T \right] -
# \nabla p + \mathrm{Ra}\,T\,\mathbf{k} &= 0, \\
# \frac{\partial T}{\partial t} \cdot \mathbf{u}\cdot\nabla T
# - \nabla \cdot (\kappa\nabla T) &= 0,
# \end{align}
#
# where :math:`\mu`, :math:`\kappa`, and :math:`\mathrm{Ra}` are constant viscosity,
Expand Down
11 changes: 6 additions & 5 deletions demos/ode.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@ def solver(index):

solutions = point_seq.solve_forward()["u"]["forward"]

# Note that the solution trajectory does not include the initial value, so we prepend it.
# We also convert the solution :class:`~.Function`\s to :class:`~.float`\s, for plotting
# purposes. Whilst there is only one subinterval in this example, we show how to loop
# over subintervals, as this is instructive for the general case. ::
# Note that the solution trajectory does not include the initial value, so we prepend
# it. We also convert the solution :class:`~.Function`\s to :class:`~.float`\s, for
# plotting purposes. Whilst there is only one subinterval in this example, we show how
# to loop over subintervals, as this is instructive for the general case. ::

forward_euler_trajectory = [1]
forward_euler_trajectory += [
Expand Down Expand Up @@ -257,7 +257,8 @@ def solver(index):
# .. math::
# \frac{u_{i+1} - u_i}{\Delta t} = (\theta u_{i+1} + (1-\theta) u_i),
#
# where :math:`\theta\in(0,1)`. The standard choice is to take :math:`\theta=\frac12`. ::
# where :math:`\theta\in(0,1)`. The standard choice is to take :math:`\theta=\frac12`.
# ::


def get_solver_crank_nicolson(point_seq):
Expand Down
13 changes: 7 additions & 6 deletions demos/point_discharge2d-goal_oriented.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,11 @@ def adaptor(mesh_seq, solutions, indicators):
#
# Looking at the final adapted mesh, we can make a few observations. Firstly, the mesh
# elements are indeed isotropic. Secondly, there is clearly increased resolution
# surrounding the point source, as well as the "receiver region" which the QoI integrates
# over. There is also a band of increased resolution between these two regions. Finally,
# the mesh has low resolution downstream of the receiver region. This is to be expected
# because we have an advection-dominated problem, so the QoI value is independent of the
# dynamics there.
# surrounding the point source, as well as the "receiver region" which the QoI
# integrates over. There is also a band of increased resolution between these two
# regions. Finally, the mesh has low resolution downstream of the receiver region. This
# is to be expected because we have an advection-dominated problem, so the QoI value is
# independent of the dynamics there.
#
# Goalie also provides drivers for *anisotropic* goal-oriented mesh adaptation. Here,
# we consider the ``anisotropic_dwr_metric`` driver. (See documentation for details.) To
Expand Down Expand Up @@ -372,4 +372,5 @@ def adaptor(mesh_seq, solutions, indicators):
# In the `next demo <./burgers-hessian.py.html>`__, we consider mesh adaptation in the
# time-dependent case.
#
# This demo can also be accessed as a `Python script <point_discharge2d-goal_oriented.py>`__.
# This demo can also be accessed as a
# `Python script <point_discharge2d-goal_oriented.py>`__.
10 changes: 5 additions & 5 deletions demos/point_discharge2d-hessian.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# before progressing with this demo.
#
# In addition to importing from Firedrake and Goalie, we also import the mesh
# adaptation functionality from Firedrake, which can be found in ``firedrake.meshadapt``.
# adaptation functionality from Animate, which can be found in ``animate.adapt``.
# ::

from animate.adapt import adapt
Expand All @@ -20,8 +20,8 @@
from goalie import *

# We again consider the "point discharge with diffusion" test case from the
# `previous demo <./point_discharge2d.py.html>`__, approximating the tracer concentration
# :math:`c` in :math:`\mathbb P1` space. ::
# `previous demo <./point_discharge2d.py.html>`__, approximating the tracer
# concentration :math:`c` in :math:`\mathbb P1` space. ::

field_names = ["c"]

Expand Down Expand Up @@ -187,8 +187,8 @@ def adaptor(mesh_seq, solutions):
)
solutions = mesh_seq.fixed_point_iteration(adaptor, parameters=params)

# Mesh adaptation often gives slightly different results on difference machines. However,
# the output should look something like
# Mesh adaptation often gives slightly different results on difference machines.
# However, the output should look something like
#
# .. code-block:: console
#
Expand Down
6 changes: 4 additions & 2 deletions demos/point_discharge2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
# \left\{\begin{array}{rl}
# \mathbf u\cdot\nabla c - \nabla\cdot(D\nabla c) = S & \text{in}\:\Omega\\
# c=0 & \text{on}\:\partial\Omega_{\mathrm{inflow}}\\
# \nabla c\cdot\widehat{\mathbf n}=0 & \text{on}\:\partial\Omega\backslash\partial\Omega_{\mathrm{inflow}}
# \nabla c\cdot\widehat{\mathbf n}=0 &
# \text{on}\:\partial\Omega\backslash\partial\Omega_{\mathrm{inflow}}
# \end{array}\right.,
#
# for a tracer concentration :math:`c`, with fluid velocity
Expand Down Expand Up @@ -73,7 +74,8 @@ def source(mesh):
# With these ingredients, we can now define the :meth:`get_solver` method. Don't forget
# to apply the corresponding `ad_block_tag` to the solve call. Additionally, we must
# communicate the defined variational form to ``mesh_seq`` using the
# :meth:`mesh_seq.read_form()` method for Goalie to utilise it during error indication. ::
# :meth:`mesh_seq.read_form()` method for Goalie to utilise it during error indication.
# ::


def get_solver(mesh_seq):
Expand Down
7 changes: 0 additions & 7 deletions goalie/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,4 @@
from goalie.function_data import * # noqa
from goalie.error_estimation import * # noqa

from animate.utility import Mesh, VTKFile # noqa

from firedrake.__future__ import interpolate # noqa

import numpy as np # noqa
import os # noqa

__version__ = "0.1"
Loading

0 comments on commit 0bedd17

Please sign in to comment.