def map_operator_binding(self, expr): from grudge.symbolic.primitives import TracePair from grudge.symbolic.mappers.type_inference import ( type_info, QuadratureRepresentation) # {{{ figure out field type try: field_type = self.typedict[expr.field] except TypeError: # numpy arrays are not hashable # has_quad_operand remains unset assert isinstance(expr.field, np.ndarray) else: try: field_repr_tag = field_type.repr_tag except AttributeError: # boundary pairs are not assigned types assert isinstance(expr.field, TracePair) has_quad_operand = False else: has_quad_operand = isinstance(field_repr_tag, QuadratureRepresentation) # }}} # Based on where this is run in the symbolic operator processing # pipeline, we may encounter both reference and non-reference # operators. # {{{ elementwise operators if isinstance(expr.op, op.MassOperator) and has_quad_operand: return op.QuadratureMassOperator( field_repr_tag.discretization_tag)(self.rec(expr.field)) elif isinstance(expr.op, op.RefMassOperator) and has_quad_operand: return op.RefQuadratureMassOperator( field_repr_tag.discretization_tag)(self.rec(expr.field)) elif (isinstance(expr.op, op.StiffnessTOperator) and has_quad_operand): return op.QuadratureStiffnessTOperator( expr.op.xyz_axis, field_repr_tag.discretization_tag)(self.rec(expr.field)) elif (isinstance(expr.op, op.RefStiffnessTOperator) and has_quad_operand): return op.RefQuadratureStiffnessTOperator( expr.op.xyz_axis, field_repr_tag.discretization_tag)(self.rec(expr.field)) elif (isinstance(expr.op, op.QuadratureGridUpsampler) and isinstance(field_type, type_info.BoundaryVectorBase)): # potential shortcut: # if (isinstance(expr.field, OperatorBinding) # and isinstance(expr.field.op, RestrictToBoundary)): # return QuadratureRestrictToBoundary( # expr.field.op.tag, expr.op.discretization_tag)( # self.rec(expr.field.field)) return op.QuadratureBoundaryGridUpsampler( expr.op.discretization_tag, field_type.boundary_tag)(expr.field) # }}} elif isinstance(expr.op, op.RestrictToBoundary) and has_quad_operand: raise TypeError( "RestrictToBoundary cannot be applied to " "quadrature-based operands--use QuadUpsample(Boundarize(...))") else: return IdentityMapper.map_operator_binding(self, expr)
def map_operator_binding(self, expr): from grudge.symbolic.primitives import BoundaryPair from grudge.symbolic.mappers.type_inference import ( type_info, QuadratureRepresentation) # {{{ figure out field type try: field_type = self.typedict[expr.field] except TypeError: # numpy arrays are not hashable # has_quad_operand remains unset assert isinstance(expr.field, np.ndarray) else: try: field_repr_tag = field_type.repr_tag except AttributeError: # boundary pairs are not assigned types assert isinstance(expr.field, BoundaryPair) has_quad_operand = False else: has_quad_operand = isinstance(field_repr_tag, QuadratureRepresentation) # }}} # Based on where this is run in the symbolic operator processing # pipeline, we may encounter both reference and non-reference # operators. # {{{ elementwise operators if isinstance(expr.op, op.MassOperator) and has_quad_operand: return op.QuadratureMassOperator( field_repr_tag.quadrature_tag)(self.rec(expr.field)) elif isinstance(expr.op, op.RefMassOperator) and has_quad_operand: return op.RefQuadratureMassOperator( field_repr_tag.quadrature_tag)(self.rec(expr.field)) elif (isinstance(expr.op, op.StiffnessTOperator) and has_quad_operand): return op.QuadratureStiffnessTOperator( expr.op.xyz_axis, field_repr_tag.quadrature_tag)( self.rec(expr.field)) elif (isinstance(expr.op, op.RefStiffnessTOperator) and has_quad_operand): return op.RefQuadratureStiffnessTOperator( expr.op.xyz_axis, field_repr_tag.quadrature_tag)( self.rec(expr.field)) elif (isinstance(expr.op, op.QuadratureGridUpsampler) and isinstance(field_type, type_info.BoundaryVectorBase)): # potential shortcut: # if (isinstance(expr.field, OperatorBinding) # and isinstance(expr.field.op, RestrictToBoundary)): # return QuadratureRestrictToBoundary( # expr.field.op.tag, expr.op.quadrature_tag)( # self.rec(expr.field.field)) return op.QuadratureBoundaryGridUpsampler( expr.op.quadrature_tag, field_type.boundary_tag)(expr.field) # }}} elif isinstance(expr.op, op.RestrictToBoundary) and has_quad_operand: raise TypeError("RestrictToBoundary cannot be applied to " "quadrature-based operands--use QuadUpsample(Boundarize(...))") # {{{ flux operator specialization elif isinstance(expr.op, op.FluxOperatorBase): from pytools.obj_array import with_object_array_or_scalar repr_tag_cell = [None] def process_flux_arg(flux_arg): arg_repr_tag = self.typedict[flux_arg].repr_tag if repr_tag_cell[0] is None: repr_tag_cell[0] = arg_repr_tag else: # An error for this condition is generated by # the type inference pass. assert arg_repr_tag == repr_tag_cell[0] is_boundary = isinstance(expr.field, BoundaryPair) if is_boundary: bpair = expr.field with_object_array_or_scalar(process_flux_arg, bpair.field) with_object_array_or_scalar(process_flux_arg, bpair.bfield) else: with_object_array_or_scalar(process_flux_arg, expr.field) is_quad = isinstance(repr_tag_cell[0], QuadratureRepresentation) if is_quad: assert not expr.op.is_lift quad_tag = repr_tag_cell[0].quadrature_tag new_fld = self.rec(expr.field) flux = expr.op.flux if is_boundary: if is_quad: return op.QuadratureBoundaryFluxOperator( flux, quad_tag, bpair.tag)(new_fld) else: return op.BoundaryFluxOperator(flux, bpair.tag)(new_fld) else: if is_quad: return op.QuadratureFluxOperator(flux, quad_tag)(new_fld) else: return op.FluxOperator(flux, expr.op.is_lift)(new_fld) # }}} else: return IdentityMapper.map_operator_binding(self, expr)