def __init__(self, epsilon, mu, flux_type, bdry_flux_type=None, pec_tag=BTAG_ALL, pmc_tag=BTAG_NONE, absorb_tag=BTAG_NONE, incident_tag=BTAG_NONE, incident_bc=lambda maxwell_op, e, h: 0, current=0, dimensions=None): """ :arg flux_type: can be in [0,1] for anything between central and upwind, or "lf" for Lax-Friedrichs :arg epsilon: can be a number, for fixed material throughout the computation domain, or a TimeConstantGivenFunction for spatially variable material coefficients :arg mu: can be a number, for fixed material throughout the computation domain, or a TimeConstantGivenFunction for spatially variable material coefficients :arg incident_bc_getter: a function of signature *(maxwell_op, e, h)* that accepts *e* and *h* as a symbolic object arrays returns a symbolic expression for the incident boundary condition """ self.dimensions = dimensions or self._default_dimensions space_subset = [True]*self.dimensions + [False]*(3-self.dimensions) e_subset = self.get_eh_subset()[0:3] h_subset = self.get_eh_subset()[3:6] from grudge.tools import SubsettableCrossProduct self.space_cross_e = SubsettableCrossProduct( op1_subset=space_subset, op2_subset=e_subset, result_subset=h_subset) self.space_cross_h = SubsettableCrossProduct( op1_subset=space_subset, op2_subset=h_subset, result_subset=e_subset) self.epsilon = epsilon self.mu = mu from pymbolic.primitives import is_constant self.fixed_material = is_constant(epsilon) and is_constant(mu) self.flux_type = flux_type if bdry_flux_type is None: self.bdry_flux_type = flux_type else: self.bdry_flux_type = bdry_flux_type self.pec_tag = pec_tag self.pmc_tag = pmc_tag self.absorb_tag = absorb_tag self.incident_tag = incident_tag self.current = current self.incident_bc_data = incident_bc
def __init__(self, epsilon, mu, flux_type, bdry_flux_type=None, pec_tag=hedge.mesh.TAG_ALL, pmc_tag=hedge.mesh.TAG_NONE, absorb_tag=hedge.mesh.TAG_NONE, incident_tag=hedge.mesh.TAG_NONE, incident_bc=lambda maxwell_op, e, h: 0, current=0, dimensions=None): """ :arg flux_type: can be in [0,1] for anything between central and upwind, or "lf" for Lax-Friedrichs :arg epsilon: can be a number, for fixed material throughout the computation domain, or a TimeConstantGivenFunction for spatially variable material coefficients :arg mu: can be a number, for fixed material throughout the computation domain, or a TimeConstantGivenFunction for spatially variable material coefficients :arg incident_bc_getter: a function of signature *(maxwell_op, e, h)* that accepts *e* and *h* as a symbolic object arrays returns a symbolic expression for the incident boundary condition """ self.dimensions = dimensions or self._default_dimensions space_subset = [True]*self.dimensions + [False]*(3-self.dimensions) e_subset = self.get_eh_subset()[0:3] h_subset = self.get_eh_subset()[3:6] from hedge.tools import SubsettableCrossProduct self.space_cross_e = SubsettableCrossProduct( op1_subset=space_subset, op2_subset=e_subset, result_subset=h_subset) self.space_cross_h = SubsettableCrossProduct( op1_subset=space_subset, op2_subset=h_subset, result_subset=e_subset) self.epsilon = epsilon self.mu = mu from pymbolic.primitives import is_constant self.fixed_material = is_constant(epsilon) and is_constant(mu) self.flux_type = flux_type if bdry_flux_type is None: self.bdry_flux_type = flux_type else: self.bdry_flux_type = bdry_flux_type self.pec_tag = pec_tag self.pmc_tag = pmc_tag self.absorb_tag = absorb_tag self.incident_tag = incident_tag self.current = current self.incident_bc_data = incident_bc
def __init__(self, epsilon, mu, flux_type, bdry_flux_type=None, pec_tag=hedge.mesh.TAG_ALL, pmc_tag=hedge.mesh.TAG_NONE, absorb_tag=hedge.mesh.TAG_NONE, incident_tag=hedge.mesh.TAG_NONE, incident_bc=None, current=None, dimensions=None): """ :param flux_type: can be in [0,1] for anything between central and upwind, or "lf" for Lax-Friedrichs :param epsilon: can be a number, for fixed material throughout the computation domain, or a TimeConstantGivenFunction for spatially variable material coefficients :param mu: can be a number, for fixed material throughout the computation domain, or a TimeConstantGivenFunction for spatially variable material coefficients """ self.dimensions = dimensions or self._default_dimensions space_subset = [True]*self.dimensions + [False]*(3-self.dimensions) e_subset = self.get_eh_subset()[0:3] h_subset = self.get_eh_subset()[3:6] from hedge.tools import SubsettableCrossProduct self.space_cross_e = SubsettableCrossProduct( op1_subset=space_subset, op2_subset=e_subset, result_subset=h_subset) self.space_cross_h = SubsettableCrossProduct( op1_subset=space_subset, op2_subset=h_subset, result_subset=e_subset) self.epsilon = epsilon self.mu = mu from pymbolic.primitives import is_constant self.fixed_material = is_constant(epsilon) if self.fixed_material != is_constant(mu): raise RuntimeError("mu and epsilon must both be " "either hedge.data quantities or constants") self.flux_type = flux_type if bdry_flux_type is None: self.bdry_flux_type = flux_type else: self.bdry_flux_type = bdry_flux_type self.pec_tag = pec_tag self.pmc_tag = pmc_tag self.absorb_tag = absorb_tag self.incident_tag = incident_tag self.current = current self.incident_bc_data = incident_bc
def is_assignment_nontrivial(name, value): if prim.is_constant(value): return False elif isinstance(value, prim.Variable): return False elif (isinstance(value, prim.Product) and len(value.children) == 2 and sum(1 for arg in value.children if prim.is_constant(arg)) == 1 and sum(1 for arg in value.children if isinstance(arg, prim.Variable)) == 1): # const*var: not good enough return False return True
def map_power(self, expr, type_context): tgt_dtype = self.infer_type(expr) exponent_dtype = self.infer_type(expr.exponent) from pymbolic.primitives import is_constant, is_zero if is_constant(expr.exponent): if is_zero(expr.exponent): return 1 elif is_zero(expr.exponent - 1): return self.rec(expr.base, type_context) elif is_zero(expr.exponent - 2): return self.rec(expr.base * expr.base, type_context) if exponent_dtype.is_integral(): from loopy.codegen import SeenFunction func_name = ( "loopy_pow_" f"{tgt_dtype.numpy_dtype}_{exponent_dtype.numpy_dtype}") self.codegen_state.seen_functions.add( SeenFunction("int_pow", func_name, (tgt_dtype, exponent_dtype), (tgt_dtype, ))) return var(func_name)(self.rec(expr.base, type_context), self.rec(expr.exponent, type_context)) else: return self.rec(var("pow")(expr.base, expr.exponent), type_context)
def pick_off_constants(expr): """ :return: a tuple ``(constant, non_constant)`` that contains separates out nodes constant multipliers from any other nodes in *expr* """ if isinstance(expr, pp.Product): constants = [] non_constants = [] for child in expr.children: if isinstance(child, pp.Product): sub_const, sub_expr = pick_off_constants(child) constants.append(sub_const) non_constants.append(sub_expr) elif pp.is_constant(child) or isinstance(child, p.Parameter): constants.append(child) else: non_constants.append(child) return (pp.flattened_product(constants), pp.flattened_product(non_constants)) else: return 1, expr
def simplify_typed_literal(expr): if (isinstance(expr, p.Product) and len(expr.children) == 2 and isinstance(expr.children[1], TypedLiteral) and p.is_constant(expr.children[0]) and expr.children[0] == -1): tl = expr.children[1] return TypedLiteral("-" + tl.value, tl.dtype) else: return expr
def map_expression(self, expr): from pymbolic.primitives import is_constant if isinstance(expr, CExpression) or is_constant(expr): return expr elif isinstance(expr, str): return expr else: raise LoopyError("Unexpected expression type: %s" % type(expr).__name__)
def map_expression(self, expr): from pymbolic.primitives import is_constant if isinstance(expr, CExpression) or is_constant(expr): return expr elif isinstance(expr, str): return expr else: raise LoopyError( "Unexpected expression type: %s" % type(expr).__name__)
def project_one(subexpr): from pymbolic.primitives import is_constant if self.dd_in == self.dd_out: # no-op projection, go away return subexpr elif is_constant(subexpr): return subexpr else: from grudge.symbolic.primitives import OperatorBinding return OperatorBinding(self, subexpr)
def simplify_typed_literal(expr): if (isinstance(expr, p.Product) and len(expr.children) == 2 and isinstance(expr.children[1], TypedLiteral) and p.is_constant(expr.children[0]) and expr.children[0] == -1): tl = expr.children[1] return TypedLiteral("-"+tl.value, tl.dtype) else: return expr
def base_impl(expr, type_context): from pymbolic.primitives import is_constant, is_zero if is_constant(expr.exponent): if is_zero(expr.exponent): return 1 elif is_zero(expr.exponent - 1): return self.rec(expr.base, type_context) elif is_zero(expr.exponent - 2): return self.rec(expr.base * expr.base, type_context) return type(expr)(self.rec(expr.base, type_context), self.rec(expr.exponent, type_context))
def map_power(self, expr, enclosing_prec): from pymbolic.mapper.stringifier import PREC_NONE from pymbolic.primitives import is_constant, is_zero if is_constant(expr.exponent): if is_zero(expr.exponent): return "1" elif is_zero(expr.exponent - 1): return self.rec(expr.base, enclosing_prec) elif is_zero(expr.exponent - 2): return self.rec(expr.base * expr.base, enclosing_prec) return self.format("pow(%s, %s)", self.rec(expr.base, PREC_NONE), self.rec(expr.exponent, PREC_NONE))
def map_power(self, expr, enclosing_prec): from pymbolic.mapper.stringifier import PREC_NONE from pymbolic.primitives import is_constant, is_zero if is_constant(expr.exponent): if is_zero(expr.exponent): return "1" elif is_zero(expr.exponent - 1): return self.rec(expr.base, enclosing_prec) elif is_zero(expr.exponent - 2): return self.rec(expr.base*expr.base, enclosing_prec) return self.format("pow(%s, %s)", self.rec(expr.base, PREC_NONE), self.rec(expr.exponent, PREC_NONE))
def base_impl(expr, enclosing_prec, type_context): from pymbolic.mapper.stringifier import PREC_NONE from pymbolic.primitives import is_constant, is_zero if is_constant(expr.exponent): if is_zero(expr.exponent): return "1" elif is_zero(expr.exponent - 1): return self.rec(expr.base, enclosing_prec, type_context) elif is_zero(expr.exponent - 2): return self.rec(expr.base * expr.base, enclosing_prec, type_context) return "pow(%s, %s)" % ( self.rec(expr.base, PREC_NONE, type_context), self.rec(expr.exponent, PREC_NONE, type_context))
def base_impl(expr, enclosing_prec, type_context): from pymbolic.mapper.stringifier import PREC_NONE from pymbolic.primitives import is_constant, is_zero if is_constant(expr.exponent): if is_zero(expr.exponent): return "1" elif is_zero(expr.exponent - 1): return self.rec(expr.base, enclosing_prec, type_context) elif is_zero(expr.exponent - 2): return self.rec( expr.base*expr.base, enclosing_prec, type_context) return "pow(%s, %s)" % ( self.rec(expr.base, PREC_NONE, type_context), self.rec(expr.exponent, PREC_NONE, type_context))
def map_product(self, expr): from pymbolic.primitives import is_constant const = [] nonconst = [] for subexpr in expr.children: if is_constant(subexpr): const.append(subexpr) else: nonconst.append(subexpr) if len(nonconst) > 1: raise RuntimeError("DerivativeTaker doesn't support products with " "more than one non-constant") if not nonconst: nonconst = [1] from pytools import product return product(const) * self.rec(nonconst[0])
def map_power(self, expr, type_context): tgt_dtype = self.infer_type(expr) base_dtype = self.infer_type(expr.base) exponent_dtype = self.infer_type(expr.exponent) from pymbolic.primitives import is_constant, is_zero if is_constant(expr.exponent): if is_zero(expr.exponent): return 1 elif is_zero(expr.exponent - 1): return self.rec(expr.base, type_context) elif is_zero(expr.exponent - 2): return self.rec(expr.base * expr.base, type_context) if exponent_dtype.is_integral(): from loopy.codegen import SeenFunction func_name = ( "loopy_pow_" f"{tgt_dtype.numpy_dtype}_{exponent_dtype.numpy_dtype}") self.codegen_state.seen_functions.add( SeenFunction("int_pow", func_name, (tgt_dtype, exponent_dtype), (tgt_dtype, ))) # FIXME: This need some more callables to be registered. return var(func_name)(self.rec(expr.base, type_context), self.rec(expr.exponent, type_context)) else: from loopy.codegen import SeenFunction clbl = self.codegen_state.ast_builder.known_callables["pow"] clbl = clbl.with_types({ 0: tgt_dtype, 1: exponent_dtype }, self.codegen_state.callables_table)[0] self.codegen_state.seen_functions.add( SeenFunction(clbl.name, clbl.name_in_target, (base_dtype, exponent_dtype), (tgt_dtype, ))) return var(clbl.name_in_target)(self.rec(expr.base, type_context), self.rec(expr.exponent, type_context))
def _is_atomic(expr): return isinstance(expr, Variable) or is_constant(expr)