Ejemplo n.º 1
0
    def add_watches(self, watches):
        """Add quantities that are printed after every time step."""

        from pytools import Record

        class WatchInfo(Record):
            pass

        for watch in watches:
            if isinstance(watch, tuple):
                display, expr = watch
            else:
                display = watch
                expr = watch

            parsed = self._parse_expr(expr)
            parsed, dep_data = self._get_expr_dep_data(parsed)

            from pytools import any
            self.have_nonlocal_watches = self.have_nonlocal_watches or \
                    any(dd.nonlocal_agg for dd in dep_data)

            from pymbolic import compile
            compiled = compile(parsed, [dd.varname for dd in dep_data])

            watch_info = WatchInfo(display=display, parsed=parsed, dep_data=dep_data,
                    compiled=compiled)

            self.watches.append(watch_info)
Ejemplo n.º 2
0
    def method_matrix_func(self):
        try:
            return self.method_matrix_func_cache
        except AttributeError:
            from pymbolic import var
            stepper = self.method_fac(var("dt"))

            mat = self.matrix

            def f2f_rhs(t, yf, ys):
                return fold_constants(expand(mat[0, 0] * yf()))

            def s2f_rhs(t, yf, ys):
                return fold_constants(expand(mat[0, 1] * ys()))

            def f2s_rhs(t, yf, ys):
                return fold_constants(expand(mat[1, 0] * yf()))

            def s2s_rhs(t, yf, ys):
                return fold_constants(expand(mat[1, 1] * ys()))

            method_matrix, _ = make_method_matrix(stepper,
                                                  rhss=(f2f_rhs, s2f_rhs,
                                                        f2s_rhs, s2s_rhs),
                                                  f_size=1,
                                                  s_size=1)

            from pymbolic import compile
            self.method_matrix_func_cache = compile(method_matrix)
            return self.method_matrix_func_cache
Ejemplo n.º 3
0
def test_compile():
    from pymbolic import parse, compile
    code = compile(parse("x ** y"), ["x", "y"])
    assert code(2, 5) == 32

    # Test pickling of compiled code.
    import pickle
    code = pickle.loads(pickle.dumps(code))
    assert code(3, 3) == 27
Ejemplo n.º 4
0
def test_compile():
    from pymbolic import parse, compile
    code = compile(parse("x ** y"), ["x", "y"])
    assert code(2, 5) == 32

    # Test pickling of compiled code.
    import pickle
    code = pickle.loads(pickle.dumps(code))
    assert code(3, 3) == 27
Ejemplo n.º 5
0
    def get_expr_dataset(self, expression, description=None, unit=None):
        """Prepare a time-series dataset for a given expression.

        @arg expression: A C{pymbolic} expression that may involve
          the time-series variables and the constants in this :class:`LogManager`.
          If there is data from multiple ranks for a quantity occuring in
          this expression, an aggregator may have to be specified.
        @return: C{(description, unit, table)}, where C{table}
          is a list of tuples C{(tick_nbr, value)}.

        Aggregators are specified as follows:
        - C{qty.min}, C{qty.max}, C{qty.avg}, C{qty.sum}, C{qty.norm2}
        - C{qty[rank_nbr]}
        - C{qty.loc}
        """

        parsed = self._parse_expr(expression)
        parsed, dep_data = self._get_expr_dep_data(parsed)

        # aggregate table data
        for dd in dep_data:
            table = self.get_table(dd.name)
            table.sort(["step"])
            dd.table = table.aggregated(["step"], "value", dd.agg_func).data

        # evaluate unit and description, if necessary
        if unit is None:
            from pymbolic import substitute, parse

            unit_dict = dict((dd.varname, dd.qdat.unit) for dd in dep_data)
            from pytools import all
            if all(v is not None for v in six.itervalues(unit_dict)):
                unit_dict = dict(
                    (k, parse(v)) for k, v in six.iteritems(unit_dict))
                unit = substitute(parsed, unit_dict)
            else:
                unit = None

        if description is None:
            description = expression

        # compile and evaluate
        from pymbolic import compile
        compiled = compile(parsed, [dd.varname for dd in dep_data])

        data = []

        for key, values in _join_by_first_of_tuple(dd.table
                                                   for dd in dep_data):
            try:
                data.append((key, compiled(*values)))
            except ZeroDivisionError:
                pass

        return (description, unit, data)
