Beispiel #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.tools.symbolic 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
Beispiel #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")
Beispiel #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)
Beispiel #4
0
    def collision_update(self, f_bar):
        from hedge.tools.symbolic 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)
Beispiel #5
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)
Beispiel #6
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))
Beispiel #7
0
    def primitive_to_conservative(self, prims, use_cses=True):
        if not use_cses:
            from hedge.tools.symbolic 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"))
Beispiel #8
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.tools.symbolic 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))
            ])
Beispiel #9
0
    def grad_interior_flux(self, tgt, u):
        from hedge.tools.symbolic 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)))
Beispiel #10
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_vector_field(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"))
Beispiel #11
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)]
Beispiel #12
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.tools.symbolic import make_common_subexpression as cse
        from hedge.flux import FluxVectorPlaceholder, make_normal, PenaltyTerm
        normal = make_normal(tgt.dimensions)

        n_times = tgt.normal_times_flux
        v_times = tgt.vec_times

        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)
Beispiel #13
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"))
Beispiel #14
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")
Beispiel #15
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
Beispiel #16
0
    def absorbing_bc(self, w=None):
        """Construct part of the flux operator template for 1st order
        absorbing boundary conditions.
        """

        from hedge.optemplate import make_normal
        absorb_normal = make_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
Beispiel #17
0
    def op_template(self, u=None):
        from pymbolic.primitives import IfPositive, Variable
        from hedge.optemplate.primitives import Field, ScalarParameter
        from hedge.tools.symbolic 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))))
Beispiel #18
0
    def dirichlet_bc(self, w=None):
        """
        Flux term for dirichlet (displacement) boundary conditions
        """
        u, v = self.split_vars(self.field_placeholder(w))

        if self.dirichlet_bc_data is not None:
            from hedge.optemplate import make_vector_field
            dir_field = cse(
                    -make_vector_field("dirichlet_bc", 3))
        else:
            dir_field = make_obj_array([0,]*3)
        
        from hedge.tools import join_fields
        return join_fields(dir_field, [0]*3, [0,]*9)
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
    from math import sqrt, pi, cos, sin

    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))
    # ones = discr.interpolate_volume_function(lambda x, el: 1)
    int_proj = discr._integral_projection()

    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.tools.symbolic 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(int_proj, mass_op(f=f_vec))
    num_integral_2 = numpy.dot(int_proj, 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
Beispiel #20
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
        from hedge.tools import join_fields
        fld_cnt = count_subset(self.get_eh_subset())

        if self.incident_bc_data is not None:
            from hedge.optemplate import make_vector_field
            inc_field = cse(
                   -make_vector_field("incident_bc", fld_cnt))
        else:
            inc_field = make_obj_array([0]*fld_cnt)

        return inc_field
Beispiel #21
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)
Beispiel #22
0
 def cse_temperature(self, q):
     return cse(self.temperature(q), "temperature")
Beispiel #23
0
 def faceq_state(self):
     return cse(to_int_face_quad(self.state()), "face_quad_state")
Beispiel #24
0
 def volq_state(self):
     return cse(to_vol_quad(self.state()), "vol_quad_state")
Beispiel #25
0
 def cse_rho_u(self, q):
     return cse(self.rho_u(q), "rho_u")
Beispiel #26
0
 def cse_p(self, q):
     return cse(self.p(q), "p")
Beispiel #27
0
 def cse_u(self, q):
     return cse(self.u(q), "u")
Beispiel #28
0
    def op_template(self, with_sensor=False):
        # {{{ operator preliminaries ------------------------------------------
        from hedge.optemplate import (Field, BoundaryPair, get_flux_operator,
                make_stiffness_t, InverseMassOperator, make_vector_field, 
                ElementwiseMaxOperator, BoundarizeOperator)

        from hedge.tools.symbolic 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_vector_field("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
Beispiel #29
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_vector_field("source_vect", len(self.state())),
                    # extra field for speed
                    0)

        return result
Beispiel #30
0
 def cse_rho(self, q):
     return cse(self.rho(q), "rho")