Exemple #1
0
    def test_wave_arrays(self):

        u_array, v_array = wave_arrays(1)
        self.assertArrayAlmostEqual(
            np.array([-1, -1, -1, 0, 0, 0, 1, 1, 1]),
            u_array
        )
        self.assertArrayAlmostEqual(
            np.array([-1, 0, 1, -1, 0, 1, -1, 0, 1]),
            v_array
        )

        u_array, v_array = wave_arrays(2)
        self.assertEqual((25,), u_array.shape)
        self.assertEqual((25,), v_array.shape)
Exemple #2
0
def get_frequency_set(qm, qu, dim):
    """
    Returns set of unique frequencies in Fourier series

    Parameters
    ----------

    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell

    Returns
    -------

    q_set:  float, array_like
        Set of unique frequencies
    q2_set:  float, array_like
        Set of unique frequencies to bin coefficients to
    """

    u_array, v_array = wave_arrays(qm)

    indices = wave_indices(qu, u_array, v_array)

    q, q2 = calculate_frequencies(u_array[indices], v_array[indices], dim)

    q_set = np.unique(q)[1:]
    q2_set = np.unique(q2)[1:]

    return q_set, q2_set
Exemple #3
0
def coeff_to_fourier(coeff, qm, dim):
    """
    Returns Fouier coefficients for Fouier series representing
    intrinsic surface from linear algebra coefficients

    Parameters
    ----------
    coeff:	float, array_like; shape=(n_waves**2)
        Optimised linear algebra surface coefficients
    qm:  int
        Maximum number of wave frequencies in Fouier Sum
        representing intrinsic surface

    Returns
    -------
    f_coeff:  float, array_like; shape=(n_waves**2)
        Optimised Fouier surface coefficients

    """

    n_waves = 2 * qm + 1
    u_array, v_array = wave_arrays(qm)
    frequencies, _ = calculate_frequencies(u_array, v_array, dim)

    amplitudes = np.zeros(coeff.shape, dtype=complex)

    for u in range(-qm, qm + 1):
        for v in range(-qm, qm + 1):
            index = n_waves * (u + qm) + (v + qm)

            j1 = n_waves * (abs(u) + qm) + (abs(v) + qm)
            j2 = n_waves * (-abs(u) + qm) + (abs(v) + qm)
            j3 = n_waves * (abs(u) + qm) + (-abs(v) + qm)
            j4 = n_waves * (-abs(u) + qm) + (-abs(v) + qm)

            if abs(u) + abs(v) == 0:
                value = coeff[j1]

            elif v == 0:
                value = (coeff[j1] - np.sign(u) * 1j * coeff[j2]) / 2.
            elif u == 0:
                value = (coeff[j1] - np.sign(v) * 1j * coeff[j3]) / 2.

            elif u < 0 and v < 0:
                value = (coeff[j1] + 1j *
                         (coeff[j2] + coeff[j3]) - coeff[j4]) / 4.
            elif u > 0 and v > 0:
                value = (coeff[j1] - 1j *
                         (coeff[j2] + coeff[j3]) - coeff[j4]) / 4.

            elif u < 0:
                value = (coeff[j1] + 1j *
                         (coeff[j2] - coeff[j3]) + coeff[j4]) / 4.
            elif v < 0:
                value = (coeff[j1] - 1j *
                         (coeff[j2] - coeff[j3]) + coeff[j4]) / 4.

            amplitudes[index] = value

    return amplitudes, frequencies
def xi_var(coeff, qm, qu):
    """Calculate average variance of surface heights

    Parameters
    ----------
    coeff:	float, array_like; shape=(n_frame, n_waves**2)
        Optimised surface coefficients
    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface
    qu:  int
        Upper limit of wave frequencies in Fourier Sum
        representing intrinsic surface

    Returns
    -------
    calc_var: float
        Variance of surface heights across whole surface

    """

    u_array, v_array = wave_arrays(qm)
    indices = wave_indices(qu, u_array, v_array)

    Psi = vcheck(u_array[indices], v_array[indices]) / 4.

    coeff_filter = coeff[:, :, indices]
    mid_point = len(indices) / 2

    av_coeff = np.mean(coeff_filter[:, :, mid_point], axis=0)
    av_coeff_2 = np.mean(coeff_filter**2, axis=(0, 1)) * Psi

    calc_var = np.sum(av_coeff_2) - np.mean(av_coeff**2, axis=0)

    return calc_var
