Esempio n. 1
0
    def op_template_struct(self, u=None):
        from hedge.optemplate import Field
        if u is None:
            u = Field("u")

        result = DecayFitDiscontinuitySensorBase\
                .op_template_struct(self, u)

        from pymbolic.primitives import IfPositive
        from hedge.optemplate.primitives import (
                CFunction, ScalarParameter)
        from math import pi
        from hedge.optemplate.primitives import make_common_subexpression as cse

        if self.correct_for_fit_error:
            decay_expt = cse(result.decay_expt_corrected, "decay_expt")
        else:
            decay_expt = cse(result.decay_expt, "decay_expt")

        def flat_end_sin(x):
            return IfPositive(-pi/2-x,
                    -1, IfPositive(x-pi/2, 1, sin(x)))

        sin = CFunction("sin")
        isnan = CFunction("isnan")
        c_abs = CFunction("abs")

        visc_scale = Field("viscosity_scaling")

        result.sensor = IfPositive(c_abs(isnan(visc_scale)), 
                ScalarParameter("max_viscosity_scaling"),
                0.5*visc_scale
                * (1+flat_end_sin((decay_expt+2)*pi/2)))
        return result
Esempio n. 2
0
    def get_mu(self, q, to_quad_op):
        """
        :param to_quad_op: If not *None*, represents an operator which transforms
          nodal values onto a quadrature grid on which the returned :math:`\mu` 
          needs to be represented. In that case, *q* is assumed to already be on the
          same quadrature grid.
        """

        if to_quad_op is None:

            def to_quad_op(x):
                return x

        if self.mu == "sutherland":
            # Sutherland's law: !!!not tested!!!
            t_s = 110.4
            mu_inf = 1.735e-5
            result = cse(
                mu_inf * self.cse_temperature(q)**1.5 * (1 + t_s) /
                (self.cse_temperature(q) + t_s), "sutherland_mu")
        else:
            result = self.mu

        if self.artificial_viscosity_mode == "cns":
            mapped_sensor = self.sensor()
        else:
            mapped_sensor = None

        if mapped_sensor is not None:
            result = result + cse(to_quad_op(mapped_sensor), "quad_sensor")

        return cse(result, "mu")
Esempio n. 3
0
 def make_flux_bc_vector(tag, bc):
     if self.fixed_material:
         return bc
     else:
         from hedge.optemplate import BoundarizeOperator
         return join_fields(cse(BoundarizeOperator(tag)(epsilon)),
                            cse(BoundarizeOperator(tag)(mu)), bc)
Esempio n. 4
0
    def get_mu(self, q, to_quad_op):
        """
        :param to_quad_op: If not *None*, represents an operator which transforms
          nodal values onto a quadrature grid on which the returned :math:`\mu` 
          needs to be represented. In that case, *q* is assumed to already be on the
          same quadrature grid.
        """

        if to_quad_op is None:
            def to_quad_op(x):
                return x

        if self.mu == "sutherland":
            # Sutherland's law: !!!not tested!!!
            t_s = 110.4
            mu_inf = 1.735e-5
            result = cse(
                    mu_inf * self.cse_temperature(q) ** 1.5 * (1 + t_s) 
                    / (self.cse_temperature(q) + t_s),
                    "sutherland_mu")
        else:
            result = self.mu

        if self.artificial_viscosity_mode == "cns":
            mapped_sensor = self.sensor()
        else:
            mapped_sensor = None

        if mapped_sensor is not None:
            result = result + cse(to_quad_op(mapped_sensor), "quad_sensor")

        return cse(result, "mu")
Esempio n. 5
0
 def make_flux_bc_vector(tag, bc):
     if self.fixed_material:
         return bc
     else:
         from hedge.optemplate import BoundarizeOperator
         return join_fields(
                 cse(BoundarizeOperator(tag)(epsilon)),
                 cse(BoundarizeOperator(tag)(mu)),
                 bc)
Esempio n. 6
0
    def collision_update(self, f_bar):
        from hedge.optemplate.primitives import make_common_subexpression as cse
        rho = cse(self.rho(f_bar), "rho")
        rho_u = self.rho_u(f_bar)
        u = cse(rho_u / rho, "u")

        f_eq_func = self.method.f_equilibrium
        f_eq = make_obj_array(
            [f_eq_func(rho, alpha, u) for alpha in range(len(self.method))])

        return f_bar - 1 / (self.tau + 1 / 2) * (f_bar - f_eq)
Esempio n. 7
0
    def collision_update(self, f_bar):
        from hedge.optemplate.primitives import make_common_subexpression as cse
        rho = cse(self.rho(f_bar), "rho")
        rho_u = self.rho_u(f_bar)
        u = cse(rho_u/rho, "u")

        f_eq_func = self.method.f_equilibrium
        f_eq = make_obj_array([
            f_eq_func(rho, alpha, u) for alpha in range(len(self.method))])

        return f_bar - 1/(self.tau+1/2)*(f_bar - f_eq)
Esempio n. 8
0
    def characteristic_velocity_optemplate(self, state):
        from hedge.optemplate.operators import ElementwiseMaxOperator

        from hedge.optemplate.primitives import CFunction
        sqrt = CFunction("sqrt")

        sound_speed = cse(
            sqrt(self.equation_of_state.gamma * self.cse_p(state) /
                 self.cse_rho(state)), "sound_speed")
        u = self.cse_u(state)
        speed = cse(sqrt(numpy.dot(u, u)), "norm_u") + sound_speed
        return ElementwiseMaxOperator()(speed)
Esempio n. 9
0
    def characteristic_velocity_optemplate(self, state):
        from hedge.optemplate.operators import ElementwiseMaxOperator

        from hedge.optemplate.primitives import CFunction
        sqrt = CFunction("sqrt")

        sound_speed = cse(sqrt(
            self.equation_of_state.gamma*self.cse_p(state)/self.cse_rho(state)),
            "sound_speed")
        u = self.cse_u(state)
        speed = cse(sqrt(numpy.dot(u, u)), "norm_u") + sound_speed
        return ElementwiseMaxOperator()(speed)
