Exemplo n.º 1
0
    def call_parameters(self, arr_shape):
        substitution_dict = {
            sym: value
            for sym, value in zip(self._symbolic_shape, arr_shape)
            if sym is not None
        }

        widths = [
            end - start for start, end in zip(
                _get_start_from_slice(self._iterationSlice),
                _get_end_from_slice(self._iterationSlice, arr_shape))
        ]
        widths = sp.Matrix(widths).subs(substitution_dict)
        extend_bs = (1, ) * (3 - len(self._block_size))
        block_size = self._block_size + extend_bs
        if not self._compile_time_block_size:
            assert len(block_size) == 3
            adapted_block_size = []
            for i in range(len(widths)):
                factor = div_floor(prod(block_size[:i]),
                                   prod(adapted_block_size))
                adapted_block_size.append(
                    sp.Min(block_size[i] * factor, widths[i]))
            block_size = tuple(adapted_block_size) + extend_bs

        block_size = tuple(
            sp.Min(bs, max_bs)
            for bs, max_bs in zip(block_size, self._maximum_block_size))
        grid = tuple(
            div_ceil(length, block_size)
            for length, block_size in zip(widths, block_size))
        extend_gr = (1, ) * (3 - len(grid))

        return {'block': block_size, 'grid': grid + extend_gr}
Exemplo n.º 2
0
def expand_diff_products(expr):
    """Fully expands all derivatives by applying product rule"""
    if isinstance(expr, Diff):
        arg = expand_diff_products(expr.args[0])
        if arg.func == sp.Add:
            new_args = [
                Diff(e, target=expr.target, superscript=expr.superscript)
                for e in arg.args
            ]
            return sp.Add(*new_args)
        if arg.func not in (sp.Mul, sp.Pow):
            return Diff(arg, target=expr.target, superscript=expr.superscript)
        else:
            prod_list = normalize_product(arg)
            result = 0
            for i in range(len(prod_list)):
                pre_factor = prod(prod_list[j] for j in range(len(prod_list))
                                  if i != j)
                result += pre_factor * Diff(prod_list[i],
                                            target=expr.target,
                                            superscript=expr.superscript)
            return result
    else:
        new_args = [expand_diff_products(e) for e in expr.args]
        return expr.func(*new_args) if new_args else expr
Exemplo n.º 3
0
def poly_moments(order, dim):
    from pystencils.sympyextensions import prod
    c = sp.Matrix([expanded_symbol("c", subscript=i) for i in range(dim)])
    return [
        prod(c_i**m_i for c_i, m_i in zip(c, m))
        for m in moments_of_order(order, dim=dim)
    ]
Exemplo n.º 4
0
def get_field_fsize(field):
    """Determines the size of the index coordinate. Since walberla fields only support one index dimension,
    pystencils fields with multiple index dimensions are linearized to a single index dimension.
    """
    assert field.has_fixed_index_shape, \
        "All Fields have to be created with fixed index coordinate shape using index_shape=(q,) " + str(field.name)

    if field.index_dimensions == 0:
        return 1
    else:
        return prod(field.index_shape)
Exemplo n.º 5
0
    def expr_to_diff_decomposition(expression):
        """Decomposes a sp.Add node containing CeDiffs into:
        diff_dict: maps (target, superscript) -> [ (pre_factor, argument), ... ]
        i.e.  a partial(b) ( a is pre-factor, b is argument)
            in case of partial(a) partial(b) two entries are created  (0.5 partial(a), b), (0.5 partial(b), a)
        """
        DiffInfo = namedtuple("DiffInfo", ["target", "superscript"])

        class DiffSplit:
            def __init__(self, fac, argument):
                self.pre_factor = fac
                self.argument = argument

            def __repr__(self):
                return str((self.pre_factor, self.argument))

        assert isinstance(expression, sp.Add)
        diff_dict = defaultdict(list)
        rest = 0
        for term in expression.args:
            if isinstance(term, Diff):
                diff_dict[DiffInfo(term.target, term.superscript)].append(
                    DiffSplit(1, term.arg))
            else:
                mul_args = normalize_product(term)
                diffs = [d for d in mul_args if isinstance(d, Diff)]
                factor = prod(d for d in mul_args if not isinstance(d, Diff))
                if len(diffs) == 0:
                    rest += factor
                else:
                    for i, diff in enumerate(diffs):
                        all_but_current = [
                            d for j, d in enumerate(diffs) if i != j
                        ]
                        pre_factor = factor * prod(
                            all_but_current) * sp.Rational(1, len(diffs))
                        diff_dict[DiffInfo(diff.target,
                                           diff.superscript)].append(
                                               DiffSplit(pre_factor, diff.arg))

        return diff_dict, rest
Exemplo n.º 6
0
 def handle_mul(mul):
     args = normalize_product(mul)
     diffs = [a for a in args if isinstance(a, DiffOperator)]
     if len(diffs) == 0:
         return mul * argument if apply_to_constants else mul
     rest = [a for a in args if not isinstance(a, DiffOperator)]
     diffs.sort(key=_default_diff_sort_key)
     result = argument
     for d in reversed(diffs):
         result = Diff(result,
                       target=d.target,
                       superscript=d.superscript)
     return prod(rest) * result
