Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
e956adb
Matfree adjoint interpolation
pbrubeck Sep 9, 2025
29a410d
Update interpolation.py
pbrubeck Sep 10, 2025
a33cfb3
Fixup, cleanup
pbrubeck Sep 11, 2025
d51db25
Reverse indices for dual_arg
pbrubeck Sep 11, 2025
afe0256
gem cofunction
pbrubeck Sep 11, 2025
7aa048e
More fixups
pbrubeck Sep 12, 2025
9826f0d
More fixup
pbrubeck Sep 12, 2025
4ce9f8e
Fixup
pbrubeck Sep 12, 2025
ae80c0f
cleanup
pbrubeck Sep 12, 2025
7fa72d6
Fix Real adjoint
pbrubeck Sep 12, 2025
3f5ca71
Fixup
pbrubeck Sep 13, 2025
42f848c
Fix multiindices
pbrubeck Sep 17, 2025
08dba92
Remove interpolate(Function(DG0), CG2) from test
pbrubeck Sep 17, 2025
d1a0710
Do not sum_factorise
pbrubeck Sep 17, 2025
9329d1a
Fix complex conjugate
pbrubeck Sep 17, 2025
44a98ed
Suggestions from review
pbrubeck Sep 18, 2025
120a2a3
Reusable Interpolator
pbrubeck Sep 18, 2025
af77aac
Allow interpolate(..., BaseForm)
pbrubeck Sep 18, 2025
820038c
Merge branch 'main' into pbrubeck/interp-adjoint
pbrubeck Sep 18, 2025
ea5c07b
Update firedrake/assemble.py
pbrubeck Sep 18, 2025
62fa31e
Explicitly assemble the interpolate adjoint matrix
pbrubeck Sep 19, 2025
ef0b10c
Fix up
pbrubeck Sep 19, 2025
34ea5f3
Move renumbering logic to Interpolator
pbrubeck Sep 20, 2025
f82b140
Fix up
pbrubeck Sep 21, 2025
be0f779
Enhacements for interpolation into VOM
pbrubeck Sep 22, 2025
6407f4e
SameMeshInterpolator: support matfree/explcit adjoint on Submesh
pbrubeck Sep 24, 2025
449420f
Update tsfc/driver.py
pbrubeck Sep 24, 2025
f614764
Test submesh in parallel
pbrubeck Sep 24, 2025
ea997ea
VOM onto other VOM still needs renumbering
pbrubeck Sep 24, 2025
eee77d6
Clarify insane interface
pbrubeck Sep 25, 2025
806d60b
Update firedrake/interpolation.py
pbrubeck Sep 25, 2025
5c6e911
Update firedrake/interpolation.py
pbrubeck Sep 25, 2025
e303940
Update firedrake/interpolation.py
pbrubeck Sep 25, 2025
cc18063
Apply suggestions from code review
pbrubeck Sep 26, 2025
fd9a3f6
Update firedrake/interpolation.py
pbrubeck Sep 26, 2025
1fad893
Merge branch 'pbrubeck/interp-adjoint' into pbrubeck/interp-adjoint-e…
pbrubeck Sep 26, 2025
b9f8088
Merge branch 'main' into pbrubeck/interp-adjoint
pbrubeck Sep 18, 2025
89f97d5
add dataclass
leo-collins Sep 25, 2025
613f630
use kwargs; dataclass
leo-collins Sep 25, 2025
0ee1e2e
`interpolate` docstring; simplify function
leo-collins Sep 25, 2025
be3b6b6
simplify `Interpolate`
leo-collins Sep 25, 2025
dd6770a
add _get_interpolator function
leo-collins Sep 25, 2025
21dea34
fix `_get_interpolator`
leo-collins Sep 25, 2025
8ed2151
fixes for `test_interpolate_cross_mesh`
leo-collins Sep 25, 2025
c180374
remove parameters from Interpolator
leo-collins Sep 25, 2025
a2d1166
remove `freeze_expr` and logic
leo-collins Sep 25, 2025
29b9d25
remove parameters
leo-collins Sep 25, 2025
5e0853e
remove interp_data dict
leo-collins Sep 25, 2025
e8125e7
simplify logic
leo-collins Sep 25, 2025
df935f8
remove default_missing_val argument
leo-collins Sep 25, 2025
ce2659a
tidy
leo-collins Sep 25, 2025
9c37277
refactor crossmeshinterpolator
leo-collins Sep 26, 2025
3146105
fix
leo-collins Sep 26, 2025
f90f6fc
tidy
leo-collins Sep 26, 2025
4097207
io -> input_ordering
leo-collins Sep 26, 2025
f895423
`make_interpolator` -> `_get_callable`
leo-collins Sep 26, 2025
4a843ae
remove comment
leo-collins Sep 26, 2025
f43b2c0
remove properties
leo-collins Sep 26, 2025
9e33ce2
suggestions from review
pbrubeck Sep 26, 2025
960e7b0
Merge branch 'main' into pbrubeck/interp-adjoint
pbrubeck Sep 26, 2025
ee99351
Merge branch 'pbrubeck/interp-adjoint' into pbrubeck/interp-adjoint-e…
pbrubeck Sep 26, 2025
687aa02
Merge branch 'pbrubeck/interp-adjoint-explicit' into leo/refactor_int…
leo-collins Sep 26, 2025
cce10bd
tidy / add comments
leo-collins Sep 26, 2025
6b39062
Test -> Trial inside `CrossMeshInterpolator._mixed_function_space`
leo-collins Sep 26, 2025
899a0ec
lint
leo-collins Sep 26, 2025
733da2d
create `_get_tensor` method
leo-collins Sep 26, 2025
d893488
tidy
leo-collins Sep 26, 2025
05237c9
simplify
leo-collins Sep 29, 2025
c7426b2
simplify
leo-collins Sep 23, 2025
106ea87
tidy function interpolate
leo-collins Sep 23, 2025
91caf94
create Coargument in Firedrake
leo-collins Sep 23, 2025
91e4500
Change `Interpolate` to `interpolate`
leo-collins Sep 23, 2025
f661be2
update `test_interp_dual.py`
leo-collins Sep 23, 2025
bc4e48b
DROP BEFORE MERGE: use UFL branch
leo-collins Sep 23, 2025
ac252dc
move FunctionSpace check into `Interpolate`
leo-collins Sep 23, 2025
79d6c83
lint
leo-collins Sep 23, 2025
4a509f7
test -> trial
leo-collins Sep 24, 2025
812f5d8
tidy function.interpolate
leo-collins Oct 1, 2025
e50cf4e
tidy cofunction.interpolate
leo-collins Oct 1, 2025
5d9c81e
tidy type hints in function.py
leo-collins Oct 1, 2025
fddcb79
remove UFL branch
leo-collins Oct 1, 2025
1bc83d4
lint
leo-collins Oct 1, 2025
8ce32ae
fix typing
leo-collins Oct 1, 2025
78dac92
runtimeerror -> valueerror
leo-collins Oct 1, 2025
62aff37
add check for shape mismatch to `Interpolate`
leo-collins Oct 1, 2025
68e5527
use ufl.as_expr
leo-collins Oct 2, 2025
d782365
update expr arg check
leo-collins Oct 6, 2025
f6f4a11
lint
leo-collins Oct 6, 2025
3a59ff1
fix check
leo-collins Oct 6, 2025
5b57198
Merge branch 'leo/simplify-interpolate' into leo/refactor_interpolate
leo-collins Oct 16, 2025
c8ffb2b
tidy
leo-collins Oct 1, 2025
8ffb3fc
review suggestions
leo-collins Oct 1, 2025
a73e23f
Squashed commit of the following:
leo-collins Oct 1, 2025
37b9cac
tidy
leo-collins Oct 1, 2025
90a0fa5
remove `V` argument
leo-collins Oct 8, 2025
72bd29e
assemble cross-mesh interpolation matrix; add test
leo-collins Oct 8, 2025
a8e7d30
assemble adjoint cross-mesh interpolation matrix
leo-collins Oct 8, 2025
40c23da
changes
leo-collins Oct 9, 2025
fcdb7c5
remove repeated checks
leo-collins Oct 9, 2025
e7fe358
progress on adjoint cross-mesh / vom-to-vom
leo-collins Oct 9, 2025
efc45c7
tidy
leo-collins Oct 9, 2025
f71dd47
tidy
leo-collins Oct 9, 2025
17469c5
fixes
leo-collins Oct 10, 2025
21d1068
fixes
leo-collins Oct 10, 2025
19187a5
fixed zero-form cross mesh
leo-collins Oct 10, 2025
d17d049
remove vomontovomwrapper
leo-collins Oct 10, 2025
4c4cf49
fixes
leo-collins Oct 11, 2025
58326de
tidy import
leo-collins Oct 11, 2025
a78b652
lint
leo-collins Oct 11, 2025
387ad5e
attempt fix for bc
leo-collins Oct 13, 2025
7f1d509
fix
leo-collins Oct 13, 2025
78b058a
make `_get_interpolator` public
leo-collins Oct 13, 2025
c9f4ac0
change bcs
leo-collins Oct 13, 2025
2340cea
fixes
leo-collins Oct 13, 2025
7979355
updates
leo-collins Oct 14, 2025
b3ce8f3
remove _interpolate WIP
leo-collins Oct 14, 2025
ca93fbd
fixes
leo-collins Oct 14, 2025
39aef14
add `get_interpolator` to `__all__`
leo-collins Oct 14, 2025
3658338
lint; type hints and docstrings
leo-collins Oct 14, 2025
b9ab2e0
fix
leo-collins Oct 14, 2025
93476e4
suggestions
leo-collins Oct 16, 2025
0934e61
fixes
leo-collins Oct 16, 2025
6b87a6b
lint
leo-collins Oct 16, 2025
15bdd53
pass bcs to `interpolate`, zero cofunction fix
leo-collins Oct 16, 2025
8667567
add zero form optimisation back in
leo-collins Oct 16, 2025
59bcb4d
conjugate test function
leo-collins Oct 16, 2025
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
2 changes: 1 addition & 1 deletion demos/boussinesq/boussinesq.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ implements a boundary condition that fixes a field at a single point. ::