Esempio n. 10
0
    def inflow_state_inner(self, normal, bc, name):
        # see hedge/doc/maxima/euler.mac
        return join_fields(
            # bc rho
            cse(bc.rho0
            + numpy.dot(normal, bc.dumvec)*bc.rho0/(2*bc.c0) + bc.dpm/(2*bc.c0*bc.c0), "bc_rho_"+name),

            # bc p
            cse(bc.p0
            + bc.c0*bc.rho0*numpy.dot(normal, bc.dumvec)/2 + bc.dpm/2, "bc_p_"+name),

            # bc u
            cse(bc.u0
            + normal*numpy.dot(normal, bc.dumvec)/2 + bc.dpm*normal/(2*bc.c0*bc.rho0), "bc_u_"+name))
Esempio n. 11
0
    def primitive_to_conservative(self, prims, use_cses=True):
        if not use_cses:
            from hedge.optemplate.primitives import make_common_subexpression as cse
        else:

            def cse(x, name):
                return x

        rho = prims[0]
        p = prims[1]
        u = prims[2:]
        e = self.equation_of_state.p_to_e(p, rho, u)

        return join_fields(rho, cse(e, "e"), cse(rho * u, "rho_u"))
Esempio n. 12
0
    def primitive_to_conservative(self, prims, use_cses=True):
        if not use_cses:
            from hedge.optemplate.primitives import make_common_subexpression as cse
        else:
            def cse(x, name): return x

        rho = prims[0]
        p = prims[1]
        u = prims[2:]
        e = self.equation_of_state.p_to_e(p, rho, u)

        return join_fields(
               rho,
               cse(e, "e"),
               cse(rho * u, "rho_u"))
Esempio n. 13
0
    def ic_expr(t, x, fields):
        from hedge.optemplate import CFunction
        from pymbolic.primitives import IfPositive
        from pytools.obj_array import make_obj_array

        tanh = CFunction("tanh")
        sin = CFunction("sin")

        rho = 1
        u0 = 0.05
        w = 0.05
        delta = 0.05

        from hedge.optemplate.primitives import make_common_subexpression as cse
        u = cse(
            make_obj_array([
                IfPositive(x[1] - 1 / 2, u0 * tanh(4 * (3 / 4 - x[1]) / w),
                           u0 * tanh(4 * (x[1] - 1 / 4) / w)),
                u0 * delta * sin(2 * np.pi * (x[0] + 1 / 4))
            ]), "u")

        return make_obj_array([
            op.method.f_equilibrium(rho, alpha, u)
            for alpha in range(len(op.method))
        ])
Esempio n. 14
0
    def ic_expr(t, x, fields):
        from hedge.optemplate import CFunction
        from pymbolic.primitives import IfPositive
        from pytools.obj_array import make_obj_array

        tanh = CFunction("tanh")
        sin = CFunction("sin")

        rho = 1
        u0 = 0.05
        w = 0.05
        delta = 0.05

        from hedge.optemplate.primitives import make_common_subexpression as cse
        u = cse(make_obj_array([
            IfPositive(x[1]-1/2,
                u0*tanh(4*(3/4-x[1])/w),
                u0*tanh(4*(x[1]-1/4)/w)),
            u0*delta*sin(2*np.pi*(x[0]+1/4))]),
            "u")

        return make_obj_array([
            op.method.f_equilibrium(rho, alpha, u)
            for alpha in range(len(op.method))
            ])
Esempio n. 15
0
    def grad_interior_flux(self, tgt, u):
        from hedge.optemplate.primitives import make_common_subexpression as cse
        n_times = tgt.normal_times_flux
        v_times = tgt.vec_times

        return n_times(
                cse(u.avg, "u_avg")
                - v_times(self.beta(tgt), n_times(u.int-u.ext)))
Esempio n. 16
0
    def inflow_state_inner(self, normal, bc, name):
        # see hedge/doc/maxima/euler.mac
        return join_fields(
            # bc rho
            cse(
                bc.rho0 + numpy.dot(normal, bc.dumvec) * bc.rho0 /
                (2 * bc.c0) + bc.dpm / (2 * bc.c0 * bc.c0), "bc_rho_" + name),

            # bc p
            cse(
                bc.p0 + bc.c0 * bc.rho0 * numpy.dot(normal, bc.dumvec) / 2 +
                bc.dpm / 2, "bc_p_" + name),

            # bc u
            cse(
                bc.u0 + normal * numpy.dot(normal, bc.dumvec) / 2 +
                bc.dpm * normal / (2 * bc.c0 * bc.rho0), "bc_u_" + name))
Esempio n. 17
0
    def grad_interior_flux(self, tgt, u):
        from hedge.optemplate.primitives import make_common_subexpression as cse
        n_times = tgt.normal_times_flux
        v_times = tgt.vec_times

        return n_times(
            cse(u.avg, "u_avg") -
            v_times(self.beta(tgt), n_times(u.int - u.ext)))
Esempio n. 18
0
    def make_bc_info(self, bc_name, tag, state, state0=None):
        """
        :param state0: The boundary 'free-stream' state around which the
          BC is linearized.
        """
        if state0 is None:
            state0 = make_sym_vector(bc_name, self.dimensions+2)

        state0 = cse(to_bdry_quad(state0))

        rho0 = self.rho(state0)
        p0 = self.cse_p(state0)
        u0 = self.cse_u(state0)

        c0 = (self.equation_of_state.gamma * p0 / rho0)**0.5

        from hedge.optemplate import BoundarizeOperator
        bdrize_op = BoundarizeOperator(tag)

        class SingleBCInfo(Record):
            pass

        return SingleBCInfo(
            rho0=rho0, p0=p0, u0=u0, c0=c0,

            # notation: suffix "m" for "minus", i.e. "interior"
            drhom=cse(self.rho(cse(to_bdry_quad(bdrize_op(state)))) 
                - rho0, "drhom"),
            dumvec=cse(self.cse_u(cse(to_bdry_quad(bdrize_op(state)))) 
                - u0, "dumvec"),
            dpm=cse(self.cse_p(cse(to_bdry_quad(bdrize_op(state)))) 
                - p0, "dpm"))
Esempio n. 19
0
    def flux(self, q):
        from pytools import delta

        return [ # one entry for each flux direction
                cse(join_fields(
                    # flux rho
                    self.rho_u(q)[i],

                    # flux E
                    cse(self.e(q)+self.cse_p(q))*self.cse_u(q)[i],

                    # flux rho_u
                    make_obj_array([
                        self.rho_u(q)[i]*self.cse_u(q)[j] 
                        + delta(i,j) * self.cse_p(q)
                        for j in range(self.dimensions)
                        ])
                    ), "%s_flux" % AXES[i])
                for i in range(self.dimensions)]
