Пример #1
0
    def allComponents(self, N):
        result = 0

        # First term
        for K in range(N - 1, self.collapse + 1):
            Cd = self.diff(self.Cs[0], order=K)
            Md = spatial_diff(self.M, order=K - N + 1)
            tmp = np.tensordot(Cd,
                               Md,
                               axes=(tuple(range(1, K - N + 2)) + (0, ),
                                     tuple(range(0, K - N + 2))))
            tmp = symmetrize(tmp, list(range(len(tmp.shape))))

            result = result + 2 * binomial(K, N - 1) * tmp

        # Second summand
        for K in range(N, self.collapse + 1):
            for J in range(N + 1, K + 2):
                Cd = self.diff(self.Cs[0], order=K)
                Md = spatial_diff(self.M, order=K - J + 1)
                tmp = np.tensordot(Cd,
                                   Md,
                                   axes=(tuple(range(1, K - J + 2)) + (0, ),
                                         tuple(range(0, K - J + 2))))
                tmp = symmetrize(tmp, list(range(len(tmp.shape))))
                tmp = spatial_diff(tmp, order=J - N)
                for i in range(J - N + 1):
                    tmp = tmp.trace(0, len(tmp.shape) - 1)

                result = result + (-1)**J * binomial(K, J - 1) * binomial(
                    J, N) * tmp

        return result
Пример #2
0
    def allComponents(self, N):
        V = np.tensordot(self.E, self.p, axes=(1, 1)) - np.tensordot(
            self.F, spatial_diff(self.p, order=1), axes=((2, 0), (1, 1)))
        result = (N + 2) * (self.degP - 1) * np.tensordot(
            self.Cs[N + 2], V, axes=(0, 0))

        # First M term
        tmp = np.tensordot(self.Cs[N + 1],
                           self.diff(self.M, order=0).swapaxes(1, 2),
                           axes=(0, 0))
        result -= (N + 1) * symmetrize(tmp, list(range(N + 1)))

        # The other M terms
        tmp = self.sumCoefficientDerivativeContraction(self.M,
                                                       N=N + 1,
                                                       freeIndices=0)
        if tmp is not None:
            result -= tmp

        # Multiply everything we have so far by (N+1)
        result = (N + 1) * result

        # The sum with the index swapping
        Cd = self.diff(self.Cs[N], order=1)
        for K in range(0, N + 1):
            result -= Cd.swapaxes(K, len(self.Cs.shape) - 2)

        # Last term
        result += 2 * spatial_diff(self.diff(self.Cs[N], order=2),
                                   order=1).trace(0, N + 2)

        return result
Пример #3
0
    def allComponents(self):
        # First term
        V = np.tensordot(self.p, self.E, axes=(1, 1)) - np.tensordot(
            spatial_diff(expr=self.p, order=1), self.F, axes=((0, 2), (2, 1)))
        result = 6 * (self.degP - 1) * np.tensordot(self.Cs[3], V, axes=(0, 1))

        # Second term. In the M_: term we swap B2 and mu
        result -= 4 * symmetrize(
            np.tensordot(self.Cs[2],
                         self.diff(expr=self.M, order=0).swapaxes(1, 2),
                         axes=(0, 0)), [0, 1])

        # Third to fifth term
        tmp = self.sumCoefficientDerivativeContraction(self.M, N=2)
        if tmp is not None:
            result -= 2 * tmp

        # Sixth summand. Need to swap the first and second axes to get into the B1 B2 order
        result -= self.diff(expr=self.Cs[1], order=1).swapaxes(0, 1)

        # Last summand
        tmp = self.sumCoefficientDerivativeTrace(N=1,
                                                 freeIndices=1,
                                                 combinatorial='K+1',
                                                 alternatingSign=True)
        if tmp is not None:
            result -= tmp

        return result
Пример #4
0
    def allComponents(self, N):
        # The C_A term
        tmpA = self.sumCoefficientDerivativeContraction(
            self.M, N=1, freeIndices=N, combinatorial='binomial(K+N,K)')
        if tmpA is not None:
            tmpA = symmetrize(
                tmpA, list(range(len(tmpA.shape) - N, len(tmpA.shape))))

        # The C term
        tmpB = self.sumCoefficientDerivativeTrace(
            N=0,
            freeIndices=N + 1,
            combinatorial='binomial(K+N-1,K)',
            alternatingSign=True)
        if tmpB is not None:
            tmpB = (-1)**N * tmpB

        # Return the result
        if tmpA is not None and tmpB is not None:
            return tmpA + tmpB
        elif tmpA is not None:
            return tmpA
        elif tmpB is not None:
            return tmpB
        else:
            return np.array([0])
Пример #5
0
    def allComponents(self, N):
        Cd = self.diff(expr=self.Cs[N], order=2)

        # Contract the coefficient with F
        result = np.tensordot(Cd, self.F, axes=(len(Cd.shape)-3,0))

        # Symmetrize in alpha, beta, gamma
        x = len(result.shape)
        return symmetrize(result, [x-4, x-3, x-1])
