示例#1
0
def setup_d_transform(b, J_dense):
    """

    """

    # We know how to efficiently compute d functions in the real basis using
    # Pinchon-Hoggans approach (d_real = J X(beta) J), but we want them in the
    # basis of complex centered spherical harmonics Y^{-l}, ..., Y^{l}.
    # These matrices perform that change of basis
    ##C2R = [cc2rcph(l) for l in range(b)]
    #C2R = [get_sh_change_of_basis(l,
    #                              frm=('complex', 'seismology', 'centered'),
    #                              to=('real', 'quantum', 'centered'))
    #       for l in range(b)]
    C2R = [
        change_of_basis_matrix(l,
                               frm=('complex', 'seismology', 'centered', 'cs'),
                               to=('real', 'quantum', 'centered', 'cs'))
        for l in range(b)
    ]

    # Compute array of beta values as described in SOFT 2.0 documentation.
    beta = np.pi * (2 * np.arange(0, 2 * b) + 1) / (4. * b)

    # Compute d matrices in real basis (fast, stable),
    # then change them to complex basis (where the d-funcs are still real):
    d = [
        np.array([rot_mat(0, bt, 0, l, J_dense[l]) for bt in beta])
        for l in range(b)
    ]
    d = [C2R[l].conj().T.dot(d[l]).dot(C2R[l]).real for l in range(b)]
    #d = [np.array([wignerd_mat(l, b, approx_lim=100000)
    #               for b in beta]).transpose(1, 0, 2)
    #     for l in range(B)]

    # We want the L2 normalized functions:
    d = [d[l] * np.sqrt(l + 0.5) for l in range(len(d))]

    # Construct quadrature weights w
    # NO: this should be separate so that we can use the same d for forward and backward transforms
    """if weight:
        k = np.arange(0, b)
        w = np.array([(2. / b) * np.sin(np.pi * (2. * j + 1.) / (4. * b)) *
                      (np.sum((1. / (2 * k + 1))
                              * np.sin((2 * j + 1) * (2 * k + 1)
                                       * np.pi / (4. * b))))
                      for j in range(2 * b)])
        # In the SOFT source, they talk about the following weights being used for
        # odd-order transforms. Do not understand this, and the weights used above
        # (defined in the SOFT papers) seems to work.
        #w = np.array([(2. / B) *
        #              (np.sum((1. / (2 * k + 1))
        #                      * np.sin((2 * j + 1) * (2 * k + 1)
        #                               * np.pi / (4. * B))))
        #              for j in range(2 * B)])

        # Apply quadrature weights to the wigner d function samples:
        d = [d[l] * w[None, :, None] for l in range(b)]
    """
    return d
def setup_d_transform(b, J_dense):
    """

    """

    # We know how to efficiently compute d functions in the real basis using
    # Pinchon-Hoggans approach (d_real = J X(beta) J), but we want them in the
    # basis of complex centered spherical harmonics Y^{-l}, ..., Y^{l}.
    # These matrices perform that change of basis
    ##C2R = [cc2rcph(l) for l in range(b)]
    #C2R = [get_sh_change_of_basis(l,
    #                              frm=('complex', 'seismology', 'centered'),
    #                              to=('real', 'quantum', 'centered'))
    #       for l in range(b)]
    C2R = [change_of_basis_matrix(l,
                                  frm=('complex', 'seismology', 'centered', 'cs'),
                                  to=('real', 'quantum', 'centered', 'cs'))
           for l in range(b)]

    # Compute array of beta values as described in SOFT 2.0 documentation.
    beta = np.pi * (2 * np.arange(0, 2 * b) + 1) / (4. * b)

    # Compute d matrices in real basis (fast, stable),
    # then change them to complex basis (where the d-funcs are still real):
    d = [np.array([rot_mat(0, bt, 0, l, J_dense[l])
                   for bt in beta])
         for l in range(b)]
    d = [C2R[l].conj().T.dot(d[l]).dot(C2R[l]).real
         for l in range(b)]
    #d = [np.array([wignerd_mat(l, b, approx_lim=100000)
    #               for b in beta]).transpose(1, 0, 2)
    #     for l in range(B)]

    # We want the L2 normalized functions:
    d = [d[l] * np.sqrt(l + 0.5) for l in range(len(d))]

    # Construct quadrature weights w
    # NO: this should be separate so that we can use the same d for forward and backward transforms
    """if weight:
        k = np.arange(0, b)
        w = np.array([(2. / b) * np.sin(np.pi * (2. * j + 1.) / (4. * b)) *
                      (np.sum((1. / (2 * k + 1))
                              * np.sin((2 * j + 1) * (2 * k + 1)
                                       * np.pi / (4. * b))))
                      for j in range(2 * b)])
        # In the SOFT source, they talk about the following weights being used for
        # odd-order transforms. Do not understand this, and the weights used above
        # (defined in the SOFT papers) seems to work.
        #w = np.array([(2. / B) *
        #              (np.sum((1. / (2 * k + 1))
        #                      * np.sin((2 * j + 1) * (2 * k + 1)
        #                               * np.pi / (4. * B))))
        #              for j in range(2 * B)])

        # Apply quadrature weights to the wigner d function samples:
        d = [d[l] * w[None, :, None] for l in range(b)]
    """
    return d
    def __init__(self, L_max, d=None, L2_normalized=True):

        self.L_max = L_max
        self.complex_fft = SO3_FFT_NaiveComplex(L_max=L_max, d=d, L2_normalized=L2_normalized)

        # Compute change of basis function:
        self.c2b = [change_of_basis_matrix(l,
                                           frm=('complex', 'seismology', 'centered', 'cs'),
                                           to=('real', 'quantum', 'centered', 'cs'))
                    for l in range(L_max + 1)]