Exemplo n.º 7
0
def correction_g(c, surface_tensions, symbolic_coefficients=False):
    assert len(c) == surface_tensions.rows
    n = len(c)
    result = 0
    for i in capital_i(4, n):
        for s in i:
            reduced_i = tuple(e for e in i if e != s)
            if symbolic_coefficients:
                coeff = sp.Symbol("Lambda_{}{}{}{}{}".format(s, *i))
            else:
                coeff = capital_lambda(surface_tensions, reduced_i)[s]
            result += coeff * capital_h(c[s], prod(c[j] for j in i))
    return result
Exemplo n.º 8
0
 def error_term_dict(self, order):
     error_terms = defaultdict(lambda: 0)
     for direction in self._stencil:
         weight = self.weights[tuple(direction)]
         x = tuple(self._dx * d_i for d_i in direction)
         for offset in multidimensional_sum(
                 order, dim=self.field.spatial_dimensions):
             fac = sp.factorial(order)
             error_terms[tuple(
                 sorted(offset))] += weight / fac * prod(x[off]
                                                         for off in offset)
     if self._derivative in error_terms:
         error_terms[self._derivative] -= 1
     return error_terms
Exemplo n.º 9
0
def generate_benchmark(ast, likwid=False, openmp=False, timing=False):
    """Return C code of a benchmark program for the given kernel.

    Args:
        ast: the pystencils AST object as returned by create_kernel
        likwid: if True likwid markers are added to the code
        openmp: relevant only if likwid=True, to generated correct likwid initialization code
        timing: add timing output to the code, prints time per iteration to stdout

    Returns:
        C code as string
    """
    accessed_fields = {f.name: f for f in ast.fields_accessed}
    constants = []
    fields = []
    call_parameters = []
    for p in ast.get_parameters():
        if not p.is_field_parameter:
            constants.append((p.symbol.name, str(p.symbol.dtype)))
            call_parameters.append(p.symbol.name)
        else:
            assert p.is_field_pointer, "Benchmark implemented only for kernels with fixed loop size"
            field = accessed_fields[p.field_name]
            dtype = str(get_base_type(p.symbol.dtype))
            fields.append((p.field_name, dtype, prod(field.shape)))
            call_parameters.append(p.field_name)

    header_list = get_headers(ast)
    includes = "\n".join(["#include %s" % (include_file,) for include_file in header_list])

    # Strip "#pragma omp parallel" from within kernel, because main function takes care of that
    # when likwid and openmp are enabled
    if likwid and openmp:
        if len(ast.body.args) > 0 and isinstance(ast.body.args[0], PragmaBlock):
            ast.body.args[0].pragma_line = ''

    args = {
        'likwid': likwid,
        'openmp': openmp,
        'kernel_code': generate_c(ast, dialect='c'),
        'kernelName': ast.function_name,
        'fields': fields,
        'constants': constants,
        'call_argument_list': ",".join(call_parameters),
        'includes': includes,
        'timing': timing,
    }
    return benchmark_template.render(**args)
Exemplo n.º 10
0
def extract_gamma(free_energy, order_parameters):
    """Extracts parameters before the gradient terms"""
    result = defaultdict(lambda: 0)
    free_energy = free_energy.expand()
    assert free_energy.func == sp.Add
    for product in free_energy.args:
        product = normalize_product(product)
        diff_factors = [e for e in product if e.func == Diff]
        if len(diff_factors) == 0:
            continue

        if len(diff_factors) != 2:
            raise ValueError(f"Could not determine Λ because of term {str(product)}")

        indices = sorted([order_parameters.index(d.args[0]) for d in diff_factors])
        increment = prod(e for e in product if e.func != Diff)
        if diff_factors[0] == diff_factors[1]:
            increment *= 2
        result[tuple(indices)] += increment
    return result
Exemplo n.º 11
0
    def visit(e):
        if not isinstance(e, sp.Tuple):
            e = e.expand()

        if e.func == Diff:
            result = 0
            diff_args = {'target': e.target, 'superscript': e.superscript}
            diff_inner = e.args[0]
            diff_inner = visit(diff_inner)
            if diff_inner.func not in (sp.Add, sp.Mul):
                return e
            for term in diff_inner.args if diff_inner.func == sp.Add else [
                    diff_inner
            ]:
                independent_terms = 1
                dependent_terms = []
                for factor in normalize_product(term):
                    if factor in functions or isinstance(factor, Diff):
                        dependent_terms.append(factor)
                    else:
                        independent_terms *= factor
                for i in range(len(dependent_terms)):
                    dependent_term = dependent_terms[i]
                    other_dependent_terms = dependent_terms[:
                                                            i] + dependent_terms[
                                                                i + 1:]
                    processed_diff = normalize_diff_order(
                        Diff(dependent_term, **diff_args))
                    result += independent_terms * prod(
                        other_dependent_terms) * processed_diff
            return result
        elif isinstance(e, sp.Piecewise):
            return sp.Piecewise(*((expand_diff_full(a, functions, constants),
                                   b) for a, b in e.args))
        elif isinstance(expr, sp.Tuple):
            new_args = [visit(arg) for arg in e.args]
            return sp.Tuple(*new_args)
        else:
            new_args = [visit(arg) for arg in e.args]
            return e.func(*new_args) if new_args else e
Exemplo n.º 12
0
 def max_threads_per_block(self):
     if is_integer_sequence(self._block_size):
         return prod(self._block_size)
     else:
         return None