Ejemplo n.º 1
0
    def map_constant(self, expr):
        from grudge.tools import is_zero

        if is_zero(expr):
            return 0
        else:
            return op.OperatorBinding(op.InverseMassOperator(),
                                      self.outer_mass_contractor(expr))
Ejemplo n.º 2
0
    def map_product(self, expr):
        def is_scalar(expr):
            return isinstance(expr, (int, float, complex, sym.ScalarParameter))

        from pytools import len_iterable
        nonscalar_count = len_iterable(ch for ch in expr.children
                                       if not is_scalar(ch))

        if nonscalar_count > 1:
            # too complicated, don't touch it
            self.extra_operator_count += 1
            return op.InverseMassOperator()(self.outer_mass_contractor(expr))
        else:

            def do_map(expr):
                if is_scalar(expr):
                    return expr
                else:
                    return self.rec(expr)

            return expr.__class__(
                tuple(do_map(child) for child in expr.children))
Ejemplo n.º 3
0
    def map_operator_binding(self, binding):
        if isinstance(binding.op, op.MassOperator):
            return binding.field
        elif isinstance(binding.op, op.StiffnessOperator):
            return op.DifferentiationOperator(binding.op.xyz_axis)(
                self.outer_mass_contractor(binding.field))
        elif isinstance(binding.op, op.StiffnessTOperator):
            return op.MInvSTOperator(binding.op.xyz_axis)(
                self.outer_mass_contractor(binding.field))
        elif isinstance(binding.op, op.FluxOperator):
            assert not binding.op.is_lift

            return op.FluxOperator(binding.op.flux, is_lift=True)(
                self.outer_mass_contractor(binding.field))
        elif isinstance(binding.op, op.BoundaryFluxOperator):
            assert not binding.op.is_lift

            return op.BoundaryFluxOperator(
                binding.op.flux, binding.op.boundary_tag,
                is_lift=True)(self.outer_mass_contractor(binding.field))
        else:
            self.extra_operator_count += 1
            return op.InverseMassOperator()(
                self.outer_mass_contractor(binding))
Ejemplo n.º 4
0
    def map_operator_binding(self, expr):
        # Global-to-reference is run after operator specialization, so
        # if we encounter non-quadrature operators here, we know they
        # must be nodal.

        dd_in = expr.op.dd_in
        dd_out = expr.op.dd_out

        if dd_in.is_volume():
            dim = self.dim
        else:
            dim = self.dim - 1

        jac_in = sym.area_element(self.ambient_dim, dim, dd=dd_in)
        jac_noquad = sym.area_element(self.ambient_dim,
                                      dim,
                                      dd=dd_in.with_discr_tag(
                                          dof_desc.DISCR_TAG_BASE))

        def rewrite_derivative(ref_class, field, dd_in, with_jacobian=True):
            def imd(rst):
                return sym.inverse_surface_metric_derivative(
                    rst,
                    expr.op.xyz_axis,
                    ambient_dim=self.ambient_dim,
                    dim=self.dim,
                    dd=dd_in)

            rec_field = self.rec(field)
            if with_jacobian:
                jac_tag = sym.area_element(self.ambient_dim,
                                           self.dim,
                                           dd=dd_in)
                rec_field = jac_tag * rec_field

                return sum(
                    ref_class(rst_axis, dd_in=dd_in)(rec_field * imd(rst_axis))
                    for rst_axis in range(self.dim))
            else:
                return sum(
                    ref_class(rst_axis, dd_in=dd_in)(rec_field) * imd(rst_axis)
                    for rst_axis in range(self.dim))

        if isinstance(expr.op, op.MassOperator):
            return op.RefMassOperator(dd_in,
                                      dd_out)(jac_in * self.rec(expr.field))

        elif isinstance(expr.op, op.InverseMassOperator):
            # based on https://arxiv.org/pdf/1608.03836.pdf
            return (
                1.0 / jac_in *
                op.RefInverseMassOperator(dd_in, dd_out)(self.rec(expr.field)))

        elif isinstance(expr.op, op.FaceMassOperator):
            jac_in_surf = sym.area_element(self.ambient_dim,
                                           self.dim - 1,
                                           dd=dd_in)
            return op.RefFaceMassOperator(dd_in, dd_out)(jac_in_surf *
                                                         self.rec(expr.field))

        elif isinstance(expr.op, op.StiffnessOperator):
            return op.RefMassOperator(dd_in=dd_in, dd_out=dd_out)(
                jac_noquad *
                self.rec(op.DiffOperator(expr.op.xyz_axis)(expr.field)))

        elif isinstance(expr.op, op.DiffOperator):
            return rewrite_derivative(op.RefDiffOperator,
                                      expr.field,
                                      dd_in=dd_in,
                                      with_jacobian=False)

        elif isinstance(expr.op, op.StiffnessTOperator):
            return rewrite_derivative(op.RefStiffnessTOperator,
                                      expr.field,
                                      dd_in=dd_in)

        elif isinstance(expr.op, op.MInvSTOperator):
            return self.rec(op.InverseMassOperator()(op.StiffnessTOperator(
                expr.op.xyz_axis)(self.rec(expr.field))))

        else:
            return IdentityMapper.map_operator_binding(self, expr)
