Compute the target space of Interpolate only in UFL

Aperta
#5,597 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
45/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
api, backend

Direzione di ricerca

Read firedrake/interpolation.py around the linked Interpolate.__init__ lines and compare them with UFL’s ufl/core/base_form_operator.py and ufl/core/interpolate.py; the issue also points to FEniCS/ufl#515 for the UFL work. Trace how the target space and adjoint status are computed, then check the UFL and Firedrake tests for these cases. Done means UFL exposes the target space and adjoint status, and Firedrake uses them without recomputing argument numbers.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Follow-up from the review of #5551 (comment).

Problem

firedrake.Interpolate.__init__ and ufl.Interpolate.__init__ both compute the argument numbers of the expression and use them to decide which argument of the dual slot is contracted. Firedrake does this in its own way:

https://github.com/firedrakeproject/firedrake/blob/7cd82b23096667ec328b01c5c18588c16a11fa2e/firedrake/interpolation.py#L126-L140

UFL does it with _split_dual_slot_arguments in ufl/core/base_form_operator.py, and stores the result as Interpolate._function_space.

The two computations must agree, but nothing makes them agree. They already differ in small ways: Firedrake contracts the primal argument numbered 0, and UFL contracts the lowest-numbered primal argument. Firedrake does not check that the first argument of a form operand is a Coargument, and UFL does.

Why Firedrake computes the numbers again

UFL already computes the space that Firedrake needs, but it does not make it public. Firedrake needs two results from the argument numbers:

  1. The target space. This is the space of the dual-slot argument that the output of the interpolation replaces. Firedrake uses it to select the Interpolator subclass (target_space.mesh(), len(target_space)) and to check the shape of the expression. UFL computes the same space and stores it in the private _function_space. The public method ufl_function_space() does not return it. That method returns the dual of the first argument of the operator, which is a different space when the interpolation is an adjoint or when the dual slot is a form:

    Expression Target space ufl_function_space()
    Interpolate(u, V) V V
    Interpolate(TestFunction(U), V) (adjoint) V U*
    Interpolate(e, Cofunction(V*)) V None
    Interpolate(w0, A(v0, v1)) V0 W0*
    Interpolate(w1, A(v0, v1)) V1 V0*

    Here v0 ∈ V0, v1 ∈ V1, w0 ∈ W0 (number 0), and w1 ∈ W1 (number 1). These values were checked against UFL main. With a 2-form in the dual slot, the target space depends on the argument numbers of the expression (see the BaseFormOperator docstring). Because of this, the target space cannot be found from the dual slot alone.

  2. A Firedrake Argument for a function-space dual slot. If V is a WithGeometry, UFL makes a ufl.Argument(V.dual(), n), which has no .function_space() method. Firedrake therefore makes its own firedrake.Argument before it calls super().__init__. To get n, it must know whether the expression is an adjoint (expr_arg_numbers == {0}), and UFL computes that again. This is also the source of Interpolate.is_adjoint.

A third copy is in Interpolator.__init__, which sets self.target_space = dual_arg.function_space().dual(). That is correct only when the dual slot is a Coargument or a Cofunction.

Proposal

Make the target space a public attribute of ufl.BaseFormOperator. Then firedrake.Interpolate can be a thin wrapper around ufl.Interpolate.

BaseFormOperator.target_space (or ufl_target_space(), if it must follow the UFL naming convention) must return the space that the output of the operator N(u) is in:

  • It is the function_space argument of BaseFormOperator.__init__. __init__ already checks that this is the space of the contracted dual-slot argument.
  • It does not depend on the argument numbering. For the examples above, it is the space in the "Target space" column. It is never a dual space and it is never None, also when the dual slot is a Cofunction.
  • It is defined for every BaseFormOperator, not only for Interpolate. ExternalOperator gets the same attribute.
  • ufl_shape and ufl_element() of Interpolate must be derived from it. At the moment they read _function_space directly.

UFL must also expose whether the interpolation is an adjoint (for example Interpolate.is_adjoint), so that Firedrake does not compute the argument numbers again.

With these changes in UFL, Firedrake can:

  • Remove the computation of expr_arg_numbers and the selection of the contracted argument from firedrake.Interpolate.__init__, and use self.target_space from UFL.
  • Remove Interpolator.target_space = dual_arg.function_space().dual(), and use expr.target_space.
  • Keep only the conversion of a WithGeometry into a firedrake.Argument. This is possible if UFL makes the argument through a hook that Firedrake can override, or if ufl.Argument gets the information that Firedrake needs from .function_space().

FEniCS/ufl#515 changes ufl/core/interpolate.py and can be a good place for the UFL part of this change.


🤖 Drafted with Claude Code (Claude Opus 5.5).

Lingua principale
Python
Stelle
684
Fork
204
Merge medio
4g 14h
PR unite (30g)
46

Preparare l'ambiente

  • Nessun Dockerfile né file Docker Compose
  • Ha un modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di firedrakeproject/firedrake

Tutte le issue di firedrakeproject/firedrake

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.