diff --git a/examples/dagrt-fusion.py b/examples/dagrt-fusion.py index cb51964f6442192ed30ea953fe1dc1be2720bdab..bd399c3a38542280f49cb66b00d6979541085a31 100755 --- a/examples/dagrt-fusion.py +++ b/examples/dagrt-fusion.py @@ -523,7 +523,7 @@ def test_stepper_equivalence(ctx_factory, order=4): fused_steps = fused_stepper.run(ic, t_start, dt, t_end) - for t_ref, (u_ref, v_ref) in stepper.run(ic, t_start, dt, t_end): + for t_ref, (u_ref, _v_ref) in stepper.run(ic, t_start, dt, t_end): step += 1 logger.debug("step %d/%d", step, nsteps) t, (u, v) = next(fused_steps) @@ -620,7 +620,7 @@ class ExecutionMapperWithMemOpCounting(ExecutionMapperWrapper): expr.op, expr.field, profile_data) else: - assert False, ("unknown operator: %s" % expr.op) + raise AssertionError("unknown operator: %s" % expr.op) else: logger.debug("assignment not profiled: %s", expr) @@ -811,7 +811,7 @@ def test_stepper_mem_ops(ctx_factory, use_fusion): step = 0 nsteps = int(np.ceil((t_end + 1e-9) / dt)) - for (_, _, profile_data) in stepper.run( + for (_, _, profile_data) in stepper.run( # noqa: B007 ic, t_start, dt, t_end, return_profile_data=True): step += 1 logger.info("step %d/%d", step, nsteps) @@ -984,7 +984,7 @@ def test_stepper_timing(ctx_factory, use_fusion): import time t = time.time() nsteps = int(np.ceil((t_end + 1e-9) / dt)) - for (_, _, profile_data) in stepper.run( + for (_, _, profile_data) in stepper.run( # noqa: B007 ic, t_start, dt, t_end, return_profile_data=True): step += 1 tn = time.time() @@ -1146,7 +1146,7 @@ def mem_ops_results(actx, dims): result = {} - for (_, _, profile_data) in stepper.run( + for (_, _, profile_data) in stepper.run( # noqa: B007 ic, t_start, dt, t_end, return_profile_data=True): pass @@ -1164,7 +1164,7 @@ def mem_ops_results(actx, dims): result["nonfused_bytes_read_by_scalar_assignments"] \ + result["nonfused_bytes_written_by_scalar_assignments"] - for (_, _, profile_data) in fused_stepper.run( + for (_, _, profile_data) in fused_stepper.run( # noqa: B007 ic, t_start, dt, t_end, return_profile_data=True): pass diff --git a/grudge/execution.py b/grudge/execution.py index 44721932737712758606ee455649c42e7c800f35..4b86fcb9e359c828a99f8f6d94a4714a999cd705 100644 --- a/grudge/execution.py +++ b/grudge/execution.py @@ -628,7 +628,7 @@ class BoundOperator: else: pass - for key, val in context.items(): + for val in context.values(): look_for_array_contexts(val) if array_contexts: diff --git a/grudge/models/em.py b/grudge/models/em.py index 244d324e0749ef48d19a67af9ab0be5c3156aa0c..3f4bc13d42a017fcee36ba7b05237c512ca11451 100644 --- a/grudge/models/em.py +++ b/grudge/models/em.py @@ -327,7 +327,9 @@ class MaxwellOperator(HyperbolicOperator): 1 / sym.sqrt(self.epsilon * self.mu) ) - def max_eigenvalue(self, t, fields=None, discr=None, context={}): + def max_eigenvalue(self, t, fields=None, discr=None, context=None): + if context is None: + context = {} if self.fixed_material: return self.max_eigenvalue_expr() else: diff --git a/grudge/models/poisson.py b/grudge/models/poisson.py deleted file mode 100644 index 6636b94fe4d7ea90894bf92a86d30189fe93348e..0000000000000000000000000000000000000000 --- a/grudge/models/poisson.py +++ /dev/null @@ -1,261 +0,0 @@ -"""Operators for Poisson problems.""" - -__copyright__ = "Copyright (C) 2007 Andreas Kloeckner" - -__license__ = """ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import numpy as np - -from grudge.models import Operator -from grudge.second_order import LDGSecondDerivative -import grudge.data -import grudge.iterative - - -class LaplacianOperatorBase: - 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 - - -class PoissonOperator(Operator, LaplacianOperatorBase): - """Implements the Local Discontinuous Galerkin (LDG) Method for elliptic - operators. - - See P. Castillo et al., - Local discontinuous Galerkin methods for elliptic problems", - Communications in Numerical Methods in Engineering 18, no. 1 (2002): 69-75. - """ - - def __init__(self, dimensions, diffusion_tensor=None, - dirichlet_bc=grudge.data.ConstantGivenFunction(), - dirichlet_tag="dirichlet", - neumann_bc=grudge.data.ConstantGivenFunction(), - neumann_tag="neumann", - scheme=LDGSecondDerivative()): - self.dimensions = dimensions - - self.scheme = scheme - - self.dirichlet_bc = dirichlet_bc - self.dirichlet_tag = dirichlet_tag - self.neumann_bc = neumann_bc - self.neumann_tag = neumann_tag - - if diffusion_tensor is None: - diffusion_tensor = np.eye(dimensions) - self.diffusion_tensor = diffusion_tensor - - # bound operator ---------------------------------------------------------- - def bind(self, discr): - """Return a :class:`BoundPoissonOperator`.""" - - assert self.dimensions == discr.dimensions - - from grudge.mesh import check_bc_coverage - check_bc_coverage(discr.mesh, [self.dirichlet_tag, self.neumann_tag]) - - return BoundPoissonOperator(self, discr) - - -class BoundPoissonOperator(grudge.iterative.OperatorBase): - """Returned by :meth:`PoissonOperator.bind`.""" - - def __init__(self, poisson_op, discr): - grudge.iterative.OperatorBase.__init__(self) - self.discr = discr - - pop = self.poisson_op = poisson_op - - op = pop.sym_operator( - apply_minv=False, dir_bc=0, neu_bc=0) - bc_op = pop.sym_operator(apply_minv=False) - - self.compiled_op = discr.compile(op) - self.compiled_bc_op = discr.compile(bc_op) - - if not isinstance(pop.diffusion_tensor, np.ndarray): - self.diffusion = pop.diffusion_tensor.volume_interpolant(discr) - - # Check whether use of Poincaré mean-value method is required. - # (for pure Neumann or pure periodic) - - from grudge.mesh import BTAG_ALL - self.poincare_mean_value_hack = ( - len(self.discr.get_boundary(BTAG_ALL).nodes) - == len(self.discr.get_boundary(poisson_op.neumann_tag).nodes)) - - @property - def dtype(self): - return self.discr.default_scalar_type - - @property - def shape(self): - nodes = len(self.discr) - return nodes, nodes - - def op(self, u): - context = {"u": u} - if not isinstance(self.poisson_op.diffusion_tensor, np.ndarray): - context["diffusion"] = self.diffusion - - result = self.compiled_op(**context) - - if self.poincare_mean_value_hack: - state_int = self.discr.integral(u) - mean_state = state_int / self.discr.mesh_volume() - return result - mean_state * self.discr._mass_ones() - else: - return result - - __call__ = op - - def prepare_rhs(self, rhs): - """Prepare the right-hand side for the linear system op(u)=rhs(f). - - In matrix form, LDG looks like this: - - .. math:: - Mv = Cu + g - Mf = Av + Bu + h - - where v is the auxiliary vector, u is the argument of the operator, f - is the result of the grad operator, g and h are inhom boundary data, and - A,B,C are some operator+lifting matrices. - - .. math:: - - M f = A M^{-1}(Cu + g) + Bu + h - - so the linear system looks like - - .. math:: - - M f = A M^{-1} Cu + A M^{-1} g + Bu + h - M f - A M^{-1} g - h = (A M^{-1} C + B)u (*) - - So the right hand side we're putting together here is really - - .. math:: - - M f - A M^{-1} g - h - - .. note:: - - Resist the temptation to left-multiply by the inverse - mass matrix, as this will result in a non-symmetric - matrix, which (e.g.) a conjugate gradient Krylov - solver will not take well. - """ - pop = self.poisson_op - - from grudge.symbolic import MassOperator - return (MassOperator().apply(self.discr, rhs) - - self.compiled_bc_op( - u=self.discr.volume_zeros(), - dir_bc=pop.dirichlet_bc.boundary_interpolant( - self.discr, pop.dirichlet_tag), - neu_bc=pop.neumann_bc.boundary_interpolant( - self.discr, pop.neumann_tag))) - - -class HelmholtzOperator(PoissonOperator): - def __init__(self, k, *args, **kwargs): - PoissonOperator.__init__(self, *args, **kwargs) - self.k = k - - 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) diff --git a/grudge/models/second_order.py b/grudge/models/second_order.py deleted file mode 100644 index 8f7251d329ea1cbbb960e368fe3c272f481ca36a..0000000000000000000000000000000000000000 --- a/grudge/models/second_order.py +++ /dev/null @@ -1,505 +0,0 @@ -"""Schemes for second-order derivatives.""" - -__copyright__ = "Copyright (C) 2009 Andreas Kloeckner" - -__license__ = """ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import numpy as np -import grudge.symbolic.mappers as mappers -from grudge import sym - - -# {{{ stabilization term generator - -class StabilizationTermGenerator(mappers.IdentityMapper): - def __init__(self, flux_args): - super().__init__() - self.flux_args = flux_args - self.flux_arg_lookup = { - flux_arg: i for i, flux_arg in enumerate(flux_args)} - - def get_flux_arg_idx(self, expr, quad_above): - from grudge.symbolic.mappers import QuadratureDetector - - quad_below = QuadratureDetector()(expr) - if quad_above: - if quad_below is not None: - # Both the part of the expression above and below the - # differentiation operator had quadrature upsamplers in it. - # Since we're removing the differentiation operator, there are - # now two layers of quadrature operators. We need to change the - # inner layer to be the only layer. - - from grudge.symbolic.mappers import QuadratureUpsamplerChanger - expr = QuadratureUpsamplerChanger(quad_above[0])(expr) - else: - # Only the part of the expression above the differentiation - # operator had quadrature. Insert quadrature here, be done. - expr = quad_above[0](expr) - else: - if quad_below is not None: - # Only the part of the expression below the differentiation - # operator had quadrature--the stuff above doesn't want it. - # Get rid of it. - from grudge.symbolic.mappers import QuadratureUpsamplerRemover - expr = QuadratureUpsamplerRemover({}, do_warn=False)(expr) - else: - # No quadrature, no headaches. - pass - - try: - return self.flux_arg_lookup[expr] - except KeyError: - flux_arg_idx = len(self.flux_args) - self.flux_arg_lookup[expr] = flux_arg_idx - self.flux_args.append(expr) - return flux_arg_idx - - def map_operator_binding(self, expr, quad_above=[]): - from grudge.symbolic.operators import ( - DiffOperatorBase, FluxOperatorBase, - InverseMassOperator, - QuadratureInteriorFacesGridUpsampler) - - if isinstance(expr.op, DiffOperatorBase): - flux_arg_idx = self.get_flux_arg_idx(expr.field, quad_above=quad_above) - - from grudge.symbolic import \ - WeakFormDiffOperatorBase, \ - StrongFormDiffOperatorBase - if isinstance(expr.op, WeakFormDiffOperatorBase): - factor = -1 - elif isinstance(expr.op, StrongFormDiffOperatorBase): - factor = 1 - else: - raise RuntimeError("unknown type of differentiation " - "operator encountered by stab term generator") - - from grudge.flux import Normal, FluxScalarPlaceholder - sph = FluxScalarPlaceholder(flux_arg_idx) - return (factor - * Normal(expr.op.xyz_axis) - * (sph.int - sph.ext)) - - elif isinstance(expr.op, FluxOperatorBase): - return 0 - elif isinstance(expr.op, InverseMassOperator): - return self.rec(expr.field, quad_above) - elif isinstance(expr.op, QuadratureInteriorFacesGridUpsampler): - if quad_above: - raise RuntimeError("double quadrature upsampler found " - "when generating stabilization term") - return self.rec(expr.field, [expr.op]) - else: - from grudge.symbolic.tools import pretty - raise ValueError("stabilization term generator doesn't know " - "what to do with '%s'" % pretty(expr)) - - def map_variable(self, expr, quad_above=[]): - from grudge.flux import FieldComponent - return FieldComponent( - self.get_flux_arg_idx(expr, quad_above), - is_interior=True) - - def map_subscript(self, expr, quad_above=[]): - from pymbolic.primitives import Variable - assert isinstance(expr.aggregate, Variable) - from grudge.flux import FieldComponent - return FieldComponent( - self.get_flux_arg_idx(expr, quad_above), - is_interior=True) - -# }}} - - -# {{{ neumann bc generator - -class NeumannBCGenerator(mappers.IdentityMapper): - def __init__(self, tag, bc): - super().__init__() - self.tag = tag - self.bc = bc - - def map_operator_binding(self, expr): - if isinstance(expr.op, sym.DiffOperatorBase): - from grudge.symbolic import \ - WeakFormDiffOperatorBase, \ - StrongFormDiffOperatorBase - if isinstance(expr.op, WeakFormDiffOperatorBase): - factor = -1 - elif isinstance(expr.op, StrongFormDiffOperatorBase): - factor = 1 - else: - raise RuntimeError("unknown type of differentiation " - "operator encountered by stab term generator") - - from grudge.symbolic import BoundaryNormalComponent - return (self.bc * factor - * BoundaryNormalComponent(self.tag, expr.op.xyz_axis)) - - elif isinstance(expr.op, sym.FluxOperatorBase): - return 0 - elif isinstance(expr.op, sym.InverseMassOperator): - return self.rec(expr.field) - else: - raise ValueError("neumann normal direction generator doesn't know " - "what to do with '%s'" % expr) - -# }}} - - -class IPDGDerivativeGenerator(mappers.IdentityMapper): - def map_operator_binding(self, expr): - if isinstance(expr.op, sym.DiffOperatorBase): - from grudge.symbolic import ( - WeakFormDiffOperatorBase, - StrongFormDiffOperatorBase) - - if isinstance(expr.op, WeakFormDiffOperatorBase): - factor = -1 - elif isinstance(expr.op, StrongFormDiffOperatorBase): - factor = 1 - else: - raise RuntimeError("unknown type of differentiation " - "operator encountered by stab term generator") - - from grudge.symbolic import DifferentiationOperator - return factor*DifferentiationOperator(expr.op.xyz_axis)(expr.field) - - elif isinstance(expr.op, sym.FluxOperatorBase): - return 0 - elif isinstance(expr.op, sym.InverseMassOperator): - return self.rec(expr.field) - elif isinstance(expr.op, - sym.QuadratureInteriorFacesGridUpsampler): - return super().map_operator_binding(expr) - else: - from grudge.symbolic.tools import pretty - raise ValueError("IPDG derivative generator doesn't know " - "what to do with '%s'" % pretty(expr)) - - -# {{{ second derivative target - -class SecondDerivativeTarget: - def __init__(self, dimensions, strong_form, operand, - int_flux_operand=None, - bdry_flux_int_operand=None): - """ - :param int_flux_operand: if not None, is used as the interior - argument to the interior fluxes. This is useful e.g. if the boundary - values are on a quadrature grid--in this case, *bdry_flux_int_operand* - can be passed to also be on a boundary grid. If it is None, it defaults - to *operand*. - - :param bdry_flux_int_operand: if not None, is used as the interior - argument to the boundary fluxes. This is useful e.g. if the boundary - values are on a quadrature grid--in this case, *bdry_flux_int_operand* - can be passed to also be on a boundary grid. If it is None, it defaults - to *int_flux_operand*. - """ - self.dimensions = dimensions - self.operand = operand - - if int_flux_operand is None: - int_flux_operand = operand - if bdry_flux_int_operand is None: - bdry_flux_int_operand = int_flux_operand - - self.int_flux_operand = int_flux_operand - self.bdry_flux_int_operand = bdry_flux_int_operand - - self.strong_form = strong_form - if strong_form: - self.strong_neg = -1 - else: - self.strong_neg = 1 - - self.local_derivatives = 0 - self.inner_fluxes = 0 - self.boundary_fluxes = 0 - - def add_local_derivatives(self, expr): - self.local_derivatives = self.local_derivatives \ - + (-self.strong_neg)*expr - - def vec_times(self, vec, operand): - from pytools.obj_array import is_obj_array - - if is_obj_array(operand): - if len(operand) != self.dimensions: - raise ValueError("operand of vec_times must have %d dimensions" - % self.dimensions) - - return np.dot(vec, operand) - else: - return vec*operand - - def normal_times_flux(self, flux): - from grudge.flux import make_normal - return self.vec_times(make_normal(self.dimensions), flux) - - def apply_diff(self, nabla, operand): - from pytools.obj_array import make_obj_array, is_obj_array - if is_obj_array(operand): - if len(operand) != self.dimensions: - raise ValueError("operand of apply_diff must have %d dimensions" - % self.dimensions) - - return sum(nabla[i](operand[i]) for i in range(self.dimensions)) - else: - return make_obj_array( - [nabla[i](operand) for i in range(self.dimensions)]) - - def _local_nabla(self): - if self.strong_form: - from grudge.symbolic import make_stiffness - return make_stiffness(self.dimensions) - else: - from grudge.symbolic import make_stiffness_t - return make_stiffness_t(self.dimensions) - - def add_derivative(self, operand=None): - if operand is None: - operand = self.operand - - self.add_local_derivatives( - self.apply_diff(self._local_nabla(), operand)) - - def add_inner_fluxes(self, flux, expr): - from grudge.symbolic import get_flux_operator - self.inner_fluxes = self.inner_fluxes \ - + get_flux_operator(self.strong_neg*flux)(expr) - - def add_boundary_flux(self, flux, volume_expr, bdry_expr, tag): - from grudge.symbolic import BoundaryPair, get_flux_operator - self.boundary_fluxes = self.boundary_fluxes + \ - get_flux_operator(self.strong_neg*flux)(BoundaryPair( - volume_expr, bdry_expr, tag)) - - @property - def fluxes(self): - return self.inner_fluxes + self.boundary_fluxes - - @property - def all(self): - return self.local_derivatives + self.fluxes - - @property - 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")) - -# }}} - - -# {{{ second derivative schemes - -class SecondDerivativeBase: - def grad(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. - """ - n_times = tgt.normal_times_flux - - if tgt.strong_form: - def adjust_flux(f): - return n_times(u.int) - f - else: - def adjust_flux(f): - return f - - from grudge.flux import FluxScalarPlaceholder - u = FluxScalarPlaceholder() - - tgt.add_derivative() - tgt.add_inner_fluxes( - adjust_flux(self.grad_interior_flux(tgt, u)), - tgt.int_flux_operand) - - for tag in dirichlet_tags: - tgt.add_boundary_flux( - adjust_flux(n_times(u.ext)), - tgt.bdry_flux_int_operand, bc_getter(tag, tgt.operand), tag) - - for tag in neumann_tags: - tgt.add_boundary_flux( - adjust_flux(n_times(u.int)), - tgt.bdry_flux_int_operand, 0, tag) - - def add_div_bcs(self, tgt, bc_getter, dirichlet_tags, neumann_tags, - stab_term, adjust_flux, flux_v, flux_arg_int, - grad_flux_arg_count): - from pytools.obj_array import make_obj_array, join_fields - n_times = tgt.normal_times_flux - - def unwrap_cse(expr): - from pymbolic.primitives import CommonSubexpression - if isinstance(expr, CommonSubexpression): - return expr.child - else: - return expr - - for tag in dirichlet_tags: - dir_bc_w = join_fields( - [0]*grad_flux_arg_count, - [bc_getter(tag, unwrap_cse(vol_expr)) for vol_expr in - flux_arg_int[grad_flux_arg_count:]]) - tgt.add_boundary_flux( - adjust_flux(n_times(flux_v.int-stab_term)), - flux_arg_int, dir_bc_w, tag) - - loc_bc_vec = make_obj_array([0]*len(flux_arg_int)) - - for tag in neumann_tags: - neu_bc_w = join_fields( - NeumannBCGenerator(tag, bc_getter(tag, None))(tgt.operand), - [0]*len(flux_arg_int)) - - tgt.add_boundary_flux( - adjust_flux(n_times(flux_v.ext)), - loc_bc_vec, neu_bc_w, tag) - - -class LDGSecondDerivative(SecondDerivativeBase): - def __init__(self, beta_value=0.5, stab_coefficient=1): - self.beta_value = beta_value - self.stab_coefficient = stab_coefficient - - def beta(self, tgt): - return np.array([self.beta_value]*tgt.dimensions, dtype=np.float64) - - def grad_interior_flux(self, tgt, u): - from grudge.symbolic.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))) - - 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 - 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 - - flux_v = FluxVectorPlaceholder(tgt.dimensions) - - stab_term_generator = StabilizationTermGenerator( - list(tgt.int_flux_operand)) - stab_term = (self.stab_coefficient * PenaltyTerm() - * stab_term_generator(tgt.int_flux_operand)) - - flux = n_times(flux_v.avg - + v_times(self.beta(tgt), - cse(n_times(flux_v.int - flux_v.ext), "jump_v")) - - 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, tgt.dimensions) - - -class StabilizedCentralSecondDerivative(LDGSecondDerivative): - def __init__(self, stab_coefficient=1): - LDGSecondDerivative.__init__(self, 0, stab_coefficient=stab_coefficient) - - -class CentralSecondDerivative(LDGSecondDerivative): - def __init__(self): - LDGSecondDerivative.__init__(self, 0, 0) - - -class IPDGSecondDerivative(SecondDerivativeBase): - def __init__(self, stab_coefficient=1): - self.stab_coefficient = stab_coefficient - - 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")) - - 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) - -# }}} - -# vim: fdm=marker diff --git a/grudge/symbolic/compiler.py b/grudge/symbolic/compiler.py index 742483aed9e02264c5ac65cfb40ee8ef0dbb8ee5..f5f7c66499b2adeadc470b9be416a06d5074048a 100644 --- a/grudge/symbolic/compiler.py +++ b/grudge/symbolic/compiler.py @@ -796,7 +796,7 @@ def aggregate_assignments(inf_mapper, instructions, result, schedulable.sort() if schedulable: - for key, name, expr in schedulable: + for _key, name, expr in schedulable: ordered_names_exprs.append((name, expr)) available_names.add(name) else: diff --git a/setup.cfg b/setup.cfg index e8791cc48f86a67e726046a2f7510f32a39a98a5..38dcd9de2c01e21191ca1612388f36ecbc251b70 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,11 +9,12 @@ exclude= grudge/models/nd_calculus.py, grudge/dt_finding.py - inline-quotes = " docstring-quotes = """ multiline-quotes = """ +# enable-flake8-bugbear + [mypy] ignore_missing_imports = True