Пример #1
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)]
Пример #2
0
def integral(arg, dd=None):
    import grudge.symbolic.primitives as prim

    if dd is None:
        dd = prim.DD_VOLUME
    dd = prim.as_dofdesc(dd)

    return NodalSum(dd)(arg * prim.cse(
        MassOperator(dd_in=dd)(prim.Ones(dd)), "mass_quad_weights",
        prim.cse_scope.DISCRETIZATION))
Пример #3
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 grudge.symbolic.primitives import make_common_subexpression as cse
        from grudge.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)
Пример #4
0
    def outflow_state(self, state):
        from grudge.symbolic import make_normal
        normal = make_normal(self.outflow_tag, self.dimensions)
        bc = self.make_bc_info("bc_q_out", self.outflow_tag, state)

        # see grudge/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"))
Пример #5
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 grudge.symbolic import RestrictToBoundary
                result = RestrictToBoundary(tag)(self.sensor())
                return cse(to_bdry_quad(result), "bdry_sensor")
Пример #6
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
Пример #7
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 grudge.symbolic import RestrictToBoundary
        bdrize_op = RestrictToBoundary(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"))
Пример #8
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)
Пример #9
0
 def grad_interior_flux(self, tgt, u):
     from grudge.symbolic.primitives import make_common_subexpression as cse
     n_times = tgt.normal_times_flux
     return n_times(cse(u.avg, "u_avg"))
Пример #10
0
 def minv_all(self):
     from grudge.symbolic.primitives import make_common_subexpression as cse
     from grudge.symbolic.operators import InverseMassOperator
     return (
         cse(InverseMassOperator()(self.local_derivatives), "grad_loc") +
         cse(InverseMassOperator()(self.fluxes), "grad_flux"))
Пример #11
0
 def volq_state(self):
     return cse(to_vol_quad(self.state()), "vol_quad_state")
Пример #12
0
    def sym_operator(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 grudge.symbolic.primitives import FunctionSymbol
        sqrt = FunctionSymbol("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 grudge.flux.tools import make_lax_friedrichs_flux
        from grudge.symbolic.operators import InverseMassOperator

        from grudge.symbolic.tools import make_stiffness_t

        primitive_bcs_as_quad_conservative = {
                tag: self.primitive_to_conservative(to_bdry_quad(bc))
                for tag, bc in
                self.get_primitive_boundary_conditions().items()}

        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
Пример #13
0
 def faceq_state(self):
     return cse(to_int_face_quad(self.state()), "face_quad_state")
Пример #14
0
 def cse_u(self, q):
     return cse(self.u(q), "u")
Пример #15
0
 def cse_rho(self, q):
     return cse(self.rho(q), "rho")
Пример #16
0
 def cse_temperature(self, q):
     return cse(self.temperature(q), "temperature")
Пример #17
0
 def cse_p(self, q):
     return cse(self.p(q), "p")
Пример #18
0
 def cse_rho_u(self, q):
     return cse(self.rho_u(q), "rho_u")