def CubicInterpolation(StencilKernel=Stencil, **kwargs): """ Creates an cubic interpolation kernel, which interpolates in input array :math:`f^{(h)}` on the fine grid into an array :math:`f^{(2 h)}` on the coarse grid via .. math:: f^{(h)}_{2 i} &= f^{(2 h)}_{i} f^{(h)}_{2 i + 1} &= - \\frac{1}{16} f^{(2 h)}_{i - 1} + \\frac{9}{16} f^{(2 h)}_{i} + \\frac{9}{16} f^{(2 h)}_{i + 1} - \\frac{1}{16} f^{(2 h)}_{i + 2} in each dimension. See :class:`transfer.InterpolationBase`. """ if kwargs.get("halo_shape", 0) < 2: raise ValueError("CubicInterpolation requires padding >= 2") from pymbolic.primitives import Quotient odd_coefs = { -3: Quotient(-1, 16), -1: Quotient(9, 16), 1: Quotient(9, 16), 3: Quotient(-1, 16) } even_coefs = {0: 1} return InterpolationBase(even_coefs, odd_coefs, StencilKernel, **kwargs)
def FullWeighting(StencilKernel=Stencil, **kwargs): """ Creates a full-weighting restriction kernel, which restricts in input array :math:`f^{(h)}` on the fine grid into an array :math:`f^{(2 h)}` on the coarse grid by applying .. math:: f^{(2 h)}_i = \\frac{1}{4} f^{(h)}_{2 i - 1} + \\frac{1}{2} f^{(h)}_{2 i} + \\frac{1}{4} f^{(h)}_{2 i + 1} in each dimension. See :class:`transfer.RestrictionBase`. """ from pymbolic.primitives import Quotient coefs = {-1: Quotient(1, 4), 0: Quotient(1, 2), 1: Quotient(1, 4)} return RestrictionBase(coefs, StencilKernel, **kwargs)
def LinearInterpolation(StencilKernel=Stencil, **kwargs): """ Creates an linear interpolation kernel, which interpolates in input array :math:`f^{(h)}` on the fine grid into an array :math:`f^{(2 h)}` on the coarse grid via .. math:: f^{(h)}_{2 i} &= f^{(2 h)}_{i} f^{(h)}_{2 i + 1} &= \\frac{1}{2} f^{(2 h)}_{i} + \\frac{1}{2} f^{(2 h)}_{i + 1} in each dimension. See :class:`transfer.InterpolationBase`. """ from pymbolic.primitives import Quotient odd_coefs = {-1: Quotient(1, 2), 1: Quotient(1, 2)} even_coefs = {0: 1} return InterpolationBase(even_coefs, odd_coefs, StencilKernel, **kwargs)
def test_strict_round_trip(knl): from pymbolic import parse from pymbolic.primitives import Quotient exprs = [2j, parse("x**y"), Quotient(1, 2), parse("exp(x)")] for expr in exprs: result = knl.eval_expr(expr) round_trips_correctly = result == expr if not round_trips_correctly: print("ORIGINAL:") print("") print(expr) print("") print("POST-MAXIMA:") print("") print(result) assert round_trips_correctly
def map_fortran_division(self, expr, *args): # We remove all these before type inference ever sees them. from loopy.type_inference import TypeInferenceFailure try: num_dtype = self.infer_type(expr.numerator).numpy_dtype den_dtype = self.infer_type(expr.denominator).numpy_dtype except TypeInferenceFailure: return super().map_fortran_division(expr, *args) from pymbolic.primitives import Quotient, FloorDiv if num_dtype.kind in "iub" and den_dtype.kind in "iub": warn_with_kernel( self.kernel, "fortran_int_div", "Integer division in Fortran code. Loopy currently gets this " "wrong for negative arguments.") return FloorDiv(self.rec(expr.numerator, *args), self.rec(expr.denominator, *args)) else: return Quotient(self.rec(expr.numerator, *args), self.rec(expr.denominator, *args))
def parse_postfix(self, pstate, min_precedence, left_exp): import pymbolic.primitives as primitives import pymbolic.parser as p did_something = False next_tag = pstate.next_tag() if next_tag is p._openpar and p._PREC_CALL > min_precedence: pstate.advance() pstate.expect_not_end() if next_tag is p._closepar: pstate.advance() left_exp = primitives.Call(left_exp, ()) else: args = self.parse_expression(pstate) if not isinstance(args, tuple): args = (args, ) pstate.expect(p._closepar) pstate.advance() if left_exp == primitives.Variable("matrix"): left_exp = np.array(list(list(row) for row in args)) else: left_exp = primitives.Call(left_exp, args) did_something = True elif next_tag is p._openbracket and p._PREC_CALL > min_precedence: pstate.advance() pstate.expect_not_end() left_exp = primitives.Subscript(left_exp, self.parse_expression(pstate)) pstate.expect(p._closebracket) pstate.advance() did_something = True elif next_tag is p._dot and p._PREC_CALL > min_precedence: pstate.advance() pstate.expect(p._identifier) left_exp = primitives.Lookup(left_exp, pstate.next_str()) pstate.advance() did_something = True elif next_tag is p._plus and p._PREC_PLUS > min_precedence: pstate.advance() left_exp += self.parse_expression(pstate, p._PREC_PLUS) did_something = True elif next_tag is p._minus and p._PREC_PLUS > min_precedence: pstate.advance() left_exp -= self.parse_expression(pstate, p._PREC_PLUS) did_something = True elif next_tag is p._times and p._PREC_TIMES > min_precedence: pstate.advance() left_exp *= self.parse_expression(pstate, p._PREC_TIMES) did_something = True elif next_tag is p._over and p._PREC_TIMES > min_precedence: pstate.advance() from pymbolic.primitives import Quotient left_exp = Quotient(left_exp, self.parse_expression(pstate, p._PREC_TIMES)) did_something = True elif next_tag is self.power_sym and p._PREC_POWER > min_precedence: pstate.advance() exponent = self.parse_expression(pstate, p._PREC_POWER) if left_exp == np.e: from pymbolic.primitives import Call, Variable left_exp = Call(Variable("exp"), (exponent, )) else: left_exp **= exponent did_something = True elif next_tag is p._comma and p._PREC_COMMA > min_precedence: # The precedence makes the comma left-associative. pstate.advance() if pstate.is_at_end() or pstate.next_tag() is p._closepar: left_exp = (left_exp, ) else: new_el = self.parse_expression(pstate, p._PREC_COMMA) if isinstance(left_exp, tuple) \ and not isinstance(left_exp, FinalizedTuple): left_exp = left_exp + (new_el, ) else: left_exp = (left_exp, new_el) did_something = True return left_exp, did_something
def test_eval_binary_expr(self): """ Tests the functionality of `matstep.simplifiers.StepSimplifier .eval_binary_expr` using `pymbolic.primitives.Quotient`. """ # Test flat: [1 / 2] -> 0.5 expr = Quotient(1, 2) actual = self.simplifier(expr) expected = 0.5 self.assertEqual(expected, actual) # Test nested left: [[1 / 2] / 2] -> 0.5 / 2 expr = Quotient(Quotient(1, 2), 2) actual = self.simplifier(expr) expected = Quotient(0.5, 2) self.assertEqual(expected, actual) # Test nested right: [1 / [1 / 2]] -> 1 / 0.5 expr = Quotient(1, Quotient(1, 2)) actual = self.simplifier(expr) expected = Quotient(1, 0.5) self.assertEqual(expected, actual) # Test nested left right: [[1 / 2] / [1 / 2]] -> 0.5 / 0.5 expr = Quotient(Quotient(1, 2), Quotient(1, 2)) actual = self.simplifier(expr) expected = Quotient(0.5, 0.5) self.assertEqual(expected, actual)