Esempio n. 20
0
    def div(self, tgt, bc_getter, dirichlet_tags, neumann_tags):
        """
        :param bc_getter: a function (tag, volume_expr) -> boundary expr.
          *volume_expr* will be None to query the Neumann condition.
        """

        from hedge.optemplate.primitives import make_common_subexpression as cse
        from hedge.flux import FluxVectorPlaceholder, PenaltyTerm

        n_times = tgt.normal_times_flux

        if tgt.strong_form:

            def adjust_flux(f):
                return n_times(flux_v.int) - f
        else:

            def adjust_flux(f):
                return f

        dim = tgt.dimensions

        flux_w = FluxVectorPlaceholder(2 * tgt.dimensions)
        flux_v = flux_w[:dim]
        pure_diff_v = flux_w[dim:]
        flux_args = (list(tgt.int_flux_operand) +
                     list(IPDGDerivativeGenerator()(tgt.int_flux_operand)))

        stab_term_generator = StabilizationTermGenerator(flux_args)
        stab_term = (self.stab_coefficient * PenaltyTerm() *
                     stab_term_generator(tgt.int_flux_operand))
        flux = n_times(pure_diff_v.avg - stab_term)

        from pytools.obj_array import make_obj_array
        flux_arg_int = cse(make_obj_array(stab_term_generator.flux_args))

        tgt.add_derivative(cse(tgt.operand))
        tgt.add_inner_fluxes(adjust_flux(flux), flux_arg_int)

        self.add_div_bcs(tgt, bc_getter, dirichlet_tags, neumann_tags,
                         stab_term, adjust_flux, flux_v, flux_arg_int,
                         2 * tgt.dimensions)
Esempio n. 21
0
    def outflow_state(self, state):
        from hedge.optemplate import make_normal
        normal = make_normal(self.outflow_tag, self.dimensions)
        bc = self.make_bc_info("bc_q_out", self.outflow_tag, state)

        # see hedge/doc/maxima/euler.mac
        return join_fields(
            # bc rho
            cse(bc.rho0
            + bc.drhom + numpy.dot(normal, bc.dumvec)*bc.rho0/(2*bc.c0)
            - bc.dpm/(2*bc.c0*bc.c0), "bc_rho_outflow"),

            # bc p
            cse(bc.p0
            + bc.c0*bc.rho0*numpy.dot(normal, bc.dumvec)/2 + bc.dpm/2, "bc_p_outflow"),

            # bc u
            cse(bc.u0
            + bc.dumvec - normal*numpy.dot(normal, bc.dumvec)/2
            + bc.dpm*normal/(2*bc.c0*bc.rho0), "bc_u_outflow"))
Esempio n. 22
0
    def flux(self, q):
        from pytools import delta

        return [  # one entry for each flux direction
            cse(
                join_fields(
                    # flux rho
                    self.rho_u(q)[i],

                    # flux E
                    cse(self.e(q) + self.cse_p(q)) * self.cse_u(q)[i],

                    # flux rho_u
                    make_obj_array([
                        self.rho_u(q)[i] * self.cse_u(q)[j] +
                        delta(i, j) * self.cse_p(q)
                        for j in range(self.dimensions)
                    ])),
                "%s_flux" % AXES[i]) for i in range(self.dimensions)
        ]
Esempio n. 23
0
        def subst_func(expr):
            from pymbolic.primitives import Subscript, Variable

            if isinstance(expr, Subscript):
                assert (isinstance(expr.aggregate, Variable)
                        and expr.aggregate.name == "q")

                return cbstate[expr.index]
            elif isinstance(expr, Variable) and expr.name == "sensor":
                from hedge.optemplate import BoundarizeOperator
                result = BoundarizeOperator(tag)(self.sensor())
                return cse(to_bdry_quad(result), "bdry_sensor")
Esempio n. 24
0
        def subst_func(expr):
            from pymbolic.primitives import Subscript, Variable

            if isinstance(expr, Subscript):
                assert (isinstance(expr.aggregate, Variable) 
                        and expr.aggregate.name == "q")

                return cbstate[expr.index]
            elif isinstance(expr, Variable) and expr.name =="sensor":
                from hedge.optemplate import BoundarizeOperator
                result = BoundarizeOperator(tag)(self.sensor())
                return cse(to_bdry_quad(result), "bdry_sensor")
Esempio n. 25
0
    def outflow_state(self, state):
        from hedge.optemplate import make_normal
        normal = make_normal(self.outflow_tag, self.dimensions)
        bc = self.make_bc_info("bc_q_out", self.outflow_tag, state)

        # see hedge/doc/maxima/euler.mac
        return join_fields(
            # bc rho
            cse(
                bc.rho0 + bc.drhom + numpy.dot(normal, bc.dumvec) * bc.rho0 /
                (2 * bc.c0) - bc.dpm / (2 * bc.c0 * bc.c0), "bc_rho_outflow"),

            # bc p
            cse(
                bc.p0 + bc.c0 * bc.rho0 * numpy.dot(normal, bc.dumvec) / 2 +
                bc.dpm / 2, "bc_p_outflow"),

            # bc u
            cse(
                bc.u0 + bc.dumvec - normal * numpy.dot(normal, bc.dumvec) / 2 +
                bc.dpm * normal / (2 * bc.c0 * bc.rho0), "bc_u_outflow"))
Esempio n. 26
0
    def tau(self, to_quad_op, state, mu=None):
        faceq_state = self.faceq_state()

        dimensions = self.dimensions

        # {{{ compute gradient of u ---------------------------------------
        # Use the product rule to compute the gradient of
        # u from the gradient of (rho u). This ensures we don't
        # compute the derivatives twice.

        from pytools.obj_array import with_object_array_or_scalar
        dq = with_object_array_or_scalar(to_quad_op, self.grad_of_state())

        q = cse(to_quad_op(state))

        du = numpy.zeros((dimensions, dimensions), dtype=object)
        for i in range(dimensions):
            for j in range(dimensions):
                du[i, j] = cse(
                    (dq[i + 2, j] - self.cse_u(q)[i] * dq[0, j]) / self.rho(q),
                    "du%d_d%s" % (i, AXES[j]))

        # }}}

        # {{{ put together viscous stress tau -----------------------------
        from pytools import delta

        if mu is None:
            mu = self.get_mu(q, to_quad_op)

        tau = numpy.zeros((dimensions, dimensions), dtype=object)
        for i in range(dimensions):
            for j in range(dimensions):
                tau[i, j] = cse(
                    mu *
                    cse(du[i, j] + du[j, i] -
                        2 / self.dimensions * delta(i, j) * numpy.trace(du)),
                    "tau_%d%d" % (i, j))

        return tau
