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)
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
    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