@@ -556,7 +556,6 @@ def base_form_assembly_visitor(self, expr, tensor, *args):
556
556
result = expr .assemble (assembly_opts = opts )
557
557
return tensor .assign (result ) if tensor else result
558
558
elif isinstance (expr , ufl .Interpolate ):
559
- orig_expr = expr
560
559
# Replace assembled children
561
560
_ , operand = expr .argument_slots ()
562
561
v , * assembled_operand = args
@@ -568,13 +567,9 @@ def base_form_assembly_visitor(self, expr, tensor, *args):
568
567
if (v , operand ) != expr .argument_slots ():
569
568
expr = reconstruct_interp (operand , v = v )
570
569
571
- # Different assembly procedures:
572
- # 1) Interpolate(Argument(V1, 1), Argument(V2.dual(), 0)) -> Jacobian (Interpolate matrix)
573
- # 2) Interpolate(Coefficient(...), Argument(V2.dual(), 0)) -> Operator (or Jacobian action)
574
- # 3) Interpolate(Argument(V1, 0), Argument(V2.dual(), 1)) -> Jacobian adjoint
575
- # 4) Interpolate(Argument(V1, 0), Cofunction(...)) -> Action of the Jacobian adjoint
576
- # This can be generalized to the case where the first slot is an arbitray expression.
577
570
rank = len (expr .arguments ())
571
+ if rank > 2 :
572
+ raise ValueError ("Cannot assemble an Interpolate with more than two arguments" )
578
573
# If argument numbers have been swapped => Adjoint.
579
574
arg_operand = ufl .algorithms .extract_arguments (operand )
580
575
is_adjoint = (arg_operand and arg_operand [0 ].number () == 0 )
@@ -605,67 +600,14 @@ def base_form_assembly_visitor(self, expr, tensor, *args):
605
600
assemble (sub_interp , tensor = tensor .subfunctions [i ])
606
601
return tensor
607
602
608
- # Workaround: Renumber argument when needed since Interpolator assumes it takes a zero-numbered argument.
609
- if not is_adjoint and rank == 2 :
610
- v0 , v1 = expr .arguments ()
611
- expr = ufl .replace (expr , {v0 : v0 .reconstruct (number = v1 .number ()),
612
- v1 : v1 .reconstruct (number = v0 .number ())})
613
- v , operand = expr .argument_slots ()
614
-
615
- # Matrix-free adjoint interpolation is only implemented by SameMeshInterpolator
616
- # so we need assemble the interpolator matrix if the meshes are different
617
- target_mesh = V .mesh ()
618
- source_mesh = extract_unique_domain (operand ) or target_mesh
619
- if is_adjoint and rank < 2 and source_mesh is not target_mesh :
620
- expr = reconstruct_interp (operand , v = V )
621
- matfree = (rank == len (expr .arguments ())) and (rank < 2 )
622
-
623
603
# Get the interpolator
624
604
interp_data = expr .interp_data .copy ()
625
605
default_missing_val = interp_data .pop ('default_missing_val' , None )
626
- if matfree and ((is_adjoint and rank == 1 ) or rank == 0 ):
627
- # Adjoint interpolation of a Cofunction or the action of a
628
- # Cofunction on an interpolated Function require INC access
629
- # on the output tensor
630
- interp_data ["access" ] = op2 .INC
631
-
632
- if rank == 1 and matfree and isinstance (tensor , firedrake .Function ):
606
+ if rank == 1 and isinstance (tensor , firedrake .Function ):
633
607
V = tensor
634
608
interpolator = firedrake .Interpolator (expr , V , ** interp_data )
635
-
636
609
# Assembly
637
- if matfree :
638
- # Assembling the operator
639
- return interpolator ._interpolate (output = tensor , default_missing_val = default_missing_val )
640
- elif rank == 0 :
641
- # Assembling the double action.
642
- Iu = interpolator ._interpolate (default_missing_val = default_missing_val )
643
- return assemble (ufl .Action (v , Iu ), tensor = tensor )
644
- elif rank == 1 :
645
- # Assembling the action of the Jacobian adjoint.
646
- if is_adjoint :
647
- return interpolator ._interpolate (v , output = tensor , adjoint = True , default_missing_val = default_missing_val )
648
- # Assembling the Jacobian action.
649
- else :
650
- return interpolator ._interpolate (operand , output = tensor , default_missing_val = default_missing_val )
651
- elif rank == 2 :
652
- res = tensor .petscmat if tensor else PETSc .Mat ()
653
- # Get the interpolation matrix
654
- op2_mat = interpolator .callable ()
655
- petsc_mat = op2_mat .handle
656
- if is_adjoint :
657
- # Out-of-place Hermitian transpose
658
- petsc_mat .hermitianTranspose (out = res )
659
- elif res :
660
- # Copy the interpolation matrix into the output tensor
661
- petsc_mat .copy (result = res )
662
- else :
663
- res = petsc_mat
664
- if tensor is None :
665
- tensor = self .assembled_matrix (orig_expr , res )
666
- return tensor
667
- else :
668
- raise ValueError ("Incompatible number of arguments." )
610
+ return interpolator .assemble (tensor = tensor , default_missing_val = default_missing_val )
669
611
elif tensor and isinstance (expr , (firedrake .Function , firedrake .Cofunction , firedrake .MatrixBase )):
670
612
return tensor .assign (expr )
671
613
elif tensor and isinstance (expr , ufl .ZeroBaseForm ):
0 commit comments