Esempio n. 27
0
    def div(self, tgt, bc_getter, dirichlet_tags, neumann_tags):
        """
        :param bc_getter: a function (tag, volume_expr) -> boundary expr.
          *volume_expr* will be None to query the Neumann condition.
        """

        from hedge.optemplate.primitives import make_common_subexpression as cse
        from hedge.flux import FluxVectorPlaceholder, PenaltyTerm

        n_times = tgt.normal_times_flux

        if tgt.strong_form:
            def adjust_flux(f):
                return n_times(flux_v.int) - f
        else:
            def adjust_flux(f):
                return f

        dim = tgt.dimensions

        flux_w = FluxVectorPlaceholder(2*tgt.dimensions)
        flux_v = flux_w[:dim]
        pure_diff_v = flux_w[dim:]
        flux_args = (
                list(tgt.int_flux_operand)
                + list(IPDGDerivativeGenerator()(tgt.int_flux_operand)))

        stab_term_generator = StabilizationTermGenerator(flux_args)
        stab_term = (self.stab_coefficient * PenaltyTerm()
                * stab_term_generator(tgt.int_flux_operand))
        flux = n_times(pure_diff_v.avg - stab_term)

        from pytools.obj_array import make_obj_array
        flux_arg_int = cse(make_obj_array(stab_term_generator.flux_args))

        tgt.add_derivative(cse(tgt.operand))
        tgt.add_inner_fluxes(adjust_flux(flux), flux_arg_int)

        self.add_div_bcs(tgt, bc_getter, dirichlet_tags, neumann_tags,
                stab_term, adjust_flux, flux_v, flux_arg_int, 2*tgt.dimensions)
Esempio n. 28
0
    def tau(self, to_quad_op, state, mu=None):
        faceq_state = self.faceq_state()

        dimensions = self.dimensions

        # {{{ compute gradient of u ---------------------------------------
        # Use the product rule to compute the gradient of
        # u from the gradient of (rho u). This ensures we don't
        # compute the derivatives twice.

        from pytools.obj_array import with_object_array_or_scalar
        dq = with_object_array_or_scalar(
                to_quad_op, self.grad_of_state())

        q = cse(to_quad_op(state))

        du = numpy.zeros((dimensions, dimensions), dtype=object)
        for i in range(dimensions):
            for j in range(dimensions):
                du[i,j] = cse(
                        (dq[i+2,j] - self.cse_u(q)[i] * dq[0,j]) / self.rho(q),
                        "du%d_d%s" % (i, AXES[j]))

        # }}}

        # {{{ put together viscous stress tau -----------------------------
        from pytools import delta

        if mu is None:
            mu = self.get_mu(q, to_quad_op)

        tau = numpy.zeros((dimensions, dimensions), dtype=object)
        for i in range(dimensions):
            for j in range(dimensions):
                tau[i,j] = cse(mu * cse(du[i,j] + du[j,i] -
                           2/self.dimensions * delta(i,j) * numpy.trace(du)),
                           "tau_%d%d" % (i, j))

        return tau
Esempio n. 29
0
    def absorbing_bc(self, w=None):
        """Construct part of the flux operator template for 1st order
        absorbing boundary conditions.
        """

        from hedge.optemplate import normal
        absorb_normal = normal(self.absorb_tag, self.dimensions)

        from hedge.optemplate import BoundarizeOperator, Field
        from hedge.tools import join_fields

        e, h = self.split_eh(self.field_placeholder(w))

        if self.fixed_material:
            epsilon = self.epsilon
            mu = self.mu
        else:
            epsilon = cse(
                BoundarizeOperator(self.absorb_tag)(Field("epsilon")))
            mu = cse(BoundarizeOperator(self.absorb_tag)(Field("mu")))

        absorb_Z = (mu / epsilon)**0.5
        absorb_Y = 1 / absorb_Z

        absorb_e = BoundarizeOperator(self.absorb_tag)(e)
        absorb_h = BoundarizeOperator(self.absorb_tag)(h)

        bc = join_fields(
            absorb_e + 1 / 2 *
            (self.space_cross_h(absorb_normal,
                                self.space_cross_e(absorb_normal, absorb_e)) -
             absorb_Z * self.space_cross_h(absorb_normal, absorb_h)),
            absorb_h + 1 / 2 *
            (self.space_cross_e(absorb_normal,
                                self.space_cross_h(absorb_normal, absorb_h)) +
             absorb_Y * self.space_cross_e(absorb_normal, absorb_e)))

        return bc
Esempio n. 30
0
    def absorbing_bc(self, w=None):
        """Construct part of the flux operator template for 1st order
        absorbing boundary conditions.
        """

        from hedge.optemplate import normal
        absorb_normal = normal(self.absorb_tag, self.dimensions)

        from hedge.optemplate import BoundarizeOperator, Field
        from hedge.tools import join_fields

        e, h = self.split_eh(self.field_placeholder(w))

        if self.fixed_material:
            epsilon = self.epsilon
            mu = self.mu
        else:
            epsilon = cse(
                    BoundarizeOperator(self.absorb_tag)(Field("epsilon")))
            mu = cse(
                    BoundarizeOperator(self.absorb_tag)(Field("mu")))

        absorb_Z = (mu/epsilon)**0.5
        absorb_Y = 1/absorb_Z

        absorb_e = BoundarizeOperator(self.absorb_tag)(e)
        absorb_h = BoundarizeOperator(self.absorb_tag)(h)

        bc = join_fields(
                absorb_e + 1/2*(self.space_cross_h(absorb_normal, self.space_cross_e(
                    absorb_normal, absorb_e))
                    - absorb_Z*self.space_cross_h(absorb_normal, absorb_h)),
                absorb_h + 1/2*(
                    self.space_cross_e(absorb_normal, self.space_cross_h(
                        absorb_normal, absorb_h))
                    + absorb_Y*self.space_cross_e(absorb_normal, absorb_e)))

        return bc