Пример #6
0
    def allComponents(self, N):
        result = - np.tensordot(self.Cs[N], np.eye(3), axes=0)

        # Subtract the second term
        tmp = np.tensordot(self.Cs[N], self.diff(self.F, order=0).transpose(0,3,2,1), axes=(0,0))
        tmp = symmetrize(tmp, list(range(N)))
        result -= N * tmp

        # E terms
        tmp = self.sumCoefficientDerivativeContraction(self.E, N=N, freeIndices=1, combinatorial='K+1')
        if tmp is not None:
            result += tmp
        
        # F terms
        tmp = self.sumCoefficientDerivativeContraction(self.F.swapaxes(1,2))
        if tmp is not None:
            result -= tmp
        
        return result
Пример #7
0
    def allComponents(self, N):
        # E terms
        result = 0
        tmp = self.coefficientDerivativeContraction(self.E,
                                                    N=N,
                                                    derivOrder=0,
                                                    freeIndices=2)
        if tmp is not None:
            result = tmp

        # F terms
        tmp = self.sumCoefficientDerivativeContraction(self.F.swapaxes(1, 2),
                                                       N=N,
                                                       freeIndices=1,
                                                       combinatorial='K+1')
        if tmp is not None:
            tmp = symmetrize(tmp, [len(tmp.shape) - 3, len(tmp.shape) - 2])
            result -= tmp

        return result
Пример #8
0
    def allComponents(self):
        result = 0

        # Third summand
        for K in range(2, self.collapse + 1):
            for J in range(2, K + 1):
                Cd = self.diff(self.Cs[0], order=K)
                Md = spatial_diff(self.M, order=K - J)
                tmp = np.tensordot(Cd,
                                   Md,
                                   axes=(tuple(range(1, K - J + 1)) + (0, ),
                                         tuple(range(0, K - J + 1))))
                tmp = symmetrize(tmp, list(range(len(tmp.shape))))
                tmp = spatial_diff(tmp, order=J + 1)
                for i in range(J + 1):
                    tmp = tmp.trace(0, len(tmp.shape) - 1)

                result = result + (-1)**J * binomial(K, J) * (J - 1) * tmp

        return result
Пример #9
0
    def symmetrizeDerivatives(self, contraction, tensor):
        # Import the symmetrization method
        from prime.utils import symmetrize

        # Unfold
        Ks, Phis = contraction

        # Prepare the result
        from copy import deepcopy
        result = deepcopy(tensor)

        offset = len(Ks)
        for i, Phi in enumerate(Phis):
            # If there are more than one derivative indices
            if Phi.derivs > 1:
                indices = list(range(offset + 1, offset + 1 + Phi.derivs))
                result = symmetrize(result, indices)

            offset = offset + 1 + Phi.derivs

        return result
Пример #10
0
    def symmetrizeBlocks(self, contraction, tensor):
        # Import the symmetrization method
        from prime.utils import symmetrize

        # Unfold
        Ks, Phis = contraction

        # Prepare the result
        from copy import deepcopy
        result = deepcopy(tensor)

        # First the exchange symmetries in the velocity indices
        if len(Ks) > 1:
            result = symmetrize(result, list(range(len(Ks))))

        # Now the Phi part
        if len(Phis) > 1:
            for i, Phi in enumerate(Phis):
                for j in range(i + 1, len(Phis)):
                    # If the number of derivative indices is different move to the next one
                    if Phi.derivs != Phis[j].derivs: continue

                    # Symmetrize in the i-th and j-th block
                    shape = tuple(range(len(Ks)))
                    for k, P in enumerate(Phis):
                        if k == i:
                            shape = shape + Phis[
                                j].getAllIndicesAfterContraction(
                                    offset=Phis[j].new_offset)
                        elif k == j:
                            shape = shape + Phi.getAllIndicesAfterContraction(
                                offset=Phi.new_offset)
                        else:
                            shape = shape + P.getAllIndicesAfterContraction(
                                offset=P.new_offset)

                    result = (result + result.transpose(shape)) / 2

        return result
Пример #11
0
    def allComponents(self):
        # First summand. It is transposed into the shape (B,mu,nu)
        result = 2 * (self.degP-1) * np.tensordot(np.tensordot(self.p, self.F, axes=(1, 1)), self.Cs[2], axes=(1, 0)) \
                    .transpose((2,0,1))

        # Second summand
        tmp = self.sumCoefficientDerivativeContraction(self.M,
                                                       N=1,
                                                       freeIndices=1,
                                                       combinatorial='K+1')
        if tmp is not None:
            result += tmp

        # Third summand
        tmp = self.sumCoefficientDerivativeTrace(N=1,
                                                 freeIndices=2,
                                                 combinatorial='(K+2)*(K+1)/2',
                                                 alternatingSign=True)
        if tmp is not None:
            result -= tmp

        return symmetrize(result, [1, 2])
