Ejemplo n.º 1
0
    def _build_mu(self, D, order):
        r"""Build the list containing the lists :math:`\mu_i` where each
        :math:`\mu_i` contains the :math:`D`-tuples in reverse lexicographical order.

        :param D: The dimension :math:`D` of the wavepacket.
        :param order: The maximal :math:`l_1` norm of any basis index :math:`\underline{k}`.
        """
        return [list(lattice_points_norm(D, i)) for i in range(order + 1)]
    def _build_mu(self, D, order):
        r"""Build the list containing the lists :math:`\mu_i` where each
        :math:`\mu_i` contains the :math:`D`-tuples in reverse lexicographical order.

        :param D: The dimension :math:`D` of the wavepacket.
        :param order: The maximal :math:`l_1` norm of any basis index :math:`\underline{k}`.
        """
        return [list(lattice_points_norm(D, i)) for i in range(order + 1)]
    def overlap(self, D, Pi, eps):
        r"""Compute the overlap matrix:

        .. math::
            \mathbf{K}_{r,c} := \langle \psi_{\underline{e_r}}[\Pi] | \phi_{\underline{e_c}}[\Pi] \rangle

        :param D: The dimension :math:`D`.
        :param Pi: The parameter set :math:`\Pi`.
        :param eps: The semiclassical scaling parameter :math:`\varepsilon`.
        """
        ED = list(lattice_points_norm(D, 1))

        BS = SimplexShape(D, 1)

        WPo = HagedornWavepacket(D, 1, eps)
        WPo.set_parameters(Pi)
        WPo.set_basis_shapes([BS])

        WPn = HagedornWavepacketPsi(D, 1, eps)
        WPn.set_parameters(Pi)
        WPn.set_basis_shapes([BS])

        TPG = TensorProductQR(D * [GaussHermiteQR(2)])
        DHQ = DirectHomogeneousQuadrature(TPG)
        G = DHQ.transform_nodes(Pi, eps)
        W = TPG.get_weights()

        phi = WPo.evaluate_basis_at(G, component=0)
        psi = WPn.evaluate_basis_at(G, component=0)

        K = zeros((D, D), dtype=complexfloating)

        for r, er in enumerate(ED):
            for c, ec in enumerate(ED):
                K[r, c] = eps**D * sum(
                    conjugate(psi[BS[er], :]) * phi[BS[ec], :] * W)

        return K
Ejemplo n.º 4
0
    def overlap(self, D, Pi, eps):
        r"""Compute the overlap matrix:

        .. math::
            \mathbf{K}_{r,c} := \langle \psi_{\underline{e_r}}[\Pi] | \phi_{\underline{e_c}}[\Pi] \rangle

        :param D: The dimension :math:`D`.
        :param Pi: The parameter set :math:`\Pi`.
        :param eps: The semiclassical scaling parameter :math:`\varepsilon`.
        """
        ED = list(lattice_points_norm(D, 1))

        BS = SimplexShape(D, 1)

        WPo = HagedornWavepacket(D, 1, eps)
        WPo.set_parameters(Pi)
        WPo.set_basis_shapes([BS])

        WPn = HagedornWavepacketPsi(D, 1, eps)
        WPn.set_parameters(Pi)
        WPn.set_basis_shapes([BS])

        TPG = TensorProductQR(D * [GaussHermiteQR(2)])
        DHQ = DirectHomogeneousQuadrature(TPG)
        G = DHQ.transform_nodes(Pi, eps)
        W = TPG.get_weights()

        phi = WPo.evaluate_basis_at(G, component=0)
        psi = WPn.evaluate_basis_at(G, component=0)

        K = zeros((D, D), dtype=complexfloating)

        for r, er in enumerate(ED):
            for c, ec in enumerate(ED):
                K[r, c] = eps**D * sum(conjugate(psi[BS[er], :]) * phi[BS[ec], :] * W)

        return K
Ejemplo n.º 5
0
    def construct_rule(self, K, tolerance=1e-15):
        r"""Compute the quadrature nodes :math:`\{\gamma_i\}_i` and quadrature
        weights :math:`\{\omega_i\}_i`.

        :param K: The level :math:`K` of the Smolyak construction.
        :param tolerance: Tolerance for dropping identical quadrature nodes.

        .. note:: This is an internal method and there should be no reason
                  to explicitely call it manually.

        .. warning:: This method is very expensive and may take a long time
                     to finish. Also, the quadrature nodes may use large amounts
                     of memory depending on the dimension and level parameters.
        """
        # Check for valid level parameter
        if not K >= 1:
            raise ValueError("Smolyak level has to be 1 at least.")
        if K > max(self._rules.keys()):
            raise ValueError("Not enough quadrature rules to build Smolyak grid of level %d" % K)

        self._level = K
        D = self._dimension

        allnodes = []
        allweights = []
        factors = []

        # Index Set
        for q in range(max(0, K - D), K):
            S = lattice_points_norm(D, q)
            for j, s in enumerate(S):
                # Only use non-negative nodes for the construction.
                # The quadrature nodes \gamma.
                rules = [self._rules[si + 1] for si in s]
                nodes = [rule.get_nodes() for rule in rules]
                indices = [where(n >= 0) for n in nodes]
                nodes = meshgrid_nd([n[i] for n, i in zip(nodes, indices)])
                nodes = vstack([node.reshape(-1) for node in nodes])
                # The quadrature weights \omega.
                weights = [rule.get_weights() for rule in rules]
                weights = meshgrid_nd([w[i] for w, i in zip(weights, indices)])
                weights = reduce(multiply, weights)
                allnodes.append(nodes)
                allweights.append(weights.reshape(-1))
                factors.append((-1)**(K - 1 - q) * binom(D - 1, K - 1 - q))

        # Sort
        allnodes = hstack(allnodes).reshape(D, -1)
        allweights = hstack([f * w for f, w in zip(factors, allweights)]).reshape(1, -1)

        I = lexsort(map(squeeze, vsplit(allnodes, D))[::-1])

        allnodes = allnodes[:, I].reshape(D, -1)
        allweights = allweights[:, I].reshape(1, -1)

        # Remove duplicates
        last = 0
        I = [last]

        no = norm(allnodes[:, :-1] - allnodes[:, 1:], axis=0)

        for col in range(1, allnodes.shape[1]):
            if no[col - 1] <= tolerance:
                allweights[0, last] += allweights[0, col]
                allweights[0, col] = 0
            else:
                last = col
                I.append(last)

        allnodes = allnodes[:, I]
        allweights = allweights[:, I]

        # Mirror points to all other hyperoctants
        for d in range(D):
            indices = abs(allnodes[d, :]) >= tolerance
            mirrorn = allnodes[:, indices]
            mirrorn[d, :] *= -1.0
            mirrorw = allweights[:, indices]
            allnodes = hstack([allnodes, mirrorn]).reshape(D, -1)
            allweights = hstack([allweights, mirrorw]).reshape(1, -1)

        self._nodes = allnodes
        self._weights = allweights
        self._number_nodes = allnodes.shape[1]