def facet_integral_predicates(self, mesh, integral_type, kinfo): self.bag.needs_cell_facets = True # Number of recerence cell facets if mesh.cell_set._extruded: self.num_facets = mesh._base_mesh.ufl_cell().num_facets() else: self.num_facets = mesh.ufl_cell().num_facets() # Index for loop over cell faces of reference cell fidx = self.bag.index_creator((self.num_facets,)) # Cell is interior or exterior select = 1 if integral_type.startswith("interior_facet") else 0 i = self.bag.index_creator((1,)) predicates = [pym.Comparison(pym.Subscript(pym.Variable(self.cell_facets_arg), (fidx[0], 0)), "==", select)] # TODO subdomain boundary integrals, this does the wrong thing for integrals like f*ds + g*ds(1) # "otherwise" is treated incorrectly as "everywhere" # However, this replicates an existing slate bug. if kinfo.subdomain_id != "otherwise": predicates.append(pym.Comparison(pym.Subscript(pym.Variable(self.cell_facets_arg), (fidx[0], 1)), "==", kinfo.subdomain_id)) # Additional facet array argument to be fed into tsfc loopy kernel subscript = pym.Subscript(pym.Variable(self.local_facet_array_arg), (pym.Sum((i[0], fidx[0])))) facet_arg = SubArrayRef(i, subscript) return predicates, fidx, facet_arg
def make_random_expression(var_values, size): from random import randrange import pymbolic.primitives as p v = randrange(1500) size[0] += 1 if v < 500 and size[0] < 40: term_count = randrange(2, 5) if randrange(2) < 1: cls = p.Sum else: cls = p.Product return cls( tuple( make_random_expression(var_values, size) for i in range(term_count))) elif v < 750: return make_random_value() elif v < 1000: var_name = "var_%d" % len(var_values) assert var_name not in var_values var_values[var_name] = make_random_value() return p.Variable(var_name) elif v < 1250: # Cannot use '-' because that destroys numpy constants. return p.Sum((make_random_expression(var_values, size), -make_random_expression(var_values, size))) elif v < 1500: # Cannot use '/' because that destroys numpy constants. return p.Quotient(make_random_expression(var_values, size), make_random_expression(var_values, size))
def expression_indexed(expr, parameters): aggregate, multiindex = (expression(c, parameters) for c in expr.children) return pym.Subscript(aggregate, multiindex) extents = [int(numpy.prod(expr.aggregate.shape[i+1:])) for i in range(len(multiindex))] make_sum = lambda x, y: pym.Sum((x, y)) index = reduce(make_sum, [pym.Product((e, m)) for e, m in zip(extents, multiindex)]) return pym.Subscript(aggregate, (index,))
def initialise_terminals(self, var2terminal, coefficients): """ Initilisation of the variables in which coefficients and the Tensors coming from TSFC are saved. :arg var2terminal: dictionary that maps Slate Tensors to gem Variables """ tensor2temp = OrderedDict() inits = [] for gem_tensor, slate_tensor in var2terminal.items(): assert slate_tensor.terminal, "Only terminal tensors need to be initialised in Slate kernels." (_, dtype), = assign_dtypes([gem_tensor], self.tsfc_parameters["scalar_type"]) loopy_tensor = loopy.TemporaryVariable( gem_tensor.name, dtype=dtype, shape=gem_tensor.shape, address_space=loopy.AddressSpace.LOCAL) tensor2temp[slate_tensor] = loopy_tensor if not slate_tensor.assembled: indices = self.bag.index_creator(self.shape(slate_tensor)) inames = {var.name for var in indices} var = pym.Subscript(pym.Variable(loopy_tensor.name), indices) inits.append( loopy.Assignment(var, "0.", id="init%d" % len(inits), within_inames=frozenset(inames))) else: f = slate_tensor.form if isinstance( slate_tensor.form, tuple) else (slate_tensor.form, ) coeff = tuple(coefficients[c] for c in f) offset = 0 ismixed = tuple( (type(c.ufl_element()) == MixedElement) for c in f) names = [] for (im, c) in zip(ismixed, coeff): names += [name for (name, ext) in c.values()] if im else [c[0]] # Mixed coefficients come as seperate parameter (one per space) for i, shp in enumerate(*slate_tensor.shapes.values()): indices = self.bag.index_creator((shp, )) inames = {var.name for var in indices} offset_index = (pym.Sum((offset, indices[0])), ) name = names[i] if ismixed else names var = pym.Subscript(pym.Variable(loopy_tensor.name), offset_index) c = pym.Subscript(pym.Variable(name), indices) inits.append( loopy.Assignment(var, c, id="init%d" % len(inits), within_inames=frozenset(inames))) offset += shp return inits, tensor2temp
def make_random_int_expression(prefix, var_values, size, nonneg): from random import randrange import pymbolic.primitives as p if size[0] < 10: v = randrange(800) else: v = randrange(1000) size[0] += 1 if v < 10: var_name = "var_%s_%d" % (prefix, len(var_values)) assert var_name not in var_values var_values[var_name] = make_random_int_value(nonneg) return p.Variable(var_name) elif v < 200 and size[0] < 40: term_count = randrange(2, 5) if randrange(2) < 1: cls = p.Sum else: cls = p.Product return cls( tuple( make_random_int_expression( prefix, var_values, size, nonneg=nonneg) for i in range(term_count))) elif v < 400 and size[0] < 40: return p.FloorDiv( make_random_int_expression(prefix, var_values, size, nonneg=nonneg), make_nonzero_random_int_expression(prefix, var_values, size, nonneg=nonneg)) elif v < 600 and size[0] < 40: return p.Remainder( make_random_int_expression(prefix, var_values, size, nonneg=nonneg), make_nonzero_random_int_expression(prefix, var_values, size, nonneg=nonneg)) elif v < 800 and not nonneg and size[0] < 40: return p.Sum(( make_random_int_expression(prefix, var_values, size, nonneg=nonneg), -make_random_int_expression( prefix, var_values, size, nonneg=nonneg), )) else: return make_random_int_value(nonneg)
def _expression_flexiblyindexed(expr, ctx): var = expression(expr.children[0], ctx) rank = [] for off, idxs in expr.dim2idxs: for index, stride in idxs: assert isinstance(index, gem.Index) rank_ = [off] for index, stride in idxs: rank_.append(p.Product((ctx.active_indices[index], stride))) rank.append(p.Sum(tuple(rank_))) return p.Subscript(var, tuple(rank))
def initialise_terminals(self, var2terminal, coefficients): """ Initilisation of the variables in which coefficients and the Tensors coming from TSFC are saved. :arg var2terminal: dictionary that maps Slate Tensors to gem Variables """ tensor2temp = OrderedDict() inits = [] for gem_tensor, slate_tensor in var2terminal.items(): loopy_tensor = loopy.TemporaryVariable(gem_tensor.name, shape=gem_tensor.shape, address_space=loopy.AddressSpace.LOCAL) tensor2temp[slate_tensor] = loopy_tensor if isinstance(slate_tensor, slate.Tensor): indices = self.bag.index_creator(self.shape(slate_tensor)) inames = {var.name for var in indices} var = pym.Subscript(pym.Variable(loopy_tensor.name), indices) inits.append(loopy.Assignment(var, "0.", id="init%d" % len(inits), within_inames=frozenset(inames))) elif isinstance(slate_tensor, slate.AssembledVector): f = slate_tensor._function coeff = coefficients[f] offset = 0 ismixed = (type(f.ufl_element()) == MixedElement) names = [name for (name, ext) in coeff.values()] if ismixed else coeff[0] # Mixed coefficients come as seperate parameter (one per space) for i, shp in enumerate(*slate_tensor.shapes.values()): indices = self.bag.index_creator((shp,)) inames = {var.name for var in indices} offset_index = (pym.Sum((offset, indices[0])),) name = names[i] if ismixed else names var = pym.Subscript(pym.Variable(loopy_tensor.name), offset_index) c = pym.Subscript(pym.Variable(name), indices) inits.append(loopy.Assignment(var, c, id="init%d" % len(inits), within_inames=frozenset(inames))) offset += shp return inits, tensor2temp
def map_sum(self, expr): first_group = [] second_group = [] for child in expr.children: tchild = child if isinstance(tchild, prim.CommonSubexpression): tchild = tchild.child if isinstance(tchild, prim.Product): neg_int_count = 0 for subchild in tchild.children: if isinstance(subchild, int) and subchild < 0: neg_int_count += 1 if neg_int_count % 2 == 1: second_group.append(child) else: first_group.append(child) else: first_group.append(child) return prim.Sum(tuple(first_group+second_group))
def make_random_fp_expression(prefix, var_values, size, use_complex): from random import randrange import pymbolic.primitives as p v = randrange(1500) size[0] += 1 if v < 500 and size[0] < 40: term_count = randrange(2, 5) if randrange(2) < 1: cls = p.Sum else: cls = p.Product return cls( tuple( make_random_fp_expression(prefix, var_values, size, use_complex) for i in range(term_count))) elif v < 750: return make_random_fp_value(use_complex=use_complex) elif v < 1000: var_name = "var_%s_%d" % (prefix, len(var_values)) assert var_name not in var_values var_values[var_name] = make_random_fp_value(use_complex=use_complex) return p.Variable(var_name) elif v < 1250: # FIXME: What does this comment mean? # Cannot use '-' because that destroys numpy constants. return p.Sum(( make_random_fp_expression(prefix, var_values, size, use_complex), -make_random_fp_expression(prefix, var_values, size, use_complex))) elif v < 1500: # FIXME: What does this comment mean? # Cannot use '/' because that destroys numpy constants. return p.Quotient( make_random_fp_expression(prefix, var_values, size, use_complex), make_random_fp_expression(prefix, var_values, size, use_complex)) else: assert False
def test_structure_preservation(): x = prim.Sum((5, 7)) from pymbolic.mapper import IdentityMapper x2 = IdentityMapper()(x) assert x == x2
def _expression_sum(expr, ctx): return p.Sum(tuple(expression(c, ctx) for c in expr.children))
def _sub(x, y): return p.Sum((x, p.Product(((-1), y))))
def _add(x, y): return p.Sum((x, y))
def map_Add(self, expr): return prim.Sum(tuple(self.rec(arg) for arg in expr.args))
def _add(x, y): # noqa return p.Sum((x, y))
def parse_postfix(self, pstate, min_precedence, left_exp): import pymbolic.primitives as primitives did_something = False next_tag = pstate.next_tag() if next_tag is _openpar and _PREC_CALL > min_precedence: pstate.advance() args, kwargs = self.parse_arglist(pstate) if kwargs: left_exp = primitives.CallWithKwargs(left_exp, args, kwargs) else: left_exp = primitives.Call(left_exp, args) did_something = True elif next_tag is _openbracket and _PREC_CALL > min_precedence: pstate.advance() pstate.expect_not_end() left_exp = primitives.Subscript(left_exp, self.parse_expression(pstate)) pstate.expect(_closebracket) pstate.advance() did_something = True elif next_tag is _if and _PREC_IF > min_precedence: from pymbolic.primitives import If then_expr = left_exp pstate.advance() pstate.expect_not_end() condition = self.parse_expression(pstate, _PREC_LOGICAL_OR) pstate.expect(_else) pstate.advance() else_expr = self.parse_expression(pstate) left_exp = If(condition, then_expr, else_expr) did_something = True elif next_tag is _dot and _PREC_CALL > min_precedence: pstate.advance() pstate.expect(_identifier) left_exp = primitives.Lookup(left_exp, pstate.next_str()) pstate.advance() did_something = True elif next_tag is _plus and _PREC_PLUS > min_precedence: pstate.advance() right_exp = self.parse_expression(pstate, _PREC_PLUS) if isinstance(left_exp, primitives.Sum): left_exp = primitives.Sum(left_exp.children + (right_exp,)) else: left_exp = primitives.Sum((left_exp, right_exp)) did_something = True elif next_tag is _minus and _PREC_PLUS > min_precedence: pstate.advance() right_exp = self.parse_expression(pstate, _PREC_PLUS) if isinstance(left_exp, primitives.Sum): left_exp = primitives.Sum(left_exp.children + ((-right_exp),)) # noqa pylint:disable=invalid-unary-operand-type else: left_exp = primitives.Sum((left_exp, -right_exp)) # noqa pylint:disable=invalid-unary-operand-type did_something = True elif next_tag is _times and _PREC_TIMES > min_precedence: pstate.advance() right_exp = self.parse_expression(pstate, _PREC_PLUS) if isinstance(left_exp, primitives.Product): left_exp = primitives.Product(left_exp.children + (right_exp,)) else: left_exp = primitives.Product((left_exp, right_exp)) did_something = True elif next_tag is _floordiv and _PREC_TIMES > min_precedence: pstate.advance() left_exp = primitives.FloorDiv( left_exp, self.parse_expression(pstate, _PREC_TIMES)) did_something = True elif next_tag is _over and _PREC_TIMES > min_precedence: pstate.advance() left_exp = primitives.Quotient( left_exp, self.parse_expression(pstate, _PREC_TIMES)) did_something = True elif next_tag is _modulo and _PREC_TIMES > min_precedence: pstate.advance() left_exp = primitives.Remainder( left_exp, self.parse_expression(pstate, _PREC_TIMES)) did_something = True elif next_tag is _power and _PREC_POWER > min_precedence: pstate.advance() left_exp = primitives.Power( left_exp, self.parse_expression(pstate, _PREC_TIMES)) did_something = True elif next_tag is _and and _PREC_LOGICAL_AND > min_precedence: pstate.advance() from pymbolic.primitives import LogicalAnd left_exp = LogicalAnd(( left_exp, self.parse_expression(pstate, _PREC_LOGICAL_AND))) did_something = True elif next_tag is _or and _PREC_LOGICAL_OR > min_precedence: pstate.advance() from pymbolic.primitives import LogicalOr left_exp = LogicalOr(( left_exp, self.parse_expression(pstate, _PREC_LOGICAL_OR))) did_something = True elif next_tag is _bitwiseor and _PREC_BITWISE_OR > min_precedence: pstate.advance() from pymbolic.primitives import BitwiseOr left_exp = BitwiseOr(( left_exp, self.parse_expression(pstate, _PREC_BITWISE_OR))) did_something = True elif next_tag is _bitwisexor and _PREC_BITWISE_XOR > min_precedence: pstate.advance() from pymbolic.primitives import BitwiseXor left_exp = BitwiseXor(( left_exp, self.parse_expression(pstate, _PREC_BITWISE_XOR))) did_something = True elif next_tag is _bitwiseand and _PREC_BITWISE_AND > min_precedence: pstate.advance() from pymbolic.primitives import BitwiseAnd left_exp = BitwiseAnd(( left_exp, self.parse_expression(pstate, _PREC_BITWISE_AND))) did_something = True elif next_tag is _rightshift and _PREC_SHIFT > min_precedence: pstate.advance() from pymbolic.primitives import RightShift left_exp = RightShift( left_exp, self.parse_expression(pstate, _PREC_SHIFT)) did_something = True elif next_tag is _leftshift and _PREC_SHIFT > min_precedence: pstate.advance() from pymbolic.primitives import LeftShift left_exp = LeftShift( left_exp, self.parse_expression(pstate, _PREC_SHIFT)) did_something = True elif next_tag in self._COMP_TABLE and _PREC_COMPARISON > min_precedence: pstate.advance() from pymbolic.primitives import Comparison left_exp = Comparison( left_exp, self._COMP_TABLE[next_tag], self.parse_expression(pstate, _PREC_COMPARISON)) did_something = True elif next_tag is _colon and _PREC_SLICE >= min_precedence: pstate.advance() expr_pstate = pstate.copy() assert not isinstance(left_exp, primitives.Slice) from pytools.lex import ParseError try: next_expr = self.parse_expression(expr_pstate, _PREC_SLICE) except ParseError: # no expression follows, too bad. left_exp = primitives.Slice((left_exp, None,)) else: left_exp = _join_to_slice(left_exp, next_expr) pstate.assign(expr_pstate) did_something = True elif next_tag is _comma and _PREC_COMMA > min_precedence: # The precedence makes the comma left-associative. pstate.advance() if pstate.is_at_end() or pstate.next_tag() is _closepar: if isinstance(left_exp, (tuple, list)) \ and not isinstance(left_exp, FinalizedContainer): # left_expr is a container with trailing commas pass else: left_exp = (left_exp,) else: new_el = self.parse_expression(pstate, _PREC_COMMA) if isinstance(left_exp, (tuple, list)) \ and not isinstance(left_exp, FinalizedContainer): left_exp = left_exp + (new_el,) else: left_exp = (left_exp, new_el) did_something = True return left_exp, did_something