def dxy_dxi(x, y, coeff, qm, qu, dim):
    """
    Function returning derivatives of intrinsic surface at
    position (x,y) wrt x and y

    Parameters
    ----------
    x:  float
        Coordinate in x dimension
    y:  float
        Coordinate in y dimension
    coeff:	float, array_like; shape=(n_waves**2)
        Optimised surface coefficients
    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface
    qu:  int
        Upper limit of wave frequencies in Fourier Sum
        representing intrinsic surface
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell

    Returns
    -------
    dx_dxi:  float
        Derivative of intrinsic surface in x dimension
    dy_dxi:  float
        Derivative of intrinsic surface in y dimension

    """

    if np.isscalar(x):
        u_array, v_array = wave_arrays(qm)
        indices = wave_indices(qu, u_array, v_array)

        wave_x = wave_function_array(x, u_array[indices], dim[0])
        wave_y = wave_function_array(y, v_array[indices], dim[1])
        wave_dx = d_wave_function_array(x, u_array[indices], dim[0])
        wave_dy = d_wave_function_array(y, v_array[indices], dim[1])

        dx_dxi = np.sum(wave_dx * wave_y * coeff[indices])
        dy_dxi = np.sum(wave_x * wave_dy * coeff[indices])

    else:
        dx_dxi = np.zeros(x.shape)
        dy_dxi = np.zeros(x.shape)
        for u in range(-qu, qu + 1):
            for v in range(-qu, qu + 1):
                j = (2 * qm + 1) * (u + qm) + (v + qm)

                wave_x = wave_function(x, u, dim[0])
                wave_y = wave_function(y, v, dim[1])
                wave_dx = d_wave_function(x, u, dim[0])
                wave_dy = d_wave_function(y, v, dim[1])

                dx_dxi += wave_dx * wave_y * coeff[j]
                dy_dxi += wave_x * wave_dy * coeff[j]

    return dx_dxi, dy_dxi
Exemple #6
0
def update_A_b(xmol, ymol, zmol, dim, qm, new_pivot):
    """
    Update A matrix and b vector for new pivot selection

    Parameters
    ----------
    xmol:  float, array_like; shape=(nmol)
        Molecular coordinates in x dimension
    ymol:  float, array_like; shape=(nmol)
        Molecular coordinates in y dimension
    zmol:  float, array_like; shape=(nmol)
        Molecular coordinates in z dimension
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell
    qm:  int
        Maximum number of wave frequencies in Fouier Sum
        representing intrinsic surface
    n_waves:  int
        Number of coefficients / waves in surface
    new_pivot:  int, array_like
        Indices of new pivot molecules for both surfaces

    Returns
    -------
    A:  float, array_like; shape=(2, n_waves**2, n_waves**2)
        Matrix containing wave product weightings
        f(x, u1, Lx).f(y, v1, Ly).f(x, u2, Lx).f(y, v2, Ly)
        for each coefficient in the linear algebra equation
        Ax = b for both surfaces
    b:  float, array_like; shape=(2, n_waves**2)
        Vector containing solutions z.f(x, u, Lx).f(y, v, Ly)
        to the linear algebra equation Ax = b
        for both surfaces

    """
    n_waves = 2 * qm + 1

    u_array, v_array = wave_arrays(qm)

    A = np.zeros((2, n_waves**2, n_waves**2))
    b = np.zeros((2, n_waves**2))

    fuv = np.zeros((2, n_waves**2, len(new_pivot[0])))

    for surf in range(2):
        for index in range(n_waves**2):
            wave_x = wave_function(xmol[new_pivot[surf]], u_array[index],
                                   dim[0])
            wave_y = wave_function(ymol[new_pivot[surf]], v_array[index],
                                   dim[1])
            fuv[surf][index] = wave_x * wave_y
            b[surf][index] += np.sum(zmol[new_pivot[index]] * fuv[surf][index])

        A[surf] += np.dot(fuv[surf], fuv[surf].T)

    return A, b, fuv
def initialise_surface(qm, phi, dim):
    """
    Calculate initial parameters for ISM

    Parameters
    ----------
    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface
    phi:  float
        Weighting factor of minimum surface area term in surface
        optimisation function
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell

    Returns
    -------

    coeff:	array_like (float); shape=(n_waves**2)
        Optimised surface coefficients
    A:  float, array_like; shape=(n_waves**2, n_waves**2)
        Matrix containing wave product weightings
        f(x, u1, Lx).f(y, v1, Ly).f(x, u2, Lx).f(y, v2, Ly)
        for each coefficient in the linear algebra equation
        Ax = b for both surfaces
    b:  float, array_like; shape=(n_waves**2)
        Vector containing solutions z.f(x, u, Lx).f(y, v, Ly)
        to the linear algebra equation Ax = b
        for both surfaces
    area_diag: float, array_like; shape=(n_waves**2)
        Surface area diagonal terms for A matrix
    """

    n_waves = 2*qm+1

    # Form the diagonal xi^2 terms
    u_array, v_array = wave_arrays(qm)
    uv_check = vcheck(u_array, v_array)

    # Make diagonal terms of A matrix
    area_diag = phi * (
        u_array**2 * dim[1] / dim[0]
        + v_array**2 * dim[0] / dim[1]
    )
    area_diag = 4 * np.pi**2 * np.diagflat(area_diag * uv_check)

    # Create empty A matrix and b vector for linear algebra
    # equation Ax = b
    A = np.zeros((2, n_waves**2, n_waves**2))
    b = np.zeros((2, n_waves**2))
    coeff = np.zeros((2, n_waves**2))

    return coeff, A, b, area_diag