示例#4
0
    def __init__(self, L_max, d=None, L2_normalized=True):

        self.L_max = L_max
        self.complex_fft = SO3_FFT_NaiveComplex(L_max=L_max,
                                                d=d,
                                                L2_normalized=L2_normalized)

        # Compute change of basis function:
        self.c2b = [
            change_of_basis_matrix(l,
                                   frm=('complex', 'seismology', 'centered',
                                        'cs'),
                                   to=('real', 'quantum', 'centered', 'cs'))
            for l in range(L_max + 1)
        ]
示例#5
0
    def setup_d_transform(b, J_dense, L2_normalized):
        """

        """

        # We know how to efficiently compute d functions in the real basis using
        # Pinchon-Hoggans approach (d_real = J X(beta) J), but we want them in the
        # basis of complex centered spherical harmonics Y^{-l}, ..., Y^{l}.
        # These matrices perform that change of basis
        #C2R = [get_sh_change_of_basis(l,
        #                              frm=('complex', 'seismology', 'centered'),
        #                              to=('real', 'quantum', 'centered'))
        #       for l in range(b)]
        C2R = [
            change_of_basis_matrix(l,
                                   frm=('complex', 'seismology', 'centered',
                                        'cs'),
                                   to=('real', 'quantum', 'centered', 'cs'))
            for l in range(b)
        ]

        # Compute array of beta values as described in SOFT 2.0 documentation.
        beta = np.pi * (2 * np.arange(0, 2 * b) + 1) / (4. * b)

        # Compute d matrices in real basis (fast, stable),
        # then change them to complex basis (where the d-funcs are still real):
        d = [
            np.array([rot_mat(0, bt, 0, l, J_dense[l]) for bt in beta])
            for l in range(b)
        ]
        d = [C2R[l].conj().T.dot(d[l]).dot(C2R[l]).real for l in range(b)]

        if L2_normalized:
            # The Unitary matrix elements have norm:
            # | U^\lambda_mn |^2 = 1/(2l+1)
            # where the 2-norm is defined in terms of normalized Haar measure.
            # So T = sqrt(2l + 1) U are L2-normalized functions
            d = [d[l] * np.sqrt(2 * l + 1) for l in range(len(d))]

        return d