Пример #12
0
    def allComponents(self, N):
        result = None

        # First term
        tmp = self.sumCoefficientDerivativeContraction(
            self.E, N=1, freeIndices=N, combinatorial='binomial(K+N,K)')
        if tmp is not None:
            result = tmp

        # Second term
        tmp = self.sumCoefficientDerivativeContraction(
            self.F.swapaxes(1, 2),
            N=1,
            freeIndices=N - 1,
            combinatorial='binomial(K+N-1,K)')
        if tmp is not None:
            # Symmetrize in the N free indices
            tmp = symmetrize(tmp, list(range(1, N + 1)))

            if result is None: result = -tmp
            else: result -= tmp

        return result
Пример #13
0
    def __init__(self, intertwiners, order=3):
        self.intertwiners = intertwiners
        self.parametrization = intertwiners.parametrization
        self.order = order # TODO: check the order of the intertwiner

        # Get the constant part and reshape
        constInts = self.intertwiners.constant()
        constInts = [i.reshape((int(np.prod(i.shape[0:-1])), i.shape[-1])) for i in constInts]
        constIntsIdx = self.intertwiners.indices

        # TODO:
        #   So far, this method is more or less a heuristics that
        #   works for almost all the parametrizations but it is possible
        #   that strange examples exist where this is not the case.
        #   Then the exception will be raised. Try to come up with a
        #   more general way to solve this.

        # Calculate the indices of the inverse intertwiners
        constInvsIdx = [[(id[0], -id[1]) for id in idx] for idx in self.intertwiners.indices]
        for i in range(len(constInvsIdx)):
            constInvsIdx[i].insert(0, constInvsIdx[i].pop(-1))
        constInvsShapes = [tuple([id[0] for id in idx]) for idx in constInvsIdx]
        # For now, sympy does not support rank defficient matrices, so we cannot use it here.
        # There is already a fix merged into master, so it should be usable quite soon...
        #constInvs = [ np.reshape(np.array(sympy.Matrix(int).pinv()), shape) for int, shape in zip(constInts, constInvsShapes) ]
        constInvs = [np.reshape(np.linalg.pinv(int.astype(np.float64)), shape) for int, shape in zip(constInts, constInvsShapes)]

        # Check the parametrization
        reshapedInvs = [I.reshape((I.shape[0], int(np.prod(I.shape[1:])))) for I in constInvs]
        d = np.zeros((len(self.parametrization.dofs), len(self.parametrization.dofs)))
        for A,B in zip(constInts, reshapedInvs):
            d = d + np.matmul(B.astype(np.float64),A.astype(np.float64))
        valid = np.all((d - np.identity(len(self.parametrization.dofs))) < 1e-10)

        if not valid:
            raise Exception("The given parametrization is invalid. The inverted intertwiners and the constant ones do not contract to the identity.")

        # Import the method for symmetrization
        from prime.utils import symmetrize

        # Get the orders for the
        cacheConsts = [ self.intertwiners.order(o) for o in range(order) ]
        cacheInvs   = [ constInvs ]

        # Iteratively construct the inverse
        components = constInvs
        for N in range(1, order):
            # Take the first one
            tmp = sum([np.tensordot(constInvs[i], cacheConsts[N][i],
                    axes=(
                        tuple(range(1,len(constInvs[i].shape))),
                        tuple(range(len(constInvs[i].shape)-1))
                    )) for i in range(len(constInvs))])
            tmp = [-np.tensordot(tmp, constInvs[j], axes=((1,), (0,))) for j in range(len(constInvs))]

            # Add the others on top
            for k in range(1,N):
                tmp2 = sum([np.tensordot(cacheInvs[k][i], cacheConsts[N-k][i],
                    axes=(
                        tuple(range(1,len(constInvs[i].shape))),
                        tuple(range(len(constInvs[i].shape)-1))
                    )) for i in range(len(constInvs))])
                tmp2 = [np.tensordot(tmp2, constInvs[j], axes=((k+1,), (0,))) for j in range(len(constInvs))]
                tmp2 = [symmetrize(t, list(range(1, k+1)) + list(range(1, N-k+1))) for t in tmp2]

                tmp = [x-y for x,y in zip(tmp, tmp2)]

            # Transpose
            tmp = [t.transpose((0,) + tuple(range(N+1, len(t.shape))) + tuple(range(1,N+1))) for t in tmp]

            # Add to the list
            cacheInvs.append(tmp)

            # Contract with phis
            r = tmp
            for i in range(N):
                r = [np.dot(t, self.parametrization.dofs) for t in r]

            # Add to the components
            components = [x + y for x, y in zip(components, r)]

        # Set the result
        self.components = components
        self.indices = constInvsIdx