Esempio n. 31
0
    def op_template(self, u=None):
        from pymbolic.primitives import IfPositive, Variable
        from hedge.optemplate.primitives import Field, ScalarParameter
        from hedge.optemplate.primitives import make_common_subexpression as cse
        from math import pi

        if u is None:
            u = Field("u")

        from hedge.optemplate.operators import (
                MassOperator, FilterOperator, OnesOperator)

        mode_truncator = FilterOperator(
                persson_peraire_filter_response_function)

        truncated_u = mode_truncator(u)
        diff = u - truncated_u

        el_norm_squared_mass_diff_u = OnesOperator()(MassOperator()(diff)*diff)
        el_norm_squared_mass_u = OnesOperator()(MassOperator()(u)*u)

        capital_s_e = cse(el_norm_squared_mass_diff_u / el_norm_squared_mass_u,
                "S_e")

        sin = Variable("sin")
        log10 = Variable("log10")

        s_e = cse(log10(capital_s_e), "s_e")
        kappa = ScalarParameter("kappa")
        eps0 = ScalarParameter("eps0")
        s_0 = ScalarParameter("s_0")

        return IfPositive(s_0-self.kappa-s_e,
                0,
                IfPositive(s_e-self.kappa-s_0,
                    eps0,
                    eps0/2*(1+sin(pi*(s_e-s_0)/self.kappa))))
Esempio n. 32
0
def test_quadrature_tri_mass_mat_monomial():
    """Check that quadrature integration on triangles is exact as designed."""

    from hedge.mesh.generator import make_square_mesh

    mesh = make_square_mesh(a=-1, b=1, max_area=4 * 1 / 8 + 0.001)
    order = 4
    discr = discr_class(
        mesh, order=order, debug=discr_class.noninteractive_debug_flags(), quad_min_degrees={"quad": 3 * order}
    )

    m, n = 2, 1
    f = Monomial((m, n))
    f_vec = discr.interpolate_volume_function(lambda x, el: f(x))

    from hedge.discretization import ones_on_volume

    ones = ones_on_volume(discr)

    if False:
        from hedge.visualization import SiloVisualizer

        vis = SiloVisualizer(discr)
        visf = vis.make_file("test")
        vis.add_data(visf, [("f", f_vec * f_vec)])
        visf.close()

    from hedge.optemplate import MassOperator, Field, QuadratureGridUpsampler

    f_fld = Field("f")
    mass_op = discr.compile(MassOperator()(f_fld * f_fld))
    from hedge.optemplate.primitives import make_common_subexpression as cse

    f_upsamp = cse(QuadratureGridUpsampler("quad")(f_fld))
    quad_mass_op = discr.compile(MassOperator()(f_upsamp * f_upsamp))

    num_integral_1 = numpy.dot(ones, mass_op(f=f_vec))
    num_integral_2 = numpy.dot(ones, quad_mass_op(f=f_vec))
    true_integral = 4 / ((2 * m + 1) * (2 * n + 1))
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    print num_integral_1, num_integral_2, true_integral
    print err_1, err_2
    assert err_1 > 1e-8
    assert err_2 < 1e-14
def test_quadrature_tri_mass_mat_monomial():
    """Check that quadrature integration on triangles is exact as designed."""

    from hedge.mesh.generator import make_square_mesh

    mesh = make_square_mesh(a=-1, b=1, max_area=4 * 1 / 8 + 0.001)
    order = 4
    discr = discr_class(mesh,
                        order=order,
                        debug=discr_class.noninteractive_debug_flags(),
                        quad_min_degrees={"quad": 3 * order})

    m, n = 2, 1
    f = Monomial((m, n))
    f_vec = discr.interpolate_volume_function(lambda x, el: f(x))

    from hedge.discretization import ones_on_volume
    ones = ones_on_volume(discr)

    if False:
        from hedge.visualization import SiloVisualizer
        vis = SiloVisualizer(discr)
        visf = vis.make_file("test")
        vis.add_data(visf, [("f", f_vec * f_vec)])
        visf.close()

    from hedge.optemplate import (MassOperator, Field, QuadratureGridUpsampler)
    f_fld = Field("f")
    mass_op = discr.compile(MassOperator()(f_fld * f_fld))
    from hedge.optemplate.primitives import make_common_subexpression as cse
    f_upsamp = cse(QuadratureGridUpsampler("quad")(f_fld))
    quad_mass_op = discr.compile(MassOperator()(f_upsamp * f_upsamp))

    num_integral_1 = numpy.dot(ones, mass_op(f=f_vec))
    num_integral_2 = numpy.dot(ones, quad_mass_op(f=f_vec))
    true_integral = 4 / ((2 * m + 1) * (2 * n + 1))
    err_1 = abs(num_integral_1 - true_integral)
    err_2 = abs(num_integral_2 - true_integral)
    print num_integral_1, num_integral_2, true_integral
    print err_1, err_2
    assert err_1 > 1e-8
    assert err_2 < 1e-14
Esempio n. 34
0
    def incident_bc(self, w=None):
        "Flux terms for incident boundary conditions"
        # NOTE: Untested for inhomogeneous materials, but would usually be
        # physically meaningless anyway (are there exceptions to this?)

        e, h = self.split_eh(self.field_placeholder(w))
        if not self.fixed_material:
            from warnings import warn
            if self.incident_tag != hedge.mesh.TAG_NONE:
                warn("Incident boundary conditions assume homogeneous"
                     " background material, results may be unphysical")

        from hedge.tools import count_subset
        fld_cnt = count_subset(self.get_eh_subset())

        from hedge.tools import is_zero
        incident_bc_data = self.incident_bc_data(self, e, h)
        if is_zero(incident_bc_data):
            return make_obj_array([0] * fld_cnt)
        else:
            return cse(-incident_bc_data)
Esempio n. 35
0
    def incident_bc(self, w=None):
        "Flux terms for incident boundary conditions"
        # NOTE: Untested for inhomogeneous materials, but would usually be
        # physically meaningless anyway (are there exceptions to this?)

        e, h = self.split_eh(self.field_placeholder(w))
        if not self.fixed_material:
            from warnings import warn
            if self.incident_tag != hedge.mesh.TAG_NONE:
                warn("Incident boundary conditions assume homogeneous"
                     " background material, results may be unphysical")

        from hedge.tools import count_subset
        fld_cnt = count_subset(self.get_eh_subset())

        from hedge.tools import is_zero
        incident_bc_data = self.incident_bc_data(self, e, h)
        if is_zero(incident_bc_data):
            return make_obj_array([0]*fld_cnt)
        else:
            return cse(-incident_bc_data)