# Take the basis function with the largest abs value at bc_point
v = TestFunction(V)
F = assemble(Interpolate(inner(v, v), Fvom))
F = assemble(interpolate(inner(v, v), Fvom))
with F.dat.vec as Fvec:
max_index, _ = Fvec.max()
nodes = V.dof_dset.lgmap.applyInverse([max_index])
Expand Down
2 changes: 1 addition & 1 deletion demos/multicomponent/multicomponent.py.rst
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ mathematically valid to do this)::

# Take the basis function with the largest abs value at bc_point
v = TestFunction(V)
F = assemble(Interpolate(inner(v, v), Fvom))
F = assemble(interpolate(inner(v, v), Fvom))
with F.dat.vec as Fvec:
max_index, _ = Fvec.max()
nodes = V.dof_dset.lgmap.applyInverse([max_index])
Expand Down
15 changes: 4 additions & 11 deletions firedrake/assemble.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from firedrake.bcs import DirichletBC, EquationBC, EquationBCSplit
from firedrake.functionspaceimpl import WithGeometry, FunctionSpace, FiredrakeDualSpace
from firedrake.functionspacedata import entity_dofs_key, entity_permutations_key
from firedrake.interpolation import get_interpolator
from firedrake.petsc import PETSc
from firedrake.slate import slac, slate
from firedrake.slate.slac.kernel_builder import CellFacetKernelArg, LayerCountKernelArg
Expand Down Expand Up @@ -578,17 +579,9 @@ def base_form_assembly_visitor(self, expr, tensor, *args):
rank = len(expr.arguments())
if rank > 2:
raise ValueError("Cannot assemble an Interpolate with more than two arguments")
# Get the target space
V = v.function_space().dual()

