@@ -343,40 +343,47 @@ def __init__(self, expr: Interpolate, V, bcs=None):
343343 "Can only interpolate into spaces with point evaluation nodes."
344344 )
345345
346- expr = self .expr_renumbered
347- self .arguments = extract_arguments (expr )
346+ self .arguments = extract_arguments (self .expr_renumbered )
348347 self .nargs = len (self .arguments )
349348
350349 if self .options .allow_missing_dofs :
351350 self .missing_points_behaviour = MissingPointsBehaviour .IGNORE
352351 else :
353352 self .missing_points_behaviour = MissingPointsBehaviour .ERROR
354353
355- # setup
356354 self .V_dest = V .function_space () if isinstance (V , firedrake .Function ) else V
357- self .src_mesh = extract_unique_domain (expr )
355+ self .src_mesh = extract_unique_domain (self . expr_renumbered )
358356 self .dest_mesh = as_domain (self .V_dest )
359357 if self .src_mesh .geometric_dimension () != self .dest_mesh .geometric_dimension ():
360358 raise ValueError ("Geometric dimensions of source and destination meshes must match." )
361359
362360 self .sub_interpolators = []
363361 dest_element = self .V_dest .ufl_element ()
364- if isinstance (dest_element , finat .ufl .MixedElement ):
365- if isinstance ( dest_element , ( finat . ufl . VectorElement , finat . ufl . TensorElement )):
366- base_element = dest_element .sub_elements [0 ]
367- if base_element .reference_value_shape != ():
368- raise NotImplementedError (
369- "Can't yet cross-mesh interpolate onto function spaces made from VectorElements or TensorElements made from sub elements with value shape other than ()."
370- )
371- self .dest_element = base_element
372- self ._symbolic_expression ()
373- else :
374- self ._mixed_function_space ()
362+ if isinstance (dest_element , ( finat .ufl .VectorElement , finat . ufl . TensorElement ) ):
363+ # In this case all sub elements are equal
364+ base_element = dest_element .sub_elements [0 ]
365+ if base_element .reference_value_shape != ():
366+ raise NotImplementedError (
367+ "Can't yet cross-mesh interpolate onto function spaces made from VectorElements or TensorElements made from sub elements with value shape other than ()."
368+ )
369+ self .dest_element = base_element
370+ self ._get_symbolic_expressions ()
371+ elif isinstance ( dest_element , finat . ufl . MixedElement ) :
372+ self ._mixed_function_space ()
375373 else :
374+ # scalar fiat/finat element
376375 self .dest_element = dest_element
377- self ._symbolic_expression ()
376+ self ._get_symbolic_expressions ()
377+
378+ def _get_symbolic_expressions (self ):
379+ """Constructs the symbolic Interpolate expressions for cross-mesh interpolation.
378380
379- def _symbolic_expression (self ):
381+ Raises
382+ ------
383+ DofNotDefinedError
384+ If some DoFs in the target function space cannot be defined
385+ in the source function space.
386+ """
380387 from firedrake .assemble import assemble
381388 # Immerse coordinates of V_dest point evaluation dofs in src_mesh
382389 V_dest_vec = firedrake .VectorFunctionSpace (self .dest_mesh , self .dest_element )
@@ -408,16 +415,14 @@ def _symbolic_expression(self):
408415 self .point_eval_io = interpolate (firedrake .TrialFunction (P0DG_vom ), P0DG_vom_i_o )
409416
410417 def _mixed_function_space (self ):
411- # Build and save an interpolator for each sub-element
412- # separately for MixedFunctionSpaces. NOTE: since we can't have
413- # expressions for MixedFunctionSpaces we know that the input
414- # argument ``expr`` must be a Function. V_dest can be a Function
415- # or a FunctionSpace, and subfunctions works for both.
418+ """Builds symbolic Interpolate expressions for each sub-element of a MixedFunctionSpace.
419+ """
420+ # NOTE: since we can't have expressions for MixedFunctionSpaces
421+ # we know that the input argument ``expr`` must be a Function.
422+ # V_dest can be a Function or a FunctionSpace, and subfunctions works for both.
416423 if self .nargs == 1 :
417424 # Arguments don't have a subfunctions property so I have to
418- # make them myself. NOTE: this will not be correct when we
419- # start allowing interpolators created from an expression
420- # with arguments, as opposed to just being the argument.
425+ # make them myself.
421426 expr_subfunctions = [
422427 firedrake .TestFunction (V_src_sub_func )
423428 for V_src_sub_func in self .expr .function_space ().subspaces
@@ -443,8 +448,6 @@ def _mixed_function_space(self):
443448 @PETSc .Log .EventDecorator ()
444449 def _interpolate (self , * function , output = None , adjoint = False ):
445450 """Compute the interpolation.
446-
447- For arguments, see :class:`.Interpolator`.
448451 """
449452 from firedrake .assemble import assemble
450453 if adjoint and not self .nargs :
0 commit comments