Esempio n. 36
0
    def make_bc_info(self, bc_name, tag, state, state0=None):
        """
        :param state0: The boundary 'free-stream' state around which the
          BC is linearized.
        """
        if state0 is None:
            state0 = make_sym_vector(bc_name, self.dimensions + 2)

        state0 = cse(to_bdry_quad(state0))

        rho0 = self.rho(state0)
        p0 = self.cse_p(state0)
        u0 = self.cse_u(state0)

        c0 = (self.equation_of_state.gamma * p0 / rho0)**0.5

        from hedge.optemplate import BoundarizeOperator
        bdrize_op = BoundarizeOperator(tag)

        class SingleBCInfo(Record):
            pass

        return SingleBCInfo(
            rho0=rho0,
            p0=p0,
            u0=u0,
            c0=c0,

            # notation: suffix "m" for "minus", i.e. "interior"
            drhom=cse(
                self.rho(cse(to_bdry_quad(bdrize_op(state)))) - rho0, "drhom"),
            dumvec=cse(
                self.cse_u(cse(to_bdry_quad(bdrize_op(state)))) - u0,
                "dumvec"),
            dpm=cse(
                self.cse_p(cse(to_bdry_quad(bdrize_op(state)))) - p0, "dpm"))
Esempio n. 37
0
 def grad_of_state_func(self, func, of_what_descr):
     return cse(
         self.grad_of(func(self.volq_state()), func(self.faceq_state())),
         "grad_" + of_what_descr)
Esempio n. 38
0
    def op_template(self, sensor_scaling=None, viscosity_only=False):
        u = self.cse_u
        rho = self.cse_rho
        rho_u = self.rho_u
        p = self.p
        e = self.e

        # {{{ artificial diffusion
        def make_artificial_diffusion():
            if self.artificial_viscosity_mode not in ["diffusion"]:
                return 0

            dq = self.grad_of_state()

            return make_obj_array([
                self.div(
                    to_vol_quad(self.sensor()) * to_vol_quad(dq[i]),
                    to_int_face_quad(self.sensor()) * to_int_face_quad(dq[i]))
                for i in range(dq.shape[0])
            ])

        # }}}

        # {{{ state setup

        volq_flux = self.flux(self.volq_state())
        faceq_flux = self.flux(self.faceq_state())

        from hedge.optemplate.primitives import CFunction
        sqrt = CFunction("sqrt")

        speed = self.characteristic_velocity_optemplate(self.state())

        has_viscosity = not is_zero(self.get_mu(self.state(), to_quad_op=None))

        # }}}

        # {{{ operator assembly -----------------------------------------------
        from hedge.flux.tools import make_lax_friedrichs_flux
        from hedge.optemplate.operators import InverseMassOperator

        from hedge.optemplate.tools import make_stiffness_t

        primitive_bcs_as_quad_conservative = dict(
            (tag, self.primitive_to_conservative(to_bdry_quad(bc))) for tag, bc
            in self.get_primitive_boundary_conditions().iteritems())

        def get_bc_tuple(tag):
            state = self.state()
            bc = make_obj_array(
                [self.get_boundary_condition_for(tag, s_i) for s_i in state])
            return tag, bc, self.flux(bc)

        first_order_part = InverseMassOperator()(
            numpy.dot(make_stiffness_t(self.dimensions), volq_flux) -
            make_lax_friedrichs_flux(
                wave_speed=cse(to_int_face_quad(speed), "emax_c"),
                state=self.faceq_state(),
                fluxes=faceq_flux,
                bdry_tags_states_and_fluxes=[
                    get_bc_tuple(tag) for tag in self.get_boundary_tags()
                ],
                strong=False))

        if viscosity_only:
            first_order_part = 0 * first_order_part

        result = join_fields(
            first_order_part + self.make_second_order_part() +
            make_artificial_diffusion() + self.make_extra_terms(), speed)

        if self.source is not None:
            result = result + join_fields(
                make_sym_vector("source_vect", len(self.state())),
                # extra field for speed
                0)

        return result
Esempio n. 39
0
    def __init__(self, **kwargs):
        from hedge.optemplate.primitives import make_common_subexpression as cse

        Record.__init__(self, dict((name, cse(expr, name))
            for name, expr in kwargs.iteritems()))
Esempio n. 40
0
 def grad_of_state_func(self, func, of_what_descr):
     return cse(self.grad_of(
         func(self.volq_state()),
         func(self.faceq_state())),
         "grad_"+of_what_descr)
Esempio n. 41
0
 def faceq_state(self):
     return cse(to_int_face_quad(self.state()), "face_quad_state")
Esempio n. 42
0
    def op_template(self, sensor_scaling=None, viscosity_only=False):
        u = self.cse_u
        rho = self.cse_rho
        rho_u = self.rho_u
        p = self.p
        e = self.e

        # {{{ artificial diffusion
        def make_artificial_diffusion():
            if self.artificial_viscosity_mode not in ["diffusion"]:
                return 0

            dq = self.grad_of_state()

            return make_obj_array([
                self.div(
                    to_vol_quad(self.sensor())*to_vol_quad(dq[i]),
                    to_int_face_quad(self.sensor())*to_int_face_quad(dq[i])) 
                for i in range(dq.shape[0])])
        # }}}

        # {{{ state setup

        volq_flux = self.flux(self.volq_state())
        faceq_flux = self.flux(self.faceq_state())

        from hedge.optemplate.primitives import CFunction
        sqrt = CFunction("sqrt")

        speed = self.characteristic_velocity_optemplate(self.state())

        has_viscosity = not is_zero(self.get_mu(self.state(), to_quad_op=None))

        # }}}

        # {{{ operator assembly -----------------------------------------------
        from hedge.flux.tools import make_lax_friedrichs_flux
        from hedge.optemplate.operators import InverseMassOperator

        from hedge.optemplate.tools import make_stiffness_t

        primitive_bcs_as_quad_conservative = dict(
                (tag, self.primitive_to_conservative(to_bdry_quad(bc)))
                for tag, bc in 
                self.get_primitive_boundary_conditions().iteritems())

        def get_bc_tuple(tag):
            state = self.state()
            bc = make_obj_array([
                self.get_boundary_condition_for(tag, s_i) for s_i in state])
            return tag, bc, self.flux(bc)

        first_order_part = InverseMassOperator()(
                numpy.dot(make_stiffness_t(self.dimensions), volq_flux)
                - make_lax_friedrichs_flux(
                    wave_speed=cse(to_int_face_quad(speed), "emax_c"),

                    state=self.faceq_state(), fluxes=faceq_flux,
                    bdry_tags_states_and_fluxes=[
                        get_bc_tuple(tag) for tag in self.get_boundary_tags()],
                    strong=False))

        if viscosity_only:
            first_order_part = 0*first_order_part

        result = join_fields(
                first_order_part 
                + self.make_second_order_part()
                + make_artificial_diffusion()
                + self.make_extra_terms(),
                 speed)

        if self.source is not None:
            result = result + join_fields(
                    make_sym_vector("source_vect", len(self.state())),
                    # extra field for speed
                    0)

        return result
