def characteristic_velocity_optemplate(self, state): from grudge.symbolic.operators import ElementwiseMaxOperator from grudge.symbolic.primitives import FunctionSymbol sqrt = FunctionSymbol("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)
def __init__(self, queue, discr, field_var_name, grudge_bound_op, num_fields, component_getter, exec_mapper_factory=ExecutionMapper): """Arguments: field_var_name: The name of the simulation variable grudge_bound_op: The BoundExpression for the right-hand side num_fields: The number of components in the simulation variable component_getter: A function, which, given an object array representing the simulation variable, splits the array into its components """ super().__init__(queue, component_getter) # Construct sym_rhs to have the effect of replacing the RHS calls in the # dagrt code with calls of the grudge operator. from grudge.symbolic.primitives import FunctionSymbol, Variable call = sym.cse( FunctionSymbol("grudge_op")( *((Variable("t", dd=sym.DD_SCALAR), ) + tuple( Variable(field_var_name, dd=sym.DD_VOLUME)[i] for i in range(num_fields))))) from pytools.obj_array import join_fields sym_rhs = join_fields(*(call[i] for i in range(num_fields))) self.queue = queue self.grudge_bound_op = grudge_bound_op from grudge.function_registry import register_external_function freg = register_external_function(base_function_registry, "grudge_op", implementation=self._bound_op, dd=sym.DD_VOLUME) self.set_up_stepper(discr, field_var_name, sym_rhs, num_fields, freg, exec_mapper_factory) self.component_getter = component_getter
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