def test_interpolation(): ''' ''' threshold = 8e-9 params.N_LGL = 8 gv = gvar.advection_variables(params.N_LGL, params.N_quad,\ params.x_nodes, params.N_Elements,\ params.c, params.total_time, params.wave,\ params.c_x, params.c_y, params.courant,\ params.mesh_file, params.total_time_2d) N_LGL = 8 xi_LGL = lagrange.LGL_points(N_LGL) xi_i = af.flat(af.transpose(af.tile(xi_LGL, 1, N_LGL))) eta_j = af.tile(xi_LGL, N_LGL) f_ij = np.e**(xi_i + eta_j) interpolated_f = wave_equation_2d.lag_interpolation_2d( f_ij, gv.Li_Lj_coeffs) xi = utils.linspace(-1, 1, 8) eta = utils.linspace(-1, 1, 8) assert (af.mean( af.transpose(utils.polyval_2d(interpolated_f, xi, eta)) - np.e**(xi + eta)) < threshold)
def test_polyval_2d(): ''' Tests the ``utils.polyval_2d`` function by evaluating the polynomial .. math:: P_0(\\xi) P_1(\\eta) here, .. math:: P_0(\\xi) = 3 \, \\xi^{2} + 2 \, \\xi + 1 .. math:: P_1(\\eta) = 3 \, \\eta^{2} + 2 \, \\eta + 1 at corresponding ``linspace`` points in :math:`\\xi \\in [-1, 1]` and :math:`\\eta \\in [-1, 1]`. This value is then compared with the reference value calculated analytically. The reference values are calculated in `polynomial_product_two_variables.sagews`_ .. _polynomial_product_two_variables.sagews: https://goo.gl/KwG7k9 ''' threshold = 1e-12 poly_xi_degree = 4 poly_xi = af.flip(af.np_to_af_array(np.arange(1, poly_xi_degree))) poly_eta_degree = 4 poly_eta = af.flip(af.np_to_af_array(np.arange(1, poly_eta_degree))) poly_xi_eta = utils.polynomial_product_coeffs(poly_xi, poly_eta) xi = utils.linspace(-1, 1, 8) eta = utils.linspace(-1, 1, 8) polyval_xi_eta = af.transpose(utils.polyval_2d(poly_xi_eta, xi, eta)) polyval_xi_eta_ref = af.np_to_af_array( np.array([ 4.00000000000000, 1.21449396084962, 0.481466055810080, 0.601416076634741, 1.81424406497291, 5.79925031236988, 15.6751353602663, 36.0000000000000 ])) diff = af.abs(polyval_xi_eta - polyval_xi_eta_ref) assert af.all_true(diff < threshold)
# While evaluating the volume integral using N_LGL # lobatto quadrature points, The integration can be vectorized # and in this case the coefficients of the differential of the # Lagrange polynomials is required diff_pow = (af.flip(af.transpose(af.range(N_LGL - 1) + 1), 1)) dl_dxi_coeffs = (af.broadcast(utils.multiply, lagrange_coeffs[:, :-1], diff_pow)) # Obtaining an array consisting of the LGL points mapped onto the elements. element_size = af.sum((x_nodes[1] - x_nodes[0]) / N_Elements) elements_xi_LGL = af.constant(0, N_Elements, N_LGL) elements = utils.linspace(af.sum(x_nodes[0]), af.sum(x_nodes[1] - element_size), N_Elements) np_element_array = np.concatenate((af.transpose(elements), af.transpose(elements + element_size))) element_mesh_nodes = utils.linspace(af.sum(x_nodes[0]), af.sum(x_nodes[1]), N_Elements + 1) element_array = af.transpose(af.interop.np_to_af_array(np_element_array)) element_LGL = wave_equation.mapping_xi_to_x(af.transpose(element_array), xi_LGL) # The minimum distance between 2 mapped LGL points. delta_x = af.min((element_LGL - af.shift(element_LGL, 1, 0))[1:, :]) # dx_dxi for elements of equal size.
def change_parameters(LGL, Elements, quad, wave='sin'): ''' Changes the parameters of the simulation. Used only for convergence tests. Parameters ---------- LGL : int The new N_LGL. Elements : int The new N_Elements. ''' # The domain of the function. params.x_nodes = af.np_to_af_array(np.array([-1., 1.])) # The number of LGL points into which an element is split. params.N_LGL = LGL # Number of elements the domain is to be divided into. params.N_Elements = Elements # The number quadrature points to be used for integration. params.N_quad = quad # Array containing the LGL points in xi space. params.xi_LGL = lagrange.LGL_points(params.N_LGL) # The weights of the lgl points params.weight_arr = lagrange.weight_arr_fun(params.xi_LGL) # N_Gauss number of Gauss nodes. params.gauss_points = af.np_to_af_array(lagrange.gauss_nodes\ (params.N_quad)) # The Gaussian weights. params.gauss_weights = lagrange.gaussian_weights(params.N_quad) # The lobatto nodes to be used for integration. params.lobatto_quadrature_nodes = lagrange.LGL_points(params.N_quad) # The lobatto weights to be used for integration. params.lobatto_weights_quadrature = lagrange.lobatto_weights\ (params.N_quad) #The b matrix params.b_matrix = lagrange.b_matrix_eval() # A list of the Lagrange polynomials in poly1d form. #params.lagrange_product = lagrange.product_lagrange_poly(params.xi_LGL) # An array containing the coefficients of the lagrange basis polynomials. params.lagrange_coeffs = af.np_to_af_array(\ lagrange.lagrange_polynomials(params.xi_LGL)[1]) # Refer corresponding functions. params.lagrange_basis_value = lagrange.lagrange_function_value\ (params.lagrange_coeffs) # While evaluating the volume integral using N_LGL # lobatto quadrature points, The integration can be vectorized # and in this case the coefficients of the differential of the # Lagrange polynomials is required params.diff_pow = (af.flip(af.transpose(af.range(params.N_LGL - 1) + 1), 1)) params.dl_dxi_coeffs = (af.broadcast(utils.multiply, params.lagrange_coeffs[:, :-1], params.diff_pow)) # Obtaining an array consisting of the LGL points mapped onto the elements. params.element_size = af.sum((params.x_nodes[1] - params.x_nodes[0])\ / params.N_Elements) params.elements_xi_LGL = af.constant(0, params.N_Elements, params.N_LGL) params.elements = utils.linspace(af.sum(params.x_nodes[0]), af.sum(params.x_nodes[1] - params.element_size),\ params.N_Elements) params.np_element_array = np.concatenate((af.transpose(params.elements), af.transpose(params.elements +\ params.element_size))) params.element_mesh_nodes = utils.linspace(af.sum(params.x_nodes[0]), af.sum(params.x_nodes[1]),\ params.N_Elements + 1) params.element_array = af.transpose(af.np_to_af_array\ (params.np_element_array)) params.element_LGL = wave_equation.mapping_xi_to_x(af.transpose\ (params.element_array), params.xi_LGL) # The minimum distance between 2 mapped LGL points. params.delta_x = af.min( (params.element_LGL - af.shift(params.element_LGL, 1, 0))[1:, :]) # dx_dxi for elements of equal size. params. dx_dxi = af.mean(wave_equation.dx_dxi_numerical((params.element_mesh_nodes[0 : 2]),\ params.xi_LGL)) # The value of time-step. params.delta_t = params.delta_x / (4 * params.c) # Array of timesteps seperated by delta_t. params.time = utils.linspace( 0, int(params.total_time / params.delta_t) * params.delta_t, int(params.total_time / params.delta_t)) # Initializing the amplitudes. Change u_init to required initial conditions. if (wave == 'sin'): params.u_init = af.sin(2 * np.pi * params.element_LGL) if (wave == 'gaussian'): params.u_init = np.e**(-(params.element_LGL)**2 / 0.4**2) params.u = af.constant(0, params.N_LGL, params.N_Elements, params.time.shape[0],\ dtype = af.Dtype.f64) params.u[:, :, 0] = params.u_init return
def __init__(self, N_LGL, N_quad, x_nodes, N_elements, c, total_time, wave, c_x, c_y, courant, mesh_file, total_time_2d): ''' Initializes the variables using the user parameters. Parameters ---------- N_LGL : int Number of LGL points(for both :math:`2D` and :math:`1D` wave equation solver). N_quad : int Number of the quadrature points to use in Gauss-Lobatto or Gauss-Legendre quadrature. x_nodes : af.Array [2 1 1 1] :math:`x` nodes for the :math:`1D` wave equation elements. N_elements : int Number of elements in a :math:`1D` domain. c : float64 Wave speed for 1D wave equation. total_time : float64 Total time for which :math:`1D` wave equation is to be evolved. wave : str Used to set u_init to ``sin`` or ``cos``. c_x : float64 :math:`x` component of wave speed for a :math:`2D` wave. c_y : float64 :math:`y` component of wave speed for a :math:`2D` wave. courant : float64 Courant parameter used for the time evolution of the wave. mesh_file : str Path of the mesh file for the 2D wave equation. total_time_2d : float64 Total time for which the wave is to propogated. Returns ------- None ''' self.xi_LGL = lagrange.LGL_points(N_LGL) # N_Gauss number of Gauss nodes. self.gauss_points = af.np_to_af_array(lagrange.gauss_nodes(N_quad)) # The Gaussian weights. self.gauss_weights = lagrange.gaussian_weights(N_quad) # The lobatto nodes to be used for integration. self.lobatto_quadrature_nodes = lagrange.LGL_points(N_quad) # The lobatto weights to be used for integration. self.lobatto_weights_quadrature = lagrange.lobatto_weights(N_quad) # An array containing the coefficients of the lagrange basis polynomials. self.lagrange_coeffs = lagrange.lagrange_polynomial_coeffs(self.xi_LGL) self.lagrange_basis_value = lagrange.lagrange_function_value( self.lagrange_coeffs, self.xi_LGL) self.diff_pow = af.flip(af.transpose(af.range(N_LGL - 1) + 1), 1) self.dl_dxi_coeffs = af.broadcast(utils.multiply, self.lagrange_coeffs[:, :-1], self.diff_pow) self.element_size = af.sum((x_nodes[1] - x_nodes[0]) / N_elements) self.elements_xi_LGL = af.constant(0, N_elements, N_LGL) self.elements = utils.linspace(af.sum(x_nodes[0]), af.sum(x_nodes[1] - self.element_size), N_elements) self.np_element_array = np.concatenate( (af.transpose(self.elements), af.transpose(self.elements + self.element_size))) self.element_mesh_nodes = utils.linspace(af.sum(x_nodes[0]), af.sum(x_nodes[1]), N_elements + 1) self.element_array = af.transpose( af.interop.np_to_af_array(self.np_element_array)) self.element_LGL = wave_equation.mapping_xi_to_x( af.transpose(self.element_array), self.xi_LGL) # The minimum distance between 2 mapped LGL points. self.delta_x = af.min( (self.element_LGL - af.shift(self.element_LGL, 1, 0))[1:, :]) # dx_dxi for elements of equal size. self.dx_dxi = af.mean( wave_equation.dx_dxi_numerical(self.element_mesh_nodes[0:2], self.xi_LGL)) # The value of time-step. self.delta_t = self.delta_x / (4 * c) # Array of timesteps seperated by delta_t. self.time = utils.linspace( 0, int(total_time / self.delta_t) * self.delta_t, int(total_time / self.delta_t)) # Initializing the amplitudes. Change u_init to required initial conditions. if (wave == 'sin'): self.u_init = af.sin(2 * np.pi * self.element_LGL) if (wave == 'gaussian'): self.u_init = np.e**(-(self.element_LGL)**2 / 0.4**2) self.test_array = af.np_to_af_array(np.array(self.u_init)) # The parameters below are for 2D advection # ----------------------------------------- ######################################################################## #######################2D Wave Equation################################# ######################################################################## self.xi_i = af.flat(af.transpose(af.tile(self.xi_LGL, 1, N_LGL))) self.eta_j = af.tile(self.xi_LGL, N_LGL) self.dLp_xi_ij = af.moddims( af.reorder( af.tile(utils.polyval_1d(self.dl_dxi_coeffs, self.xi_i), 1, 1, N_LGL), 1, 2, 0), N_LGL**2, 1, N_LGL**2) self.Lp_xi_ij = af.moddims( af.reorder( af.tile(utils.polyval_1d(self.lagrange_coeffs, self.xi_i), 1, 1, N_LGL), 1, 2, 0), N_LGL**2, 1, N_LGL**2) self.dLq_eta_ij = af.tile( af.reorder(utils.polyval_1d(self.dl_dxi_coeffs, self.eta_j), 1, 2, 0), 1, 1, N_LGL) self.Lq_eta_ij = af.tile( af.reorder(utils.polyval_1d(self.lagrange_coeffs, self.eta_j), 1, 2, 0), 1, 1, N_LGL) self.dLp_Lq = self.Lq_eta_ij * self.dLp_xi_ij self.dLq_Lp = self.Lp_xi_ij * self.dLq_eta_ij self.Li_Lj_coeffs = wave_equation_2d.Li_Lj_coeffs(N_LGL) self.delta_y = self.delta_x self.delta_t_2d = courant * self.delta_x * self.delta_y \ / (self.delta_x * c_x + self.delta_y * c_y) self.c_lax_2d_x = c_x self.c_lax_2d_y = c_y self.nodes, self.elements = msh_parser.read_order_2_msh(mesh_file) self.x_e_ij = af.np_to_af_array( np.zeros([N_LGL * N_LGL, len(self.elements)])) self.y_e_ij = af.np_to_af_array( np.zeros([N_LGL * N_LGL, len(self.elements)])) for element_tag, element in enumerate(self.elements): self.x_e_ij[:, element_tag] = isoparam.isoparam_x_2D( self.nodes[element, 0], self.xi_i, self.eta_j) self.y_e_ij[:, element_tag] = isoparam.isoparam_y_2D( self.nodes[element, 1], self.xi_i, self.eta_j) self.u_e_ij = af.sin(self.x_e_ij * 2 * np.pi + self.y_e_ij * 4 * np.pi) # Array of timesteps seperated by delta_t. self.time_2d = utils.linspace( 0, int(total_time_2d / self.delta_t_2d) * self.delta_t_2d, int(total_time_2d / self.delta_t_2d)) self.sqrt_det_g = wave_equation_2d.sqrt_det_g(self.nodes[self.elements[0]][:, 0], \ self.nodes[self.elements[0]][:, 1], np.array(self.xi_i), np.array(self.eta_j)) self.elements_nodes = (af.reorder( af.transpose(af.np_to_af_array(self.nodes[self.elements[:]])), 0, 2, 1)) self.sqrt_g = af.reorder(wave_equation_2d.trial_sqrt_det_g(self.elements_nodes[:, 0, :],\ self.elements_nodes[:, 1, :], self.xi_i, self.eta_j), 0, 2, 1) return