Beispiel #1
0
    def __init__(self,
                 nodes,
                 weights,
                 position=None,
                 factor=1,
                 mean=None,
                 cov=None,
                 dirs=None,
                 types=None):
        """Create a quadrature object

        Args:
            nodes: The nodes of the quadrature.
            weights: The weights of the quadrature, in the basis.

        Returns:
            True if successful, False otherwise.

        Note:
            Do not include the  parameter in the Args section.

        """

        #  FIXME: This requires same number of points in each direction
        self.nodes = np.asarray(nodes, float)
        self.weights = np.asarray(weights, float)

        dim = len(self.nodes)
        self.position = position if position is not None else \
            hm.Position(dim=dim, mean=mean, cov=cov, dirs=dirs, types=types)

        # Factor used for hermite transform, discretize
        self.factor = hm.Function(factor, dirs=self.position.dirs)
        self.factor.sym = self.factor.sym.expand()
        self.do_fourier = [int(t == "fourier") for t in self.position.types]
Beispiel #2
0
    def discretize_op(self, op, degree, sparse=None, index_set="triangle"):

        if not isinstance(op, hm.Operator):
            op = hm.Operator(op, dirs=self.position.dirs)

        if self.factor != hm.Function(1, dirs=self.position.dirs):
            op = op.map(self.factor)

        if not op.dirs == self.position.dirs:
            raise ValueError("Invalid argument: directions don't match")
        splitop = op.split()
        sparse = hm.settings['sparse'] if sparse is None else sparse

        if splitop == {}:
            return self.varf(0, degree, sparse=sparse, index_set=index_set)

        varf_operator = 0
        for m, coeff in splitop.items():
            enum_dirs = enumerate(self.position.dirs)
            d_vector = sum([[d] * m[i] for i, d in enum_dirs], [])
            varf_part = self.varfd(coeff,
                                   degree,
                                   d_vector,
                                   sparse=sparse,
                                   index_set=index_set)
            varf_operator = varf_operator + varf_part
        return varf_operator
Beispiel #3
0
    def transform(self,
                  function,
                  degree,
                  index_set="triangle",
                  significant=0,
                  tensorize=None):

        if not isinstance(function, np.ndarray):
            function = hm.Function(function, dirs=self.position.dirs)
            function = self.discretize(function)

        factor = self.discretize(self.factor)
        mapped = function / (1e-300 * (factor == 0) + factor)

        coeffs = core.transform(degree,
                                mapped,
                                self.nodes,
                                self.weights,
                                forward=True,
                                do_fourier=self.do_fourier,
                                index_set=index_set)

        return hm.Series(coeffs,
                         self.position,
                         factor=self.factor,
                         index_set=index_set,
                         significant=significant)
Beispiel #4
0
 def tensorize(args):
     if not len(args) > 0 or \
        not isinstance(args[0], Quad):
         raise ValueError("Invalid argument(s)!")
     position = hm.Position.tensorize([a.position for a in args])
     nodes, weights = [0] * len(position.dirs), [0] * len(position.dirs)
     factor = sym.Integer(1)
     for a in args:
         if not isinstance(a, Quad):
             raise ValueError("Invalid argument!")
         factor *= a.factor.sym
         for i, d in enumerate(a.position.dirs):
             nodes[position.dirs.index(d)] = a.nodes[i]
             weights[position.dirs.index(d)] = a.weights[i]
     factor = hm.Function(factor, dirs=position.dirs)
     return Quad(nodes, weights, position, factor)
