def test_isoparam_x(): ''' This test tests the function ``isoparam_x`` function. It uses a list of analytically calculated values at this sage worksheet `isoparam.sagews`_ for an element at :math:`5` random :math:`(\\xi, \\eta)` coordinates and finds the :math:`L_1` norm of the :math:`x` coordinates got by the ``isoparam_x`` function. .. _isoparam.sagews: https://goo.gl/3EP3Pg ''' threshold = 1e-7 x_nodes = (np.array([0., 0.2, 0., 0.5, 1., 0.8, 1., 0.5])) y_nodes = (np.array([1., 0.5, 0., 0.2, 0., 0.5, 1., 0.8])) xi = np.array( [-0.71565335, -0.6604077, -0.87006188, -0.59216134, 0.73777285]) eta = np.array( [-0.76986362, 0.62167345, -0.38380703, 0.85833585, 0.92388897]) Xi, Eta = np.meshgrid(xi, eta) Xi = af.np_to_af_array(Xi) Eta = af.np_to_af_array(Eta) x = isoparam.isoparam_x_2D(x_nodes, Xi, Eta) y = isoparam.isoparam_y_2D(y_nodes, Xi, Eta) test_x = af.np_to_af_array(np.array( \ [[ 0.20047188, 0.22359428, 0.13584604, 0.25215798, 0.80878597], [ 0.22998716, 0.2508311 , 0.1717295 , 0.27658015, 0.77835843], [ 0.26421973, 0.28242104, 0.21334805, 0.3049056 , 0.7430678 ], [ 0.17985384, 0.20456788, 0.11077948, 0.23509776, 0.83004127], [ 0.16313183, 0.18913674, 0.09044955, 0.22126127, 0.84728013]])) test_y = af.np_to_af_array( np.array([[0.19018229, 0.20188751, 0.15248238, 0.2150496, 0.18523221], [0.75018125, 0.74072916, 0.78062435, 0.73010062, 0.7541785], [0.34554379, 0.3513793, 0.32674892, 0.35794112, 0.34307598], [0.84542176, 0.83237139, 0.88745412, 0.81769672, 0.8509407], [0.87180243, 0.85775537, 0.9170449, 0.84195996, 0.87774287]])) L1norm_x_test_x = np.abs(x - test_x).sum() L1norm_y_test_y = np.abs(y - test_y).sum() assert (L1norm_x_test_x < threshold) & (L1norm_y_test_y < threshold)
def plot_element_boundary(x_nodes, y_nodes, axes_handler, grid_width=2., grid_color='blue', print_node_tag=False, node_tag_fontsize=12): ''' Plots the boundary of a given :math:`2^{nd}` order element. Parameters ---------- x_nodes : np.ndarray [8] :math:`x` nodes of the element. y_nodes : np.ndarray [8] :math:`y` nodes of the element. axes_handler : matplotlib.axes.Axes The plot handler being used to plot the element grid. You may generate it by calling the function ``pyplot.axes()``. grid_width : float Grid line width. grid_color : str Grid line color. Returns ------- None ''' xi = np.linspace(-1, 1, 20) eta = np.linspace(-1, 1, 20) left_edge = np.zeros([xi.size, 2]) bottom_edge = np.zeros([xi.size, 2]) right_edge = np.zeros([xi.size, 2]) top_edge = np.zeros([xi.size, 2]) left_edge[:, 0] = isoparam.isoparam_x_2D(x_nodes, -1., eta) bottom_edge[:, 0] = isoparam.isoparam_x_2D(x_nodes, xi, -1) right_edge[:, 0] = isoparam.isoparam_x_2D(x_nodes, 1., eta) top_edge[:, 0] = isoparam.isoparam_x_2D(x_nodes, xi, 1.) left_edge[:, 1] = isoparam.isoparam_y_2D(y_nodes, -1., eta) bottom_edge[:, 1] = isoparam.isoparam_y_2D(y_nodes, xi, -1) right_edge[:, 1] = isoparam.isoparam_y_2D(y_nodes, 1., eta) top_edge[:, 1] = isoparam.isoparam_y_2D(y_nodes, xi, 1.) # Plot edges utils.plot_line(left_edge, axes_handler, grid_width, grid_color) utils.plot_line(bottom_edge, axes_handler, grid_width, grid_color) utils.plot_line(right_edge, axes_handler, grid_width, grid_color) utils.plot_line(top_edge, axes_handler, grid_width, grid_color) return
def plot_element_grid(x_nodes, y_nodes, xi_LGL, eta_LGL, axes_handler, grid_width=1., grid_color='red'): ''' Uses the :math:`\\xi_{LGL}` and :math:`\\eta_{LGL}` points to plot a grid in the :math:`x-y` plane using the points corresponding to the :math:`(\\xi_{LGL}, \\eta_{LGL})` points. **Usage** .. code-block:: python :linenos: # Plots a grid for an element using 8 LGL points N_LGL = 8 xi_LGL = lagrange.LGL_points(N) eta_LGL = lagrange.LGL_points(N) # 8 x_nodes and y_nodes of an element x_nodes = [0., 0., 0., 0.5, 1., 1., 1., 0.5] y_nodes = [1., 0.5, 0., 0., 0., 0.5, 1., 1.] axes_handler = pyplot.axes() msh_parser.plot_element_grid(x_nodes, y_nodes, xi_LGL, eta_LGL, axes_handler) pyplot.title(r'Gird plot of an element.') pyplot.xlabel(r'$x$') pyplot.ylabel(r'$y$') pyplot.xlim(-.1, 1.1) pyplot.ylim(-.1, 1.1) pyplot.show() Parameters ---------- x_nodes : np.array [8] x_nodes of the element. y_nodes : np.array [8] y_nodes of the element. xi_LGL : np.array [N_LGL] LGL points on the :math:`\\xi` axis eta_LGL : np.array [N_LGL] LGL points on the :math:`\\eta` axis axes_handler : matplotlib.axes.Axes The plot handler being used to plot the element grid. You may generate it by calling the function pyplot.axes() grid_width : float Grid line width. grid_color : str Grid line color. Returns ------- None ''' axes_handler.set_aspect('equal') N = xi_LGL.shape[0] xy_map = np.ndarray((N, N, 2), float) for m in np.arange(N): for n in np.arange(N): xy_map[m][n][0] = isoparam.isoparam_x_2D(x_nodes, xi_LGL[m], eta_LGL[n]) xy_map[m][n][1] = isoparam.isoparam_y_2D(y_nodes, xi_LGL[m], eta_LGL[n]) array3d = xy_map.copy() N = array3d.shape[0] #Plot the vertical lines for m in np.arange(0, N): for n in np.arange(1, N): line = [array3d[m][n].tolist(), array3d[m][n - 1].tolist()] (line1_xs, line1_ys) = zip(*line) axes_handler.add_line( lines.Line2D(line1_xs, line1_ys, linewidth=grid_width, color=grid_color)) #Plot the horizontal lines for n in np.arange(0, N): for m in np.arange(1, N): line = [array3d[m][n].tolist(), array3d[m - 1][n].tolist()] (line1_xs, line1_ys) = zip(*line) axes_handler.add_line( lines.Line2D(line1_xs, line1_ys, linewidth=grid_width, color=grid_color)) 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