def initialise_recon(qm, phi, dim):
    """
    Calculate initial parameters for reconstructed
    ISM fitting procedure

    Parameters
    ----------
    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface
    phi:  float
        Weighting factor of minimum surface area term in surface
        optimisation function
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell

    Returns
    -------
    psi:  float
        Weighting factor for surface reconstruction function
    curve_matrix: float, array_like; shape=(n_waves**2, n_waves**2)
        Surface curvature terms for A matrix
    H_var: float, array_like; shape=(n_waves**2)
        Diagonal terms for global variance of mean curvature
    """

    psi = phi * dim[0] * dim[1]
    n_waves = 2 * qm + 1

    "Form the diagonal xi^2 terms"
    u_array, v_array = wave_arrays(qm)
    uv_check = vcheck(u_array, v_array)

    u_matrix = np.tile(u_array, (n_waves**2, 1))
    v_matrix = np.tile(v_array, (n_waves**2, 1))

    H_var = 4 * np.pi**4 * uv_check * (
        u_array**4 / dim[0]**4 + v_array**4 / dim[1]**4
        + 2 * (u_array * v_array)**2 / np.prod(dim**2)
    )

    curve_matrix = 16 * np.pi**4 * (
        (u_matrix * u_matrix.T)**2 / dim[0]**4 +
        (v_matrix * v_matrix.T)**2 / dim[1]**4 +
        ((u_matrix * v_matrix.T)**2 +
         (u_matrix.T * v_matrix)**2) / np.prod(dim**2)
    )

    return psi, curve_matrix, H_var
Exemple #9
0
def surface_tension_coeff(coeff_2, qm, qu, dim, T):
    """
    Returns spectrum of surface tension, corresponding to
    the frequencies in q2_set

    Parameters
    ----------

    coeff_2:  float, array_like; shape=(n_waves**2)
        Square of optimised surface coefficients
    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface
    qu:  int
        Upper limit of wave frequencies in Fourier Sum
        representing intrinsic surface
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell
    T:  float
        Average temperature of simulation (K)

    Returns
    -------
    unique_q:  float, array_like
        Set of frequencies for power spectrum histogram
    av_gamma:  float, array_like
        Surface tension histogram of Fourier series frequencies

    """

    u_array, v_array = wave_arrays(qm)

    indices = wave_indices(qu, u_array, v_array)

    q, q2 = calculate_frequencies(u_array[indices], v_array[indices], dim)

    int_A = dim[0] * dim[1] * q2 * coeff_2[indices] * vcheck(
        u_array[indices], v_array[indices]) / 4
    gamma = con.k * T * 1E23 / int_A

    unique_q, av_gamma = filter_frequencies(q, gamma)

    return unique_q, av_gamma
Exemple #10
0
def power_spectrum_coeff(coeff_2, qm, qu, dim):
    """
    Returns power spectrum of average surface coefficients,
    corresponding to the frequencies in q2_set

    Parameters
    ----------

    coeff_2:  float, array_like; shape=(n_waves**2)
        Square of optimised surface coefficients
    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface
    qu:  int
        Upper limit of wave frequencies in Fourier Sum
        representing intrinsic surface
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell

    Returns
    -------
    unique_q:  float, array_like
        Set of frequencies for power spectrum
        histogram
    av_fourier:  float, array_like
        Power spectrum histogram of Fourier
        series coefficients

    """

    u_array, v_array = wave_arrays(qm)

    indices = wave_indices(qu, u_array, v_array)

    q, q2 = calculate_frequencies(u_array[indices], v_array[indices], dim)

    fourier = coeff_2[indices] / 4 * vcheck(u_array[indices], v_array[indices])

    # Remove redundant frequencies
    unique_q, av_fourier = filter_frequencies(q, fourier)

    return unique_q, av_fourier
Exemple #11
0
def intrinsic_area(coeff, qm, qu, dim):
    """
    Calculate the intrinsic surface area from coefficients
    at resolution qu

    Parameters
    ----------

    coeff:	float, array_like; shape=(n_waves**2)
        Optimised surface coefficients
    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface
    qu:  int
        Upper limit of wave frequencies in Fourier Sum
        representing intrinsic surface
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell

    Returns
    -------

    int_A:  float
        Relative size of intrinsic surface area, compared
        to cell cross section XY
    """

    u_array, v_array = wave_arrays(qm)
    indices = wave_indices(qu, u_array, v_array)

    q2 = np.pi**2 * (u_array[indices]**2 / dim[0]**2 +
                     v_array[indices]**2 / dim[1]**2)

    int_A = q2 * coeff[indices]**2 * vcheck(u_array[indices], v_array[indices])
    int_A = 1 + 0.5 * np.sum(int_A)

    return int_A