Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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)