예제 #1
0
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
예제 #2
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
예제 #3
0
def H_xy(x, y, coeff, qm, qu, dim):
    """
    H_xy(x, y, coeff, qm, qu, dim)

    Calculation of mean curvature at position (x,y) at resolution qu

    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 Fouier Sum representing
        intrinsic surface
    qu:  int
        Upper limit of wave frequencies in Fouier Sum representing
        intrinsic surface
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell

    Returns
    -------

    H:  float
        Mean curvature of intrinsic surface at point x,y
    """

    n_waves = 2 * qm + 1

    if np.isscalar(x) and np.isscalar(y):
        u_array = np.array(np.arange(n_waves**2) / n_waves, dtype=int) - qm
        v_array = np.array(np.arange(n_waves**2) % n_waves, dtype=int) - qm
        wave_check = ((u_array >= -qu) * (u_array <= qu) * (v_array >= -qu) *
                      (v_array <= qu))
        indices = np.argwhere(wave_check).flatten()

        fuv = wave_function_array(x, u_array[indices], dim[0])
        fuv *= wave_function_array(y, v_array[indices], dim[1])
        H = -4 * np.pi**2 * np.sum(
            (u_array[indices]**2 / dim[0]**2 + v_array[indices]**2 / dim[1]**2)
            * fuv * coeff[indices])
    else:
        H_array = 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)
                H_array += (wave_function(x, u, dim[0]) *
                            wave_function(y, v, dim[1]) *
                            (u**2 / dim[0]**2 + v**2 / dim[1]**2) * coeff[j])
        H = -4 * np.pi**2 * H_array

    return H
예제 #4
0
    def test_wave_function(self):

        self.assertEqual(
            1.0, wave_function(0, 0, self.lx))
        self.assertEqual(
            1.0, wave_function(0, self.lx, self.lx))
        self.assertEqual(
            1.0, wave_function(self.lx, 0, self.lx))
        self.assertEqual(
            1.0, wave_function(self.lx, self.lx, self.lx))

        self.assertEqual(
            -1.0, wave_function(1, self.lx / 2, self.lx))
        self.assertEqual(
            1.0, wave_function(2, self.lx / 2, self.lx))
예제 #5
0
def make_pos_dxdy(xmol, ymol, coeff, nmol, dim, qm):
    """
    Calculate distances and derivatives at each molecular position with
    respect to intrinsic surface

    Parameters
    ----------

    xmol:  float, array_like; shape=(nmol)
        Molecular coordinates in x dimension
    ymol:  float, array_like; shape=(nmol)
        Molecular coordinates in y dimension
    coeff:	float, array_like; shape=(n_waves**2)
        Optimised surface coefficients
    nmol:  int
        Number of molecules in simulation
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell
    qm:  int
        Maximum number of wave frequencies in Fourier Sum
        representing intrinsic surface

    Returns
    -------

    int_z_mol:  array_like (float); shape=(nframe, 2, qm+1, nmol)
        Molecular distances from intrinsic surface
    int_dxdy_mol:  array_like (float); shape=(nframe, 4, qm+1, nmol)
        First derivatives of intrinsic surface wrt x and y at xmol, ymol
    int_ddxddy_mol:  array_like (float); shape=(nframe, 4, qm+1, nmol)
        Second derivatives of intrinsic surface wrt x and y at xmol, ymol

    """

    int_z_mol = np.zeros((qm + 1, 2, nmol))
    int_dxdy_mol = np.zeros((qm + 1, 4, nmol))
    int_ddxddy_mol = np.zeros((qm + 1, 4, nmol))

    tmp_int_z_mol = np.zeros((2, nmol))
    tmp_dxdy_mol = np.zeros((4, nmol))
    tmp_ddxddy_mol = np.zeros((4, nmol))

    for qu in range(qm + 1):

        if qu == 0:
            j = (2 * qm + 1) * qm + qm
            f_x = wave_function(xmol, 0, dim[0])
            f_y = wave_function(ymol, 0, dim[1])

            tmp_int_z_mol[0] += f_x * f_y * coeff[0][j]
            tmp_int_z_mol[1] += f_x * f_y * coeff[1][j]

        else:
            for u in [-qu, qu]:
                for v in range(-qu, qu + 1):
                    j = (2 * qm + 1) * (u + qm) + (v + qm)

                    f_x = wave_function(xmol, u, dim[0])
                    f_y = wave_function(ymol, v, dim[1])
                    df_dx = d_wave_function(xmol, u, dim[0])
                    df_dy = d_wave_function(ymol, v, dim[1])
                    ddf_ddx = dd_wave_function(xmol, u, dim[0])
                    ddf_ddy = dd_wave_function(ymol, v, dim[1])

                    tmp_int_z_mol[0] += f_x * f_y * coeff[0][j]
                    tmp_int_z_mol[1] += f_x * f_y * coeff[1][j]
                    tmp_dxdy_mol[0] += df_dx * f_y * coeff[0][j]
                    tmp_dxdy_mol[1] += f_x * df_dy * coeff[0][j]
                    tmp_dxdy_mol[2] += df_dx * f_y * coeff[1][j]
                    tmp_dxdy_mol[3] += f_x * df_dy * coeff[1][j]
                    tmp_ddxddy_mol[0] += ddf_ddx * f_y * coeff[0][j]
                    tmp_ddxddy_mol[1] += f_x * ddf_ddy * coeff[0][j]
                    tmp_ddxddy_mol[2] += ddf_ddx * f_y * coeff[1][j]
                    tmp_ddxddy_mol[3] += f_x * ddf_ddy * coeff[1][j]

            for u in range(-qu + 1, qu):
                for v in [-qu, qu]:
                    j = (2 * qm + 1) * (u + qm) + (v + qm)

                    f_x = wave_function(xmol, u, dim[0])
                    f_y = wave_function(ymol, v, dim[1])
                    df_dx = d_wave_function(xmol, u, dim[0])
                    df_dy = d_wave_function(ymol, v, dim[1])
                    ddf_ddx = dd_wave_function(xmol, u, dim[0])
                    ddf_ddy = dd_wave_function(ymol, v, dim[1])

                    tmp_int_z_mol[0] += f_x * f_y * coeff[0][j]
                    tmp_int_z_mol[1] += f_x * f_y * coeff[1][j]
                    tmp_dxdy_mol[0] += df_dx * f_y * coeff[0][j]
                    tmp_dxdy_mol[1] += f_x * df_dy * coeff[0][j]
                    tmp_dxdy_mol[2] += df_dx * f_y * coeff[1][j]
                    tmp_dxdy_mol[3] += f_x * df_dy * coeff[1][j]
                    tmp_ddxddy_mol[0] += ddf_ddx * f_y * coeff[0][j]
                    tmp_ddxddy_mol[1] += f_x * ddf_ddy * coeff[0][j]
                    tmp_ddxddy_mol[2] += ddf_ddx * f_y * coeff[1][j]
                    tmp_ddxddy_mol[3] += f_x * ddf_ddy * coeff[1][j]

        int_z_mol[qu] += tmp_int_z_mol
        int_dxdy_mol[qu] += tmp_dxdy_mol
        int_ddxddy_mol[qu] += tmp_ddxddy_mol

    int_z_mol = np.swapaxes(int_z_mol, 0, 1)
    int_dxdy_mol = np.swapaxes(int_dxdy_mol, 0, 1)
    int_ddxddy_mol = np.swapaxes(int_ddxddy_mol, 0, 1)

    return int_z_mol, int_dxdy_mol, int_ddxddy_mol