# Get the interpolator
interp_data = expr.interp_data.copy()
default_missing_val = interp_data.pop('default_missing_val', None)
if rank == 1 and isinstance(tensor, firedrake.Function):
V = tensor
interpolator = firedrake.Interpolator(expr, V, **interp_data)
# Assembly
return interpolator.assemble(tensor=tensor, default_missing_val=default_missing_val)

interpolator = get_interpolator(expr)
return interpolator.assemble(tensor=tensor)
elif tensor and isinstance(expr, (firedrake.Function, firedrake.Cofunction, firedrake.MatrixBase)):
return tensor.assign(expr)
elif tensor and isinstance(expr, ufl.ZeroBaseForm):
Expand Down
16 changes: 8 additions & 8 deletions firedrake/bcs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# A module implementing strong (Dirichlet) boundary conditions.
import numpy as np

import functools
from functools import partial, reduce
import itertools

import ufl
Expand Down Expand Up @@ -167,7 +167,7 @@ def hermite_stride(bcnodes):
# Edge conditions have only been tested with Lagrange elements.
# Need to expand the list.
bcnodes1.append(hermite_stride(self._function_space.boundary_nodes(ss)))
bcnodes1 = functools.reduce(np.intersect1d, bcnodes1)
bcnodes1 = reduce(np.intersect1d, bcnodes1)
bcnodes.append(bcnodes1)
return np.concatenate(bcnodes)