Ejemplo n.º 6
0
    def get_expr_dataset(self, expression, description=None, unit=None):
        """Prepare a time-series dataset for a given expression.

        @arg expression: A C{pymbolic} expression that may involve
          the time-series variables and the constants in this :class:`LogManager`.
          If there is data from multiple ranks for a quantity occuring in
          this expression, an aggregator may have to be specified.
        @return: C{(description, unit, table)}, where C{table}
          is a list of tuples C{(tick_nbr, value)}.

        Aggregators are specified as follows:
        - C{qty.min}, C{qty.max}, C{qty.avg}, C{qty.sum}, C{qty.norm2}
        - C{qty[rank_nbr]}
        - C{qty.loc}
        """

        parsed = self._parse_expr(expression)
        parsed, dep_data = self._get_expr_dep_data(parsed)

        # aggregate table data
        for dd in dep_data:
            table = self.get_table(dd.name)
            table.sort(["step"])
            dd.table = table.aggregated(["step"], "value", dd.agg_func).data

        # evaluate unit and description, if necessary
        if unit is None:
            from pymbolic import substitute, parse

            unit_dict = dict((dd.varname, dd.qdat.unit) for dd in dep_data)
            from pytools import all
            if all(v is not None for v in six.itervalues(unit_dict)):
                unit_dict = dict((k, parse(v)) for k, v in six.iteritems(unit_dict))
                unit = substitute(parsed, unit_dict)
            else:
                unit = None

        if description is None:
            description = expression

        # compile and evaluate
        from pymbolic import compile
        compiled = compile(parsed, [dd.varname for dd in dep_data])

        data = []

        for key, values in _join_by_first_of_tuple(dd.table for dd in dep_data):
            try:
                data.append((key, compiled(*values)))
            except ZeroDivisionError:
                pass

        return (description, unit, data)
Ejemplo n.º 7
0
def fast_evaluator(matrix, sparse=False):
    """
    Generate a function to evaluate a step matrix quickly.
    The input comes from StepMatrixFinder.
    """
    # First, rename variables in the matrix to names that are acceptable Python
    # identifiers. We make use of dagrt's KeyToUniqueNameMap.
    from dagrt.codegen.utils import KeyToUniqueNameMap
    name_map = KeyToUniqueNameMap(forced_prefix="matrix")

    def make_identifier(symbol):
        from pymbolic import var
        assert isinstance(symbol, var)
        return var(name_map.get_or_make_name_for_key(symbol.name))

    def get_var_order_from_name_map():
        order = sorted(name_map)
        return (order,
            [name_map.get_or_make_name_for_key(key) for key in order])

    from pymbolic.mapper.substitutor import SubstitutionMapper

    substitutor = SubstitutionMapper(make_identifier)

    from pymbolic import compile
    # functools.partial ensures the resulting object is picklable.
    from functools import partial

    if sparse:
        data = [substitutor(entry) for entry in matrix.data]
        var_order, renamed_vars = get_var_order_from_name_map()
        compiled_entries = [compile(entry, renamed_vars) for entry in data]
        compiled_matrix = matrix.copy(data=compiled_entries)
    else:
        matrix = substitutor(matrix)
        var_order, renamed_vars = get_var_order_from_name_map()
        compiled_matrix = compile(matrix, renamed_vars)

    return partial(_eval_compiled_matrix, compiled_matrix, var_order)
Ejemplo n.º 8
0
    def add_watches(self, watches):
        """Add quantities that are printed after every time step."""

        from pytools import Record

        for watch in watches:
            parsed = self._parse_expr(watch)
            parsed, dep_data = self._get_expr_dep_data(parsed)

            from pymbolic import compile
            compiled = compile(parsed, [dd.varname for dd in dep_data])

            watch_info = Record(expr=watch, parsed=parsed, dep_data=dep_data,
                    compiled=compiled)

            self.watches.append(watch_info)