Ejemplo n.º 5
0
 def map_algebraic_leaf(self, expr):
     return op.OperatorBinding(op.InverseMassOperator(),
                               self.outer_mass_contractor(expr))
Ejemplo n.º 6
0
    def map_operator_binding(self, expr):
        # Global-to-reference is run after operator specialization, so
        # if we encounter non-quadrature operators here, we know they
        # must be nodal.

        if expr.op.dd_in.is_volume():
            dim = self.dim
        else:
            dim = self.dim - 1

        jac_in = sym.area_element(self.ambient_dim, dim, dd=expr.op.dd_in)
        jac_noquad = sym.area_element(self.ambient_dim, dim,
                dd=expr.op.dd_in.with_qtag(sym.QTAG_NONE))

        def rewrite_derivative(ref_class, field,  dd_in, with_jacobian=True):
            jac_tag = sym.area_element(self.ambient_dim, self.dim, dd=dd_in)

            rec_field = self.rec(field)
            if with_jacobian:
                rec_field = jac_tag * rec_field
            return sum(
                    sym.inverse_metric_derivative(
                        rst_axis, expr.op.xyz_axis,
                        ambient_dim=self.ambient_dim, dim=self.dim)
                    * ref_class(rst_axis, dd_in=dd_in)(rec_field)
                    for rst_axis in range(self.dim))

        if isinstance(expr.op, op.MassOperator):
            return op.RefMassOperator(expr.op.dd_in, expr.op.dd_out)(
                    jac_in * self.rec(expr.field))

        elif isinstance(expr.op, op.InverseMassOperator):
            return op.RefInverseMassOperator(expr.op.dd_in, expr.op.dd_out)(
                1/jac_in * self.rec(expr.field))

        elif isinstance(expr.op, op.FaceMassOperator):
            jac_in_surf = sym.area_element(self.ambient_dim, self.dim - 1,
                    dd=expr.op.dd_in)
            return op.RefFaceMassOperator(expr.op.dd_in, expr.op.dd_out)(
                    jac_in_surf * self.rec(expr.field))

        elif isinstance(expr.op, op.StiffnessOperator):
            return op.RefMassOperator()(
                    jac_noquad
                    * self.rec(
                        op.DiffOperator(expr.op.xyz_axis)(expr.field)))

        elif isinstance(expr.op, op.DiffOperator):
            return rewrite_derivative(
                    op.RefDiffOperator,
                    expr.field, dd_in=expr.op.dd_in, with_jacobian=False)

        elif isinstance(expr.op, op.StiffnessTOperator):
            return rewrite_derivative(
                    op.RefStiffnessTOperator,
                    expr.field, dd_in=expr.op.dd_in)

        elif isinstance(expr.op, op.MInvSTOperator):
            return self.rec(
                    op.InverseMassOperator()(
                        op.StiffnessTOperator(expr.op.xyz_axis)(
                            self.rec(expr.field))))

        else:
            return IdentityMapper.map_operator_binding(self, expr)