Beispiel #5
0
    def streamlines(self, fx, fy, factor=None, ax=None, **kwargs):
        if not self.position.is_diag or \
           not isinstance(fx, type(fy)) or \
           self.position.dim != 2:
            raise ValueError("Invalid argument(s)!")

        show_plt = ax is None
        if show_plt:
            import matplotlib.pyplot as plt
            ax = plt.subplots(1)[1]

        if isinstance(fx, sym.Basic):
            fx = hm.Function(fx, dirs=self.position.dirs)
            fy = hm.Function(fy, dirs=self.position.dirs)

        if isinstance(fx, hm.Function):
            if factor is not None:
                raise ValueError("Invalid argument!")
            fx, fy = self.discretize(fx), self.discretize(fy)

        elif isinstance(fx, hm.Series):

            if factor is None:
                sx, sy = self.eval(fx), self.eval(fy)

            elif not isinstance(factor, np.ndarray):
                factor = hm.Function(factor, dirs=self.position.dirs)
                factor = self.discretize(factor)
                sx, sy = self.eval(fx) * factor, self.eval(fy) * factor

        else:
            raise TypeError("Unsupported type: " + str(type(fx)))

        n_nodes = []
        r_nodes = []
        for i in range(self.position.dim):
            direction = hm.Function.xyz[self.position.dirs[i]]
            n_nodes.append(len(self.nodes[i]))
            r_nodes.append(self.project(i).discretize(direction))
        sx, sy = sx.reshape(*n_nodes).T, sy.reshape(*n_nodes).T
        # magnitude = sx**2 + sy**2
        x, y = r_nodes[0], r_nodes[1]

        # See https://github.com/matplotlib/matplotlib/issues/9269
        def calc_psi2d(x, y, fx, fy):  # solenoidal flows
            # psi by integrating dpsi = -fy*dx + fx*dy, psi[0,0]=0
            ny, nx = fx.shape
            psi = np.zeros((ny, nx))
            for jx in range(1, nx):
                psi[0, jx] = psi[0, jx - 1] - fy[0, jx] * (x[jx] - x[jx - 1])
            for jy in range(1, ny):
                psi[jy, :] = psi[jy - 1, :] + fx[jy, :] * (y[jy] - y[jy - 1])
            return psi

        psi = calc_psi2d(x, y, sx, sy)
        _min, _max, thresh = np.min(psi), np.max(psi), .1
        if abs(_min) < thresh * (_max - _min):
            _min = thresh * (_max - _min)
        if abs(_max) < thresh * (_max - _min):
            _max = -thresh * (_max - _min)
        levels = np.linspace(_min, _max, 10)
        streams = ax.contour(x, y, psi, levels=levels, **kwargs)

        # ax.quiver(x, y, sx, sy)
        # streams = ax.streamplot(r_nodes[0], r_nodes[1], sx, sy,
        #                         color=magnitude, density=0.6, cmap='autumn')

        return plt.show() if show_plt else streams