Ejemplo n.º 9
0
    def get_expr_dataset(self, expression, description=None, unit=None):
        """Prepare a time-series dataset for a given expression.

        @arg expression: A C{pymbolic} expression that may involve
          the time-series variables and the constants in this L{LogManager}.
          If there is data from multiple ranks for a quantity occuring in
          this expression, an aggregator may have to be specified.
        @return: C{(description, unit, table)}, where C{table} 
          is a list of tuples C{(tick_nbr, value)}.

        Aggregators are specified as follows:
        - C{qty.min}, C{qty.max}, C{qty.avg}, C{qty.sum}, C{qty.norm2}
        - C{qty[rank_nbr]
        """

        parsed = self._parse_expr(expression)
        parsed, dep_data = self._get_expr_dep_data(parsed)

        # aggregate table data
        for dd in dep_data:
            table = self.get_table(dd.name)
            table.sort(["step"])
            dd.table = table.aggregated(["step"], "value", dd.agg_func).data

        # evaluate unit and description, if necessary
        if unit is None:
            from pymbolic import substitute, parse

            unit = substitute(parsed,
                    dict((dd.varname, parse(dd.qdat.unit)) for dd in dep_data)
                    )

        if description is None:
            description = expression

        # compile and evaluate
        from pymbolic import compile
        compiled = compile(parsed, [dd.varname for dd in dep_data])

        return (description,
                unit,
                [(key, compiled(*values))
                    for key, values in _join_by_first_of_tuple(
                        dd.table for dd in dep_data)
                    ])
Ejemplo n.º 10
0
def test():
    from hedge.timestep.multirate_ab import \
            TwoRateAdamsBashforthMethodBuilder
    from pymbolic import var
    stepper = TwoRateAdamsBashforthMethodBuilder(
            method="Fqsr",
            large_dt=var("dt"),
            substep_count=2,
            order=1)

    mat = numpy.random.randn(2, 2)

    def f2f_rhs(t, yf, ys):
        return fold_constants(expand(mat[0, 0] * yf()))

    def s2f_rhs(t, yf, ys):
        return fold_constants(expand(mat[0, 1] * ys()))

    def f2s_rhs(t, yf, ys):
        return fold_constants(expand(mat[1, 0] * yf()))

    def s2s_rhs(t, yf, ys):
        return fold_constants(expand(mat[1, 1] * ys()))

    z, vars = make_method_matrix(stepper,
            rhss=(f2f_rhs, s2f_rhs, f2s_rhs, s2s_rhs),
            f_size=1, s_size=1)

    from pymbolic import compile
    num_mat_func = compile(z)
    num_mat = num_mat_func(0.1)

    if False:
        from pymbolic import substitute
        num_mat_2 = numpy.array(
                fold_constants(substitute(z, dt=0.1)),
                dtype=numpy.complex128)

    print(la.norm(num_mat - num_mat_2))

    if True:
        for row, ivar in zip(num_mat, vars):
            print("".join("*" if entry else "." for entry in row), ivar)
Ejemplo n.º 11
0
    def __init__(self,
                 op1_subset=full_subset,
                 op2_subset=full_subset,
                 result_subset=full_subset):
        """Construct a subset-able cross product.

        :param op1_subset: The subset of indices of operand 1 to be taken into account.
          Given as a 3-sequence of bools.
        :param op2_subset: The subset of indices of operand 2 to be taken into account.
          Given as a 3-sequence of bools.
        :param result_subset: The subset of indices of the result that are calculated.
          Given as a 3-sequence of bools.
        """
        def subset_indices(subset):
            return [
                i for i, use_component in enumerate(subset) if use_component
            ]

        self.op1_subset = op1_subset
        self.op2_subset = op2_subset
        self.result_subset = result_subset

        import pymbolic
        op1 = pymbolic.var("x")
        op2 = pymbolic.var("y")

        self.functions = []
        self.component_lcjk = []
        for i, use_component in enumerate(result_subset):
            if use_component:
                this_expr = 0
                this_component = []
                for j, j_real in enumerate(subset_indices(op1_subset)):
                    for k, k_real in enumerate(subset_indices(op2_subset)):
                        lc = levi_civita((i, j_real, k_real))
                        if lc != 0:
                            this_expr += lc * op1[j] * op2[k]
                            this_component.append((lc, j, k))
                self.functions.append(
                    pymbolic.compile(this_expr, variables=[op1, op2]))
                self.component_lcjk.append(this_component)