Esempio n. 43
0
 def cse_rho_u(self, q):
     return cse(self.rho_u(q), "rho_u")
Esempio n. 44
0
 def cse_p(self, q):
     return cse(self.p(q), "p")
Esempio n. 45
0
 def cse_rho_u(self, q):
     return cse(self.rho_u(q), "rho_u")
Esempio n. 46
0
 def cse_rho(self, q):
     return cse(self.rho(q), "rho")
Esempio n. 47
0
 def cse_u(self, q):
     return cse(self.u(q), "u")
Esempio n. 48
0
 def cse_temperature(self, q):
     return cse(self.temperature(q), "temperature")
Esempio n. 49
0
 def minv_all(self):
     from hedge.optemplate.primitives import make_common_subexpression as cse
     from hedge.optemplate.operators import InverseMassOperator
     return (
         cse(InverseMassOperator()(self.local_derivatives), "grad_loc") +
         cse(InverseMassOperator()(self.fluxes), "grad_flux"))
Esempio n. 50
0
 def cse_p(self, q):
     return cse(self.p(q), "p")
Esempio n. 51
0
    def op_template_struct(self, u, with_baseline=True):
        from hedge.optemplate.operators import (
                MassOperator, OnesOperator, InverseVandermondeOperator,
                InverseMassOperator)
        from hedge.optemplate.primitives import Field
        from hedge.optemplate.tools import get_flux_operator
        from hedge.optemplate.primitives import make_common_subexpression as cse
        from hedge.optemplate.primitives import CFunction
        from pymbolic.primitives import Variable

        if u is None:
            u = Field("u")

        from hedge.flux import (
                FluxScalarPlaceholder, ElementOrder,
                ElementJacobian, FaceJacobian, flux_abs)

        log, exp, sqrt = CFunction("log"), CFunction("exp"), CFunction("sqrt")

        if False:
            # On the whole, this should scale like u.
            # Columns of lift scale like 1/N^2, compensate for that.
            # Further compensate for all geometric factors.

            u_flux = FluxScalarPlaceholder(0)

            jump_part = InverseMassOperator()(
                    get_flux_operator(
                        ElementJacobian()/(ElementOrder()**2 * FaceJacobian())
                            *flux_abs(u_flux.ext - u_flux.int))(u))

        baseline_squared = Field("baseline_squared")
        el_norm_u_squared = cse(
                OnesOperator()(MassOperator()(u)*u),
                "l2_norm_u")

        indicator_modal_coeffs = cse(
                InverseVandermondeOperator()(u),
                #InverseChebyshevVandermondeOperator()(u),
                "u_modes")

        indicator_modal_coeffs_squared = indicator_modal_coeffs**2

        if self.mode_processor is not None:
            indicator_modal_coeffs_squared = \
                    Variable("mode_processor")(indicator_modal_coeffs_squared)

        log_modal_coeffs = cse(
                log(indicator_modal_coeffs_squared
                    + baseline_squared*el_norm_u_squared
                    )/2,
                "log_modal_coeffs")

        if False:
            modal_coeffs_jump = cse(
                    InverseVandermondeOperator()(jump_part),
                    "jump_modes")
            log_modal_coeffs_jump = cse(
                    log(modal_coeffs_jump**2)/2,
                    "lmc_jump")

        # fit to c * n**s
        expt_op = DecayExponentOperator(
                self.ignored_modes, self.weight_mode)
        log_const_op = LogDecayConstantOperator(
                self.ignored_modes, self.weight_mode)

        mode_weights = Field("mode_weights")

        weighted_log_modal_coeffs = mode_weights*log_modal_coeffs

        s = cse(expt_op(weighted_log_modal_coeffs),
                "first_decay_expt")
        log_c = cse(log_const_op(weighted_log_modal_coeffs),
                "first_decay_coeff")
        c = exp(log_const_op(weighted_log_modal_coeffs))

        log_mode_numbers = Field("log_mode_numbers")
        estimated_log_modal_coeffs = cse(
                log_c + s*log_mode_numbers,
                "estimated_log_modal_coeffs")
        estimate_error = cse(
                sqrt((estimated_log_modal_coeffs-weighted_log_modal_coeffs)**2),
                "estimate_error")

        log_modal_coeffs_corrected = log_modal_coeffs + estimate_error
        s_corrected = expt_op(mode_weights*log_modal_coeffs_corrected)

        return DecayInformation(
                indicator_modal_coeffs=indicator_modal_coeffs,
                decay_expt=s, c=c,
                log_modal_coeffs=log_modal_coeffs,
                weighted_log_modal_coeffs=weighted_log_modal_coeffs,
                estimated_log_modal_coeffs=estimated_log_modal_coeffs,
                decay_expt_corrected=s_corrected,
                )
Esempio n. 52
0
 def cse_temperature(self, q):
     return cse(self.temperature(q), "temperature")
Esempio n. 53
0
 def volq_state(self):
     return cse(to_vol_quad(self.state()), "vol_quad_state")
