def sym_operator(self): from grudge.mesh import BTAG_ALL from grudge.symbolic import Field, BoundaryPair, \ make_nabla, InverseMassOperator, get_flux_operator u = Field("u") bc = Field("bc") nabla = make_nabla(self.dimensions) flux_op = get_flux_operator(self.flux()) return nabla * u - InverseMassOperator()( flux_op(u) + flux_op(BoundaryPair(u, bc, BTAG_ALL)))
def bind_characteristic_velocity(self, discr): from grudge.symbolic import Field compiled = discr.compile( self.characteristic_velocity_optemplate(Field("u"))) def do(u): return compiled(u=u) return do
def sym_operator(self, apply_minv, u=None, dir_bc=None, neu_bc=None): from grudge.symbolic import Field if u is None: u = Field("u") result = PoissonOperator.sym_operator(self, apply_minv, u, dir_bc, neu_bc) if apply_minv: return result + self.k**2 * u else: from grudge.symbolic import MassOperator return result + self.k**2 * MassOperator()(u)
def sym_operator(self, with_sensor): from grudge.symbolic import (Field, make_stiffness_t, make_nabla, InverseMassOperator, ElementwiseMaxOperator, get_flux_operator) from grudge.symbolic.operators import ( QuadratureGridUpsampler, QuadratureInteriorFacesGridUpsampler) to_quad = QuadratureGridUpsampler("quad") to_if_quad = QuadratureInteriorFacesGridUpsampler("quad") u = Field("u") u0 = Field("u0") # boundary conditions ------------------------------------------------- minv_st = make_stiffness_t(self.dimensions) nabla = make_nabla(self.dimensions) m_inv = InverseMassOperator() def flux(u): return u**2 / 2 #return u0*u emax_u = self.characteristic_velocity_optemplate(u) from grudge.flux.tools import make_lax_friedrichs_flux from pytools.obj_array import make_obj_array num_flux = make_lax_friedrichs_flux( #u0, to_if_quad(emax_u), make_obj_array([to_if_quad(u)]), [make_obj_array([flux(to_if_quad(u))])], [], strong=False)[0] from grudge.second_order import SecondDerivativeTarget if self.viscosity is not None or with_sensor: viscosity_coeff = 0 if with_sensor: viscosity_coeff += Field("sensor") if isinstance(self.viscosity, float): viscosity_coeff += self.viscosity elif self.viscosity is None: pass else: raise TypeError("unsupported type of viscosity coefficient") # strong_form here allows IPDG to reuse the value of grad u. grad_tgt = SecondDerivativeTarget(self.dimensions, strong_form=True, operand=u) self.viscosity_scheme.grad(grad_tgt, bc_getter=None, dirichlet_tags=[], neumann_tags=[]) div_tgt = SecondDerivativeTarget(self.dimensions, strong_form=False, operand=viscosity_coeff * grad_tgt.minv_all) self.viscosity_scheme.div(div_tgt, bc_getter=None, dirichlet_tags=[], neumann_tags=[]) viscosity_bit = div_tgt.minv_all else: viscosity_bit = 0 return m_inv((minv_st[0](flux(to_quad(u)))) - num_flux) \ + viscosity_bit
def sym_operator(self, apply_minv, u=None, dir_bc=None, neu_bc=None): """ :param apply_minv: :class:`bool` specifying whether to compute a complete divergence operator. If False, the final application of the inverse mass operator is skipped. This is used in :meth:`op` in order to reduce the scheme :math:`M^{-1} S u = f` to :math:`S u = M f`, so that the mass operator only needs to be applied once, when preparing the right hand side in :meth:`prepare_rhs`. :class:`grudge.models.diffusion.DiffusionOperator` needs this. """ from grudge.symbolic import Field, make_sym_vector from grudge.second_order import SecondDerivativeTarget if u is None: u = Field("u") if dir_bc is None: dir_bc = Field("dir_bc") if neu_bc is None: neu_bc = Field("neu_bc") # strong_form here allows IPDG to reuse the value of grad u. grad_tgt = SecondDerivativeTarget(self.dimensions, strong_form=True, operand=u) def grad_bc_getter(tag, expr): assert tag == self.dirichlet_tag return dir_bc self.scheme.grad(grad_tgt, bc_getter=grad_bc_getter, dirichlet_tags=[self.dirichlet_tag], neumann_tags=[self.neumann_tag]) def apply_diff_tensor(v): if isinstance(self.diffusion_tensor, np.ndarray): sym_diff_tensor = self.diffusion_tensor else: sym_diff_tensor = (make_sym_vector("diffusion", self.dimensions**2).reshape( self.dimensions, self.dimensions)) return np.dot(sym_diff_tensor, v) div_tgt = SecondDerivativeTarget(self.dimensions, strong_form=False, operand=apply_diff_tensor( grad_tgt.minv_all)) def div_bc_getter(tag, expr): if tag == self.dirichlet_tag: return dir_bc elif tag == self.neumann_tag: return neu_bc else: assert False, "divergence bc getter " \ "asked for '%s' BC for '%s'" % (tag, expr) self.scheme.div(div_tgt, div_bc_getter, dirichlet_tags=[self.dirichlet_tag], neumann_tags=[self.neumann_tag]) if apply_minv: return div_tgt.minv_all else: return div_tgt.all