Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 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
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
a548b98
Fix up
pbrubeck Sep 26, 2025
aa9e0c6
Update firedrake/assemble.py
pbrubeck Sep 26, 2025
d776c73
merge conflict
pbrubeck Sep 26, 2025
8d631f8
Relax test to avoid randomness
pbrubeck Sep 28, 2025
f21dad9
MixedInterpolator
pbrubeck Sep 28, 2025
2297f08
PMGPC: use native matrix-free (adjoint) interpolation
pbrubeck Sep 29, 2025
3bd935e
MixedInterpolator
pbrubeck Sep 30, 2025
76ec367
Fixup
pbrubeck Oct 1, 2025
f1080ea
Interpolate: support fieldsplit
pbrubeck Oct 1, 2025
997e638
cleanup
pbrubeck Oct 1, 2025
e400fc9
cleanup
pbrubeck Oct 1, 2025
fee366a
Implement missing functionality in CrossMeshInterpolator
pbrubeck Oct 1, 2025
3aeb517
Test the MixedInterpolator 0-form across different meshes
pbrubeck Oct 1, 2025
aa87c36
Fixup
pbrubeck Oct 1, 2025
719067d
Merge conflict
pbrubeck Oct 1, 2025
972c5e2
merge conflict
pbrubeck Oct 1, 2025
528800a
Fix tests
pbrubeck Oct 1, 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
28 changes: 0 additions & 28 deletions firedrake/assemble.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import finat.ufl
from firedrake import (extrusion_utils as eutils, matrix, parameters, solving,
tsfc_interface, utils)
from firedrake.formmanipulation import split_form
from firedrake.adjoint_utils import annotate_assemble
from firedrake.ufl_expr import extract_unique_domain
from firedrake.bcs import DirichletBC, EquationBC, EquationBCSplit
Expand Down Expand Up @@ -570,36 +569,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")
# If argument numbers have been swapped => Adjoint.
arg_operand = ufl.algorithms.extract_arguments(operand)
is_adjoint = (arg_operand and arg_operand[0].number() == 0)

# Get the target space
V = v.function_space().dual()

# Dual interpolation from mixed source
if is_adjoint and len(V) > 1:
cur = 0
sub_operands = []
components = numpy.reshape(operand, (-1,))
for Vi in V:
sub_operands.append(ufl.as_tensor(components[cur:cur+Vi.value_size].reshape(Vi.value_shape)))
cur += Vi.value_size

# Component-split of the primal operands interpolated into the dual argument-split
split_interp = sum(reconstruct_interp(sub_operands[i], v=vi) for (i,), vi in split_form(v))
return assemble(split_interp, tensor=tensor)

# Dual interpolation into mixed target
if is_adjoint and len(arg_operand[0].function_space()) > 1 and rank == 1:
V = arg_operand[0].function_space()
tensor = tensor or firedrake.Cofunction(V.dual())

# Argument-split of the Interpolate gets assembled into the corresponding sub-tensor
for (i,), sub_interp in split_form(expr):
assemble(sub_interp, tensor=tensor.subfunctions[i])
return tensor

# Get the interpolator
interp_data = expr.interp_data.copy()
default_missing_val = interp_data.pop('default_missing_val', None)
Expand Down
46 changes: 45 additions & 1 deletion firedrake/formmanipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import numpy
import collections

from ufl import as_vector, split
from ufl import as_tensor, as_vector, split
from ufl.classes import Zero, FixedIndex, ListTensor, ZeroBaseForm
from ufl.algorithms.map_integrands import map_integrand_dags
from ufl.algorithms import expand_derivatives
Expand All @@ -14,6 +14,7 @@
from firedrake.petsc import PETSc
from firedrake.functionspace import MixedFunctionSpace
from firedrake.cofunction import Cofunction
from firedrake.ufl_expr import Coargument
from firedrake.matrix import AssembledMatrix


Expand Down Expand Up @@ -133,6 +134,17 @@ def argument(self, o):
args.extend(Zero() for j in numpy.ndindex(V[i].value_shape))
return self._arg_cache.setdefault(o, as_vector(args))

def coargument(self, o):
V = o.function_space()

if len(V) == 1:
# Not on a mixed space, just return ourselves.
return o

indices = self.blocks[o.number()]
W = subspace(V, indices)
return Coargument(W, number=o.number(), part=o.part())

def cofunction(self, o):
V = o.function_space()

Expand Down Expand Up @@ -171,6 +183,38 @@ def matrix(self, o):
bcs = ()
return AssembledMatrix(tuple(args), bcs, submat)

def interpolate(self, o, operand):
if isinstance(operand, Zero):
return ZeroBaseForm(o.arguments())

dual_arg, _ = o.argument_slots()
V = dual_arg.function_space()
if len(V) == 1 or len(dual_arg.arguments()) == 1:
return o._ufl_expr_reconstruct_(operand, dual_arg)

# Split the target (dual) argument
if isinstance(dual_arg, Coargument):
dual_arg = self(dual_arg)
indices = self.blocks[dual_arg.number()]
else:
raise NotImplementedError()

# Unflatten the expression into the target shapes
cur = 0
cindices = []
for i, Vi in enumerate(V):
if i in indices:
cindices.extend(range(cur, cur+Vi.value_size))
cur += Vi.value_size

W = dual_arg.function_space()
components = [operand[i] for i in cindices]
operand = as_tensor(numpy.reshape(components, W.value_shape))
if isinstance(operand, Zero):
return ZeroBaseForm(o.arguments())

return o._ufl_expr_reconstruct_(operand, dual_arg)


SplitForm = collections.namedtuple("SplitForm", ["indices", "form"])

Expand Down
Loading
Loading