Expand Down Expand Up @@ -339,6 +339,7 @@ def reconstruct(self, field=None, V=None, g=None, sub_domain=None, use_split=Fal
@function_arg.setter
def function_arg(self, g):
'''Set the value of this boundary condition.'''
from firedrake.interpolation import get_interpolator
try:
# Clear any previously set update function
del self._function_arg_update
Expand All @@ -359,12 +360,11 @@ def function_arg(self, g):
raise RuntimeError(f"Provided boundary value {g} does not match shape of space")
try:
self._function_arg = firedrake.Function(V)
# Use `Interpolator` instead of assembling an `Interpolate` form
# as the expression compilation needs to happen at this stage to
# determine if we should use interpolation or projection
# -> e.g. interpolation may not be supported for the element.
self._function_arg_update = firedrake.Interpolator(g, self._function_arg)._interpolate
except (NotImplementedError, AttributeError):
interpolator = get_interpolator(firedrake.interpolate(g, V))
# Call this here to check if the element supports interpolation
interpolator._build_callable()
self._function_arg_update = partial(interpolator.assemble, tensor=self._function_arg)
except (ValueError, NotImplementedError):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this ValueError showing up? We might want to change it to NotImplementedError

# Element doesn't implement interpolation
self._function_arg = firedrake.Function(V).project(g)
self._function_arg_update = firedrake.Projector(g, self._function_arg).project
Expand Down
6 changes: 3 additions & 3 deletions firedrake/cofunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ def interpolate(self,
Parameters
----------
expression
A dual UFL expression to interpolate.
A UFL BaseForm to adjoint interpolate.
ad_block_tag
An optional string for tagging the resulting assemble
block on the Pyadjoint tape.
Expand All @@ -331,9 +331,9 @@ def interpolate(self,
firedrake.cofunction.Cofunction
Returns `self`
"""
from firedrake import interpolation, assemble
from firedrake import interpolate, assemble
v, = self.arguments()
interp = interpolation.Interpolate(v, expression, **kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was necessary to keep adjoint tests happy, does this cause issues still?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fixed by #4582, which is included in this PR

interp = interpolate(v, expression, **kwargs)
return assemble(interp, tensor=self, ad_block_tag=ad_block_tag)

@property
Expand Down
10 changes: 5 additions & 5 deletions firedrake/external_operators/point_expr_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import firedrake.ufl_expr as ufl_expr
from firedrake.assemble import assemble
from firedrake.interpolation import Interpolate
from firedrake.interpolation import interpolate
from firedrake.external_operators import AbstractExternalOperator, assemble_method


Expand Down Expand Up @@ -58,7 +58,7 @@ def assemble_operator(self, *args, **kwargs):
V = self.function_space()
expr = as_ufl(self.expr(*self.ufl_operands))
if len(V) < 2:
interp = Interpolate(expr, self.function_space())
interp = interpolate(expr, self.function_space())
return assemble(interp)
# Interpolation of UFL expressions for mixed functions is not yet supported
# -> `Function.assign` might be enough in some cases.
Expand All @@ -72,7 +72,7 @@ def assemble_operator(self, *args, **kwargs):
def assemble_Jacobian_action(self, *args, **kwargs):
V = self.function_space()
expr = as_ufl(self.expr(*self.ufl_operands))
interp = Interpolate(expr, V)
interp = interpolate(expr, V)

u, = [e for i, e in enumerate(self.ufl_operands) if self.derivatives[i] == 1]
w = self.argument_slots()[-1]
Expand All @@ -83,7 +83,7 @@ def assemble_Jacobian_action(self, *args, **kwargs):
def assemble_Jacobian(self, *args, assembly_opts, **kwargs):
V = self.function_space()
expr = as_ufl(self.expr(*self.ufl_operands))
interp = Interpolate(expr, V)
interp = interpolate(expr, V)

u, = [e for i, e in enumerate(self.ufl_operands) if self.derivatives[i] == 1]
jac = ufl_expr.derivative(interp, u)
Expand All @@ -99,7 +99,7 @@ def assemble_Jacobian_adjoint(self, *args, assembly_opts, **kwargs):
def assemble_Jacobian_adjoint_action(self, *args, **kwargs):
V = self.function_space()
expr = as_ufl(self.expr(*self.ufl_operands))
interp = Interpolate(expr, V)
interp = interpolate(expr, V)

u, = [e for i, e in enumerate(self.ufl_operands) if self.derivatives[i] == 1]
ustar = self.argument_slots()[0]
Expand Down
8 changes: 4 additions & 4 deletions firedrake/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,9 @@ def interpolate(self,
firedrake.function.Function
Returns `self`
"""
from firedrake import interpolation, assemble
from firedrake import interpolate, assemble
V = self.function_space()
interp = interpolation.Interpolate(expression, V, **kwargs)
interp = interpolate(expression, V, **kwargs)
return assemble(interp, tensor=self, ad_block_tag=ad_block_tag)

def zero(self, subset=None):
Expand Down Expand Up @@ -701,7 +701,7 @@ def __init__(self, domain, point):
self.point = point

def __str__(self):
return "domain %s does not contain point %s" % (self.domain, self.point)
return f"Domain {self.domain} does not contain point {self.point}"


class PointEvaluator:
Expand All @@ -716,7 +716,7 @@ def __init__(self, mesh: MeshGeometry, points: np.ndarray | list, tolerance: flo
The mesh on which to embed the points.
points : numpy.ndarray | list
Array or list of points to evaluate at.
tolerance : float | None
tolerance : Optional[float]
Tolerance to use when checking if a point is in a cell.
If ``None`` (the default), the ``tolerance`` of the ``mesh`` is used.
missing_points_behaviour : str
Expand Down
Loading
Loading