Esempio n. 54
0
    def op_template(self, with_sensor=False):
        # {{{ operator preliminaries ------------------------------------------
        from hedge.optemplate import (Field, BoundaryPair, get_flux_operator,
                                      make_stiffness_t, InverseMassOperator,
                                      make_sym_vector, ElementwiseMaxOperator,
                                      BoundarizeOperator)

        from hedge.optemplate.primitives import make_common_subexpression as cse

        from hedge.optemplate.operators import (
            QuadratureGridUpsampler, QuadratureInteriorFacesGridUpsampler)

        to_quad = QuadratureGridUpsampler("quad")
        to_if_quad = QuadratureInteriorFacesGridUpsampler("quad")

        from hedge.tools import join_fields, \
                                ptwise_dot

        u = Field("u")
        v = make_sym_vector("v", self.dimensions)
        c = ElementwiseMaxOperator()(ptwise_dot(1, 1, v, v))

        quad_u = cse(to_quad(u))
        quad_v = cse(to_quad(v))

        w = join_fields(u, v, c)
        quad_face_w = to_if_quad(w)
        # }}}

        # {{{ boundary conditions ---------------------------------------------

        from hedge.mesh import TAG_ALL
        bc_c = to_quad(BoundarizeOperator(TAG_ALL)(c))
        bc_u = to_quad(Field("bc_u"))
        bc_v = to_quad(BoundarizeOperator(TAG_ALL)(v))

        if self.bc_u_f is "None":
            bc_w = join_fields(0, bc_v, bc_c)
        else:
            bc_w = join_fields(bc_u, bc_v, bc_c)

        minv_st = make_stiffness_t(self.dimensions)
        m_inv = InverseMassOperator()

        flux_op = get_flux_operator(self.flux())
        # }}}

        # {{{ diffusion -------------------------------------------------------
        if with_sensor or (self.diffusion_coeff is not None
                           and self.diffusion_coeff != 0):
            if self.diffusion_coeff is None:
                diffusion_coeff = 0
            else:
                diffusion_coeff = self.diffusion_coeff

            if with_sensor:
                diffusion_coeff += Field("sensor")

            from hedge.second_order import SecondDerivativeTarget

            # strong_form here allows IPDG to reuse the value of grad u.
            grad_tgt = SecondDerivativeTarget(self.dimensions,
                                              strong_form=True,
                                              operand=u)

            self.diffusion_scheme.grad(grad_tgt,
                                       bc_getter=None,
                                       dirichlet_tags=[],
                                       neumann_tags=[])

            div_tgt = SecondDerivativeTarget(self.dimensions,
                                             strong_form=False,
                                             operand=diffusion_coeff *
                                             grad_tgt.minv_all)

            self.diffusion_scheme.div(div_tgt,
                                      bc_getter=None,
                                      dirichlet_tags=[],
                                      neumann_tags=[])

            diffusion_part = div_tgt.minv_all
        else:
            diffusion_part = 0

        # }}}

        to_quad = QuadratureGridUpsampler("quad")
        quad_u = cse(to_quad(u))
        quad_v = cse(to_quad(v))

        return m_inv(numpy.dot(minv_st, cse(quad_v*quad_u))
                - (flux_op(quad_face_w)
                    + flux_op(BoundaryPair(quad_face_w, bc_w, TAG_ALL)))) \
                            + diffusion_part
Esempio n. 55
0
 def grad_interior_flux(self, tgt, u):
     from hedge.optemplate.primitives import make_common_subexpression as cse
     n_times = tgt.normal_times_flux
     return n_times(cse(u.avg, "u_avg"))
Esempio n. 56
0
    def op_template(self, with_sensor=False):
        # {{{ operator preliminaries ------------------------------------------
        from hedge.optemplate import (Field, BoundaryPair, get_flux_operator,
                make_stiffness_t, InverseMassOperator, make_sym_vector,
                ElementwiseMaxOperator, BoundarizeOperator)

        from hedge.optemplate.primitives import make_common_subexpression as cse

        from hedge.optemplate.operators import (
                QuadratureGridUpsampler,
                QuadratureInteriorFacesGridUpsampler)

        to_quad = QuadratureGridUpsampler("quad")
        to_if_quad = QuadratureInteriorFacesGridUpsampler("quad")

        from hedge.tools import join_fields, \
                                ptwise_dot

        u = Field("u")
        v = make_sym_vector("v", self.dimensions)
        c = ElementwiseMaxOperator()(ptwise_dot(1, 1, v, v))

        quad_u = cse(to_quad(u))
        quad_v = cse(to_quad(v))

        w = join_fields(u, v, c)
        quad_face_w = to_if_quad(w)
        # }}}

        # {{{ boundary conditions ---------------------------------------------

        from hedge.mesh import TAG_ALL
        bc_c = to_quad(BoundarizeOperator(TAG_ALL)(c))
        bc_u = to_quad(Field("bc_u"))
        bc_v = to_quad(BoundarizeOperator(TAG_ALL)(v))

        if self.bc_u_f is "None":
            bc_w = join_fields(0, bc_v, bc_c)
        else:
            bc_w = join_fields(bc_u, bc_v, bc_c)

        minv_st = make_stiffness_t(self.dimensions)
        m_inv = InverseMassOperator()

        flux_op = get_flux_operator(self.flux())
        # }}}

        # {{{ diffusion -------------------------------------------------------
        if with_sensor or (
                self.diffusion_coeff is not None and self.diffusion_coeff != 0):
            if self.diffusion_coeff is None:
                diffusion_coeff = 0
            else:
                diffusion_coeff = self.diffusion_coeff

            if with_sensor:
                diffusion_coeff += Field("sensor")

            from hedge.second_order import SecondDerivativeTarget

            # strong_form here allows IPDG to reuse the value of grad u.
            grad_tgt = SecondDerivativeTarget(
                    self.dimensions, strong_form=True,
                    operand=u)

            self.diffusion_scheme.grad(grad_tgt, bc_getter=None,
                    dirichlet_tags=[], neumann_tags=[])

            div_tgt = SecondDerivativeTarget(
                    self.dimensions, strong_form=False,
                    operand=diffusion_coeff*grad_tgt.minv_all)

            self.diffusion_scheme.div(div_tgt,
                    bc_getter=None,
                    dirichlet_tags=[], neumann_tags=[])

            diffusion_part = div_tgt.minv_all
        else:
            diffusion_part = 0

        # }}}

        to_quad = QuadratureGridUpsampler("quad")
        quad_u = cse(to_quad(u))
        quad_v = cse(to_quad(v))

        return m_inv(numpy.dot(minv_st, cse(quad_v*quad_u))
                - (flux_op(quad_face_w)
                    + flux_op(BoundaryPair(quad_face_w, bc_w, TAG_ALL)))) \
                            + diffusion_part
Esempio n. 57
0
 def cse_rho(self, q):
     return cse(self.rho(q), "rho")