Ejemplo n.º 12
0
    def __init__(self, kernel):
        # a mapping from parameter names to a list of tuples
        # (arg_name, axis_nr, function), where function is a
        # unary function of kernel.arg_dict[arg_name].shape[axis_nr]
        # returning the desired parameter.
        self.param_to_sources = param_to_sources = {}

        param_names = kernel.all_params()

        from loopy.kernel.data import GlobalArg
        from loopy.symbolic import DependencyMapper
        from pymbolic import compile

        dep_map = DependencyMapper()

        from pymbolic import var

        for arg in kernel.args:
            if isinstance(arg, GlobalArg):
                for axis_nr, shape_i in enumerate(arg.shape):
                    deps = dep_map(shape_i)
                    if len(deps) == 1:
                        dep, = deps

                        if dep.name in param_names:
                            from pymbolic.algorithm import solve_affine_equations_for

                            try:
                                # friggin' overkill :)
                                param_expr = solve_affine_equations_for([dep.name], [(shape_i, var("shape_i"))])[
                                    dep.name
                                ]
                            except:
                                # went wrong? oh well
                                pass
                            else:
                                param_func = compile(param_expr, ["shape_i"])
                                param_to_sources.setdefault(dep.name, []).append((arg.name, axis_nr, param_func))
Ejemplo n.º 13
0
    def __init__(self, op1_subset=full_subset, op2_subset=full_subset, result_subset=full_subset):
        """Construct a subset-able cross product.

        :param op1_subset: The subset of indices of operand 1 to be taken into account.
          Given as a 3-sequence of bools.
        :param op2_subset: The subset of indices of operand 2 to be taken into account.
          Given as a 3-sequence of bools.
        :param result_subset: The subset of indices of the result that are calculated.
          Given as a 3-sequence of bools.
        """
        def subset_indices(subset):
            return [i for i, use_component in enumerate(subset)
                    if use_component]

        self.op1_subset = op1_subset
        self.op2_subset = op2_subset
        self.result_subset = result_subset

        import pymbolic
        op1 = pymbolic.var("x")
        op2 = pymbolic.var("y")

        self.functions = []
        self.component_lcjk = []
        for i, use_component in enumerate(result_subset):
            if use_component:
                this_expr = 0
                this_component = []
                for j, j_real in enumerate(subset_indices(op1_subset)):
                    for k, k_real in enumerate(subset_indices(op2_subset)):
                        lc = levi_civita((i, j_real, k_real))
                        if lc != 0:
                            this_expr += lc*op1.index(j)*op2.index(k)
                            this_component.append((lc, j, k))
                self.functions.append(pymbolic.compile(this_expr,
                    variables=[op1, op2]))
                self.component_lcjk.append(this_component)