示例#6
0
def make_D_sample_grid(Jd, b=4, l=0, m=0, n=0, D='c'):
    if D == 'c':
        C2R = change_of_basis_matrix(l,
                                     frm=('complex', 'seismology', 'centered',
                                          'cs'),
                                     to=('real', 'quantum', 'centered', 'cs'))

        D = lambda a, b, c: C2R.conj().T.dot(rot_mat(a, b, c, l, Jd[l])).dot(
            C2R)[m + l, n + l]

    elif D == 'r':
        D = lambda a, b, c: rot_mat(a, b, c, l, Jd[l])[m + l, n + l]
    else:
        assert False

    f = np.zeros((2 * b, 2 * b, 2 * b), dtype='complex')

    # We use the L2-normalized Wigner D functions
    #Z = (1. / (2 * np.pi)) * np.sqrt(l + 0.5)
    #Z = 1. / np.pi

    # Normalized wrt normalized Haar measure, as used by S3.integrate()
    #Z = np.sqrt(2 * l + 1)

    Z = 1.

    for j1 in range(f.shape[0]):
        alpha = 2 * np.pi * j1 / (2. * b)
        for k in range(f.shape[1]):
            beta = np.pi * (2 * k + 1) / (4. * b)
            for j2 in range(f.shape[2]):
                gamma = 2 * np.pi * j2 / (2. * b)
                #f[j1, k, j2] = D(alpha, beta, gamma) * (1. / 2. * np.pi) * np.sqrt(l + 0.5)
                #f[j1, k, j2] = (C2R.conj().T.dot(D(alpha, beta, gamma)).dot(C2R))[m + l, n + l]
                #f[j1, k, j2] *= (1. / (2. * np.pi)) * np.sqrt(l + 0.5)

                f[j1, k, j2] = D(alpha, beta, gamma) * Z

    return f
def make_D_sample_grid(Jd, b=4, l=0, m=0, n=0, D='c'):
    if D == 'c':
        C2R = change_of_basis_matrix(l,
                                     frm=('complex', 'seismology', 'centered', 'cs'),
                                     to=('real', 'quantum', 'centered', 'cs'))

        D = lambda a, b, c: C2R.conj().T.dot(rot_mat(a, b, c, l, Jd[l])).dot(C2R)[m + l, n + l]

    elif D == 'r':
        D = lambda a, b, c: rot_mat(a, b, c, l, Jd[l])[m + l, n + l]
    else:
        assert False

    f = np.zeros((2 * b, 2 * b, 2 * b), dtype='complex')

    # We use the L2-normalized Wigner D functions
    #Z = (1. / (2 * np.pi)) * np.sqrt(l + 0.5)
    #Z = 1. / np.pi

    # Normalized wrt normalized Haar measure, as used by S3.integrate()
    #Z = np.sqrt(2 * l + 1)

    Z = 1.

    for j1 in range(f.shape[0]):
        alpha = 2 * np.pi * j1 / (2. * b)
        for k in range(f.shape[1]):
            beta = np.pi * (2 * k + 1) / (4. * b)
            for j2 in range(f.shape[2]):
                gamma = 2 * np.pi * j2 / (2. * b)
                #f[j1, k, j2] = D(alpha, beta, gamma) * (1. / 2. * np.pi) * np.sqrt(l + 0.5)
                #f[j1, k, j2] = (C2R.conj().T.dot(D(alpha, beta, gamma)).dot(C2R))[m + l, n + l]
                #f[j1, k, j2] *= (1. / (2. * np.pi)) * np.sqrt(l + 0.5)

                f[j1, k, j2] = D(alpha, beta, gamma) * Z

    return f
    def setup_d_transform(b, J_dense, L2_normalized):
        """

        """

        # We know how to efficiently compute d functions in the real basis using
        # Pinchon-Hoggans approach (d_real = J X(beta) J), but we want them in the
        # basis of complex centered spherical harmonics Y^{-l}, ..., Y^{l}.
        # These matrices perform that change of basis
        #C2R = [get_sh_change_of_basis(l,
        #                              frm=('complex', 'seismology', 'centered'),
        #                              to=('real', 'quantum', 'centered'))
        #       for l in range(b)]
        C2R = [change_of_basis_matrix(l,
                                      frm=('complex', 'seismology', 'centered', 'cs'),
                                      to=('real', 'quantum', 'centered', 'cs'))
               for l in range(b)]

        # Compute array of beta values as described in SOFT 2.0 documentation.
        beta = np.pi * (2 * np.arange(0, 2 * b) + 1) / (4. * b)

        # Compute d matrices in real basis (fast, stable),
        # then change them to complex basis (where the d-funcs are still real):
        d = [np.array([rot_mat(0, bt, 0, l, J_dense[l])
                       for bt in beta])
             for l in range(b)]
        d = [C2R[l].conj().T.dot(d[l]).dot(C2R[l]).real
             for l in range(b)]

        if L2_normalized:
            # The Unitary matrix elements have norm:
            # | U^\lambda_mn |^2 = 1/(2l+1)
            # where the 2-norm is defined in terms of normalized Haar measure.
            # So T = sqrt(2l + 1) U are L2-normalized functions
            d = [d[l] * np.sqrt(2 * l + 1) for l in range(len(d))]

        return d