def H_var_coeff(coeff, qm, qu, dim): """ H_var_coeff(coeff, qm, qu, dim) Variance of mean curvature H across surface determined by coeff at resolution qu Parameters ---------- coeff: float, array_like; shape=(n_frame, 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 across whole surface """ if qu == 0: return 0 n_waves = 2 * qm + 1 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_filter = ((u_array >= -qu) * (u_array <= qu) * (v_array >= -qu) * (v_array <= qu)) indices = np.argwhere(wave_filter).flatten() Psi = vcheck(u_array, v_array)[indices] / 4. coeff_filter = coeff[:, :, indices] av_coeff_2 = np.mean(coeff_filter**2, axis=(0, 1)) * Psi H_var_array = av_coeff_2[indices] * vcheck(u_array[indices], v_array[indices]) H_var_array *= (u_array[indices]**4 / dim[0]**4 + v_array[indices]**4 / dim[1]**4 + 2 * u_array[indices]**2 * v_array[indices]**2 / (dim[0]**2 * dim[1]**2)) H_var = 16 * np.pi**4 * np.sum(H_var_array) return H_var
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 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
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
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
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
def coeff_to_fourier_2(coeff_2, qm, dim): """Converts square coefficients to square Fourier coefficients""" n_waves = 2 * qm + 1 u_mat, v_mat = np.meshgrid(np.arange(-qm, qm + 1), np.arange(-qm, qm + 1)) x_mat, y_mat = np.meshgrid(np.linspace(0, 1 / dim[0], n_waves), np.linspace(0, 1 / dim[1], n_waves)) Psi = vcheck(u_mat.flatten(), v_mat.flatten()) / 4. frequencies = np.pi * 2 * (u_mat * x_mat + y_mat * v_mat) / n_waves amplitudes_2 = np.reshape(Psi * coeff_2, (n_waves, n_waves)) A = np.zeros((n_waves, n_waves)) for i in range(n_waves): for j in range(n_waves): A[i][j] += ( amplitudes_2 * np.exp(-2 * np.pi * 1j / n_waves * (u_mat * x_mat[i][j] + y_mat[i][j] * v_mat))).sum() return A, frequencies