Beispiel #6
0
    def plot(self,
             arg,
             factor=None,
             ax=None,
             contours=0,
             bounds=False,
             title=None,
             **kwargs):

        if not self.position.is_diag:
            raise ValueError("Invalid argument: position must be diag!")

        show_plt = ax is None
        if show_plt:
            import matplotlib.pyplot as plt
            ax = plt.subplots(1)[1]

        if isinstance(arg, sym.Basic):
            arg = hm.Function(arg, dirs=self.position.dirs)

        if isinstance(arg, hm.Function):
            if factor is not None:
                raise ValueError("Invalid argument!")
            solution = self.discretize(arg)

        elif isinstance(arg, np.ndarray):
            solution = arg

        elif isinstance(arg, hm.Series):

            series = arg

            # Fix me maybe?
            if series.coeffs.dtype == np.dtype('complex128'):
                series.coeffs = np.real(series.coeffs).copy(order='C')

            if factor is None:
                solution = self.eval(series)

            elif not isinstance(factor, np.ndarray):
                factor = hm.Function(factor, dirs=self.position.dirs)
                factor = self.discretize(factor)
                solution = self.eval(series) * factor

            if bounds:

                degree_bounds = series.degree
                bounds, adim_width = [], np.sqrt(2) * np.sqrt(
                    2 * degree_bounds + 1)
                for i in range(series.position.dim):
                    mean = series.position.mean[i]
                    cov = series.position.cov[i][i]
                    bounds.append([
                        mean - adim_width * np.sqrt(cov),
                        mean + adim_width * np.sqrt(cov)
                    ])

                if self.position.dim >= 1:
                    ax.axvline(x=bounds[0][0])
                    ax.axvline(x=bounds[0][1])
                if self.position.dim == 2:
                    ax.axhline(y=bounds[1][0])
                    ax.axhline(y=bounds[1][1])

        else:
            raise TypeError("Unsupported type: " + str(type(arg)))

        n_nodes = []
        r_nodes = []
        for i, d in enumerate(self.position.dirs):
            direction = hm.Function.xyz[d]
            n_nodes.append(len(self.nodes[i]))
            r_nodes.append(self.project(d).discretize(direction))
        solution = solution.reshape(*n_nodes).T

        if self.position.dim == 1:
            plot = ax.plot(*r_nodes, solution, **kwargs)
        elif self.position.dim == 2:
            plot = ax.contourf(*r_nodes, solution, 100, **kwargs)
            for c in plot.collections:
                c.set_edgecolor("face")
            if contours > 0:
                ax.contour(*r_nodes, solution, levels=contours, colors='k')

        _min, _max = np.min(solution), np.max(solution)

        if title is None:
            title = "Min: {:.3f}, Max: {:.3f}".format(_min, _max)
        ax.set_title(title)

        if show_plt:
            if self.position.dim == 2:
                plt.colorbar(plot, ax=ax)
            plt.show()
        else:
            return plot
Beispiel #7
0
 def discretize(self, f):
     if not isinstance(f, hm.Function):
         f = hm.Function(f, dirs=self.position.dirs)
     function = core.discretize(f.ccode(), self.nodes, self.position.mean,
                                self.position.factor)
     return function
Beispiel #8
0
            def wrapper(*args, **kwargs):
                tensorize = kwargs['tensorize'] if 'tensorize' in kwargs \
                        else None
                do_tensorize = hm.settings['tensorize'] if \
                    tensorize is None else tensorize

                # <- Fix bug with integrate(series)
                if isinstance(args[arg_num], hm.Series):
                    do_tensorize = False
                # ->

                if not do_tensorize:
                    return func(*args, **kwargs)

                quad, function = args[0], args[arg_num]
                if not quad.position.is_diag or \
                        isinstance(function, np.ndarray):
                    return func(*args, **kwargs)

                results = []
                if not isinstance(function, hm.Function):
                    function = hm.Function(function, dirs=quad.position.dirs)

                for add in function.split(legacy=False):
                    multiplicator = add[frozenset()]
                    del add[frozenset()]

                    factor_split = quad.factor.split(legacy=False)
                    if len(factor_split) != 1:
                        raise ValueError("Tensorization not possible!")
                    finest_division = lib.finest_common(
                        set(add), set(factor_split[0]))
                    new_add = {
                        sub: hm.Function('1')
                        for sub in finest_division
                    }
                    for dirs, term in add.items():
                        for s in new_add:
                            if dirs.issubset(s):
                                f = hm.Function(new_add[s].sym * term.sym,
                                                dirs=list(s))
                                new_add[s] = f
                    func_dirs = {}
                    for dirs, term in new_add.items():
                        new_args = list(args).copy()
                        new_args[0] = quad.project(list(dirs))
                        new_args[arg_num] = term
                        func_dirs[dirs] = func(*new_args, **kwargs)

                    if hm.settings['debug']:
                        print("Tensorizing results")

                    kwargs_func = {'sparse': kwargs['sparse']} \
                        if 'sparse' in kwargs else {}
                    t = type(list(func_dirs.values())[0])
                    if t is hm.Varf or t is hm.Series:
                        values = list(func_dirs.values())
                        tensorized = t.tensorize(values, **kwargs_func)
                    else:
                        tensorized = core.tensorize(func_dirs, **kwargs_func)
                    results.append(tensorized * float(multiplicator.sym))
                return sum(results[1:], results[0])