Ejemplo n.º 14
0
    def __init__(self, kernel):
        # a mapping from parameter names to a list of tuples
        # (arg_name, axis_nr, function), where function is a
        # unary function of kernel.arg_dict[arg_name].shape[axis_nr]
        # returning the desired parameter.
        self.param_to_sources = param_to_sources = {}

        param_names = kernel.all_params()

        from loopy.kernel.data import GlobalArg
        from loopy.symbolic import DependencyMapper
        from pymbolic import compile
        dep_map = DependencyMapper()

        from pymbolic import var
        for arg in kernel.args:
            if isinstance(arg, GlobalArg):
                for axis_nr, shape_i in enumerate(arg.shape):
                    deps = dep_map(shape_i)
                    if len(deps) == 1:
                        dep, = deps

                        if dep.name in param_names:
                            from pymbolic.algorithm import solve_affine_equations_for
                            try:
                                # friggin' overkill :)
                                param_expr = solve_affine_equations_for(
                                    [dep.name],
                                    [(shape_i, var("shape_i"))])[dep.name]
                            except:
                                # went wrong? oh well
                                pass
                            else:
                                param_func = compile(param_expr, ["shape_i"])
                                param_to_sources.setdefault(
                                    dep.name, []).append(
                                        (arg.name, axis_nr, param_func))
Ejemplo n.º 15
0
def test_elliptic():
    """Test various properties of elliptic operators."""

    from hedge.tools import unit_vector

    def matrix_rep(op):
        h, w = op.shape
        mat = numpy.zeros(op.shape)
        for j in range(w):
            mat[:, j] = op(unit_vector(w, j))
        return mat

    def check_grad_mat():
        import pyublas

        if not pyublas.has_sparse_wrappers():
            return

        grad_mat = op.grad_matrix()

        # print len(discr), grad_mat.nnz, type(grad_mat)
        for i in range(10):
            u = numpy.random.randn(len(discr))

            mat_result = grad_mat * u
            op_result = numpy.hstack(op.grad(u))

            err = la.norm(mat_result - op_result) * la.norm(op_result)
            assert la.norm(mat_result - op_result) * la.norm(op_result) < 1e-5

    def check_matrix_tgt():
        big = num.zeros((20, 20), flavor=num.SparseBuildMatrix)
        small = num.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
        print small
        from hedge._internal import MatrixTarget

        tgt = MatrixTarget(big, 4, 4)
        tgt.begin(small.shape[0], small.shape[1])
        print "YO"
        tgt.add_coefficients(4, 4, small)
        print "DUDE"
        tgt.finalize()
        print big

    import pymbolic

    v_x = pymbolic.var("x")
    truesol = pymbolic.parse("math.sin(x[0]**2*x[1]**2)")
    truesol_c = pymbolic.compile(truesol, variables=["x"])
    rhs = pymbolic.simplify(pymbolic.laplace(truesol, [v_x[0], v_x[1]]))
    rhs_c = pymbolic.compile(rhs, variables=["x", "el"])

    from hedge.mesh import TAG_ALL, TAG_NONE
    from hedge.mesh.generator import make_disk_mesh

    mesh = make_disk_mesh(r=0.5, max_area=0.1, faces=20)
    mesh = mesh.reordered_by("cuthill")

    from hedge.backends import CPURunContext

    rcon = CPURunContext()

    from hedge.tools import EOCRecorder

    eocrec = EOCRecorder()
    for order in [1, 2, 3, 4, 5]:
        for flux in ["ldg", "ip"]:
            from hedge.discretization.local import TriangleDiscretization

            discr = rcon.make_discretization(
                mesh, TriangleDiscretization(order), debug=discr_class.noninteractive_debug_flags()
            )

            from hedge.data import GivenFunction
            from hedge.models.poisson import PoissonOperator

            op = PoissonOperator(
                discr.dimensions,
                dirichlet_tag=TAG_ALL,
                dirichlet_bc=GivenFunction(lambda x, el: truesol_c(x)),
                neumann_tag=TAG_NONE,
            )

            bound_op = op.bind(discr)

            if order <= 3:
                mat = matrix_rep(bound_op)
                sym_err = la.norm(mat - mat.T)
                # print sym_err
                assert sym_err < 1e-12
                # check_grad_mat()

            from hedge.iterative import parallel_cg

            truesol_v = discr.interpolate_volume_function(lambda x, el: truesol_c(x))
            sol_v = -parallel_cg(
                rcon,
                -bound_op,
                bound_op.prepare_rhs(discr.interpolate_volume_function(rhs_c)),
                tol=1e-10,
                max_iterations=40000,
            )

            eocrec.add_data_point(order, discr.norm(sol_v - truesol_v))

    # print eocrec.pretty_print()
    assert eocrec.estimate_order_of_convergence()[0, 1] > 8