예제 #6
0
def H_var_mol(xmol, ymol, coeff, qm, qu, dim):
    """
    Variance of mean curvature H at molecular positions determined by
    coeff at resolution qu

    Parameters
    ----------

    xmol:  float, array_like; shape=(nmol)
        Molecular coordinates in x dimension
    ymol:  float, array_like; shape=(nmol)
        Molecular coordinates in y dimension
    coeff:	float, array_like; shape=(n_waves**2)
        Optimised surface coefficients
    qm:  int
        Maximum number of wave frequencies in Fouier Sum representing
        intrinsic surface
    qu:  int
        Upper limit of wave frequencies in Fouier Sum representing
        intrinsic surface
    dim:  float, array_like; shape=(3)
        XYZ dimensions of simulation cell

    Returns
    -------

    H_var:  float
        Variance of mean curvature H at pivot points
    """

    if qu == 0:
        return 0

    n_waves = 2 * qm + 1
    nmol = xmol.shape[0]

    # Create arrays of wave frequency indicies u and v
    u_array = np.array(np.arange(n_waves**2) / n_waves, dtype=int) - qm
    v_array = np.array(np.arange(n_waves**2) % n_waves, dtype=int) - qm
    wave_check = ((u_array >= -qu) * (u_array <= qu) * (v_array >= -qu) *
                  (v_array <= qu))
    indices = np.argwhere(wave_check).flatten()

    # Create matrix of wave frequency indicies (u, v)**2
    u_matrix = np.tile(u_array[indices], (len([indices]), 1))
    v_matrix = np.tile(v_array[indices], (len([indices]), 1))

    # Make curvature diagonal terms of A matrix
    curve_diag = 16 * np.pi**4 * (
        u_matrix**2 * u_matrix.T**2 / dim[0]**4 +
        v_matrix**2 * v_matrix.T**2 / dim[1]**4 +
        (u_matrix**2 * v_matrix.T**2 + u_matrix.T**2 * v_matrix**2) /
        (dim[0]**2 * dim[1]**2))

    # Form the diagonal xi^2 terms and b vector solutions
    fuv = np.zeros((n_waves**2, nmol))
    for u in range(-qu, qu + 1):
        for v in range(-qu, qu + 1):
            j = (2 * qm + 1) * (u + qm) + (v + qm)
            fuv[j] = (wave_function(xmol, u_array[j], dim[0]) *
                      wave_function(ymol, v_array[j], dim[1]))
    ffuv = np.dot(fuv[indices], fuv[indices].T)

    coeff_matrix = np.tile(coeff[indices], (len([indices]), 1))
    H_var = np.sum(coeff_matrix * coeff_matrix.T * ffuv * curve_diag / nmol)

    return H_var