Ejemplo n.º 16
0
def newton_interpolation_function(x, y):
    return pymbolic.compile(newton_interpolation_polynomial(x, y), ["x"])
Ejemplo n.º 17
0
def test_elliptic():
    """Test various properties of elliptic operators."""

    from hedge.tools import unit_vector

    def matrix_rep(op):
        h, w = op.shape
        mat = numpy.zeros(op.shape)
        for j in range(w):
            mat[:, j] = op(unit_vector(w, j))
        return mat

    def check_grad_mat():
        import pyublas
        if not pyublas.has_sparse_wrappers():
            return

        grad_mat = op.grad_matrix()

        #print len(discr), grad_mat.nnz, type(grad_mat)
        for i in range(10):
            u = numpy.random.randn(len(discr))

            mat_result = grad_mat * u
            op_result = numpy.hstack(op.grad(u))

            err = la.norm(mat_result - op_result) * la.norm(op_result)
            assert err < 1e-5

    def check_matrix_tgt():
        big = numpy.zeros((20, 20), flavor=numpy.SparseBuildMatrix)
        small = numpy.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
        print small
        from hedge._internal import MatrixTarget
        tgt = MatrixTarget(big, 4, 4)
        tgt.begin(small.shape[0], small.shape[1])
        print "YO"
        tgt.add_coefficients(4, 4, small)
        print "DUDE"
        tgt.finalize()
        print big

    import pymbolic
    v_x = pymbolic.var("x")
    truesol = pymbolic.parse("math.sin(x[0]**2*x[1]**2)")
    truesol_c = pymbolic.compile(truesol, variables=["x"])

    def laplace(expression, variables):
        return sum(
            pymbolic.diff(pymbolic.diff(expression, var), var)
            for var in variables)

    rhs = laplace(truesol, [v_x[0], v_x[1]])
    rhs_c = pymbolic.compile(rhs, variables=["x", "el"])

    from hedge.mesh import TAG_ALL, TAG_NONE
    from hedge.mesh.generator import make_disk_mesh
    mesh = make_disk_mesh(r=0.5, max_area=0.1, faces=20)
    mesh = mesh.reordered_by("cuthill")

    from hedge.backends import CPURunContext
    rcon = CPURunContext()

    from hedge.tools import EOCRecorder
    eocrec = EOCRecorder()
    for order in [1, 2, 3, 4, 5]:
        for flux in ["ldg", "ip"]:
            from hedge.discretization.local import TriangleDiscretization
            discr = rcon.make_discretization(
                mesh,
                TriangleDiscretization(order),
                debug=discr_class.noninteractive_debug_flags())

            from hedge.data import GivenFunction
            from hedge.models.poisson import PoissonOperator
            op = PoissonOperator(
                discr.dimensions,
                dirichlet_tag=TAG_ALL,
                dirichlet_bc=GivenFunction(lambda x, el: truesol_c(x)),
                neumann_tag=TAG_NONE)

            bound_op = op.bind(discr)

            if order <= 3:
                mat = matrix_rep(bound_op)
                sym_err = la.norm(mat - mat.T)
                #print sym_err
                assert sym_err < 1e-12
                #check_grad_mat()

            from hedge.iterative import parallel_cg
            truesol_v = discr.interpolate_volume_function(
                lambda x, el: truesol_c(x))
            sol_v = -parallel_cg(rcon,
                                 -bound_op,
                                 bound_op.prepare_rhs(
                                     discr.interpolate_volume_function(rhs_c)),
                                 tol=1e-10,
                                 max_iterations=40000)

            eocrec.add_data_point(order, discr.norm(sol_v - truesol_v))

    #print eocrec.pretty_print()
    assert eocrec.estimate_order_of_convergence()[0, 1] > 8