예제 #1
0
def A_matrix():
    '''

    Calculates A matrix whose elements :math:`A_{p i}` are given by
    :math:`A_{pi} = \\int^1_{-1} L_p(\\xi)L_i(\\xi) \\frac{dx}{d\\xi}`

    The integrals are computed using the integrate() function.
    Since elements are taken to be of equal size, :math:`\\frac {dx}{d\\xi}`
    is same everywhere
    
    Returns
    -------

    A_matrix : arrayfire.Array [N_LGL N_LGL 1 1]
               The value of integral of product of lagrange basis functions
               obtained by LGL points, using the integrate() function

    '''
    # Coefficients of Lagrange basis polynomials.
    lagrange_coeffs = params.lagrange_coeffs
    lagrange_coeffs = af.reorder(lagrange_coeffs, 1, 2, 0)

    # Coefficients of product of Lagrange basis polynomials.
    lag_prod_coeffs = af.convolve1(lagrange_coeffs,\
                                   af.reorder(lagrange_coeffs, 0, 2, 1),\
                                   conv_mode=af.CONV_MODE.EXPAND)
    lag_prod_coeffs = af.reorder(lag_prod_coeffs, 1, 2, 0)
    lag_prod_coeffs = af.moddims(lag_prod_coeffs, params.N_LGL**2,
                                 2 * params.N_LGL - 1)

    dx_dxi = params.dx_dxi
    A_matrix = dx_dxi * af.moddims(lagrange.integrate(lag_prod_coeffs),\
                                             params.N_LGL, params.N_LGL)

    return A_matrix
예제 #2
0
def test_integrate():
    '''
    Testing the integrate() function by passing coefficients
    of a polynomial and comparing it to the analytical result.
    '''
    threshold = 1e-14

    params.N_LGL = 8
    params.N_quad = 10
    params.N_Elements = 10
    wave = 'gaussian'

    gv = global_variables.advection_variables(params.N_LGL, params.N_quad,\
                                          params.x_nodes, params.N_Elements,\
                                          params.c, params.total_time, wave,\
                                          params.c_x, params.c_y, params.courant,\
                                          params.mesh_file, params.total_time_2d)

    test_coeffs = af.np_to_af_array(np.array([7., 6, 4, 2, 1, 3, 9, 2]))
    # The coefficients of a test polynomial
    # `7x^7 + 6x^6 + 4x^5 + 2x^4 + x^3 + 3x^2 + 9x + 2`

    # Using integrate() function.

    calculated_integral = lagrange.integrate(af.transpose(test_coeffs), gv)

    analytical_integral = 8.514285714285714

    assert (calculated_integral - analytical_integral) <= threshold
예제 #3
0
def test_integrate():
    '''
    Testing the integrate() function by passing coefficients
    of a polynomial and comparing it to the analytical result.
    '''
    threshold = 1e-14

    test_coeffs = af.np_to_af_array(np.array([7., 6, 4, 2, 1, 3, 9, 2]))
    # The coefficients of a test polynomial
    # `7x^7 + 6x^6 + 4x^5 + 2x^4 + x^3 + 3x^2 + 9x + 2`

    # Using integrate() function.

    calculated_integral = lagrange.integrate(af.transpose(test_coeffs))

    analytical_integral = 8.514285714285714

    assert (calculated_integral - analytical_integral) <= threshold
예제 #4
0
def volume_integral_flux(u_n):
    '''
    Calculates the volume integral of flux in the wave equation.
    :math:`\\int_{-1}^1 f(u) \\frac{d L_p}{d\\xi} d\\xi`
    This will give N values of flux integral as p varies from 0 to N - 1.
    
    This integral is carried out using the analytical form of the integrand
    obtained as a linear combination of Lagrange basis polynomials.
    This integrand is the used in the integrate() function.
    Calculation of volume integral flux using N_LGL Lobatto quadrature points
    can be vectorized and is much faster.
    
    Parameters
    ----------
    u : arrayfire.Array [N_LGL N_Elements M 1]
        Amplitude of the wave at the mapped LGL nodes of each element. This
        function can computer flux for :math:`M` :math:`u`.
            
    Returns
    -------
    flux_integral : arrayfire.Array [N_LGL N_Elements M 1]
                    Value of the volume integral flux. It contains the integral
                    of all N_LGL * N_Element integrands.
    '''
    shape_u_n = utils.shape(u_n)
    
    # The coefficients of dLp / d\xi
    diff_lag_coeff  = params.dl_dxi_coeffs

    lobatto_nodes   = params.lobatto_quadrature_nodes
    Lobatto_weights = params.lobatto_weights_quadrature

    #nodes_tile   = af.transpose(af.tile(lobatto_nodes, 1, diff_lag_coeff.shape[1]))
    #power        = af.flip(af.range(diff_lag_coeff.shape[1]))
    #power_tile   = af.tile(power, 1, params.N_quad)
    #nodes_power  = nodes_tile ** power_tile
    #weights_tile = af.transpose(af.tile(Lobatto_weights, 1, diff_lag_coeff.shape[1]))
    #nodes_weight = nodes_power * weights_tile

    #dLp_dxi      = af.matmul(diff_lag_coeff, nodes_weight)
    
    dLp_dxi      = af.np_to_af_array(params.b_matrix)


    # The first option to calculate the volume integral term, directly uses
    # the Lobatto quadrature instead of using the integrate() function by
    # passing the coefficients of the Lagrange interpolated polynomial.
    if(params.volume_integral_scheme == 'lobatto_quadrature' \
        and params.N_quad == params.N_LGL):

        # Flux using u_n, reordered to 1 X N_LGL X N_Elements array.
        F_u_n                  = af.reorder(flux_x(u_n), 3, 0, 1, 2)
        F_u_n = af.tile(F_u_n, d0 = params.N_LGL)

        # Multiplying with dLp / d\xi
        integral_expansion     = af.broadcast(utils.multiply,
                                            dLp_dxi, F_u_n)

    #     # Using the quadrature rule.
        flux_integral = af.sum(integral_expansion, 1)

        flux_integral = af.reorder(flux_integral, 0, 2, 3, 1)

    # Using the integrate() function to calculate the volume integral term
    # by passing the Lagrange interpolated polynomial.
    else:
        #print('option3')
        analytical_flux_coeffs = af.transpose(af.moddims(u_n,
                                                        d0 = params.N_LGL,
                                                        d1 = params.N_Elements \
                                                            * shape_u_n[2]))
        
        analytical_flux_coeffs = flux_x(
            lagrange.lagrange_interpolation(analytical_flux_coeffs))
        analytical_flux_coeffs = af.transpose(
            af.moddims(af.transpose(analytical_flux_coeffs),
                       d0 = params.N_LGL, d1 = params.N_Elements,
                       d2 = shape_u_n[2]))
        
        analytical_flux_coeffs = af.reorder(analytical_flux_coeffs,
                                            d0 = 3, d1 = 1, d2 = 0, d3 = 2)
        analytical_flux_coeffs = af.tile(analytical_flux_coeffs,
                                         d0 = params.N_LGL)
        analytical_flux_coeffs = af.moddims(
            af.transpose(analytical_flux_coeffs),
            d0 = params.N_LGL,
            d1 = params.N_LGL * params.N_Elements, d2 = 1,
            d3 = shape_u_n[2])
        
        analytical_flux_coeffs = af.moddims(
            analytical_flux_coeffs, d0 = params.N_LGL,
            d1 = params.N_LGL * params.N_Elements * shape_u_n[2],
            d2 = 1, d3 = 1)
        
        analytical_flux_coeffs = af.transpose(analytical_flux_coeffs)

        dl_dxi_coefficients    = af.tile(af.tile(params.dl_dxi_coeffs,
                                                 d0 = params.N_Elements), \
                                         d0 = shape_u_n[2])

        volume_int_coeffs = utils.poly1d_product(dl_dxi_coefficients,
                                                analytical_flux_coeffs)
        
        flux_integral = lagrange.integrate(volume_int_coeffs)
        flux_integral = af.moddims(af.transpose(flux_integral),
                                   d0 = params.N_LGL,
                                   d1 = params.N_Elements,
                                   d2 = shape_u_n[2])

    return flux_integral
예제 #5
0
def surface_term_vectorized(u, advec_var):
    '''
    '''
    lagrange_coeffs = advec_var.lagrange_coeffs
    N_LGL = params.N_LGL

    eta_LGL = advec_var.xi_LGL

    f_xi_surface_term = lax_friedrichs_flux(u, advec_var)[0]
    f_eta_surface_term = lax_friedrichs_flux(u, advec_var)[1]

    Lp_xi = af.moddims(
        af.reorder(
            af.tile(utils.polyval_1d(lagrange_coeffs, advec_var.xi_LGL), 1, 1,
                    params.N_LGL), 1, 2, 0), params.N_LGL, 1, params.N_LGL**2)

    Lq_eta  = af.tile(af.reorder(utils.polyval_1d(lagrange_coeffs,\
                         eta_LGL), 1, 2, 0), 1, 1, params.N_LGL)

    Lp_xi_1      = af.moddims(af.reorder(af.tile(utils.polyval_1d(lagrange_coeffs, advec_var.xi_LGL[-1]),\
                           1, 1, params.N_LGL), 2, 1, 0), 1, 1, params.N_LGL ** 2)
    Lp_xi_minus1 = af.moddims(af.reorder(af.tile(utils.polyval_1d(lagrange_coeffs, advec_var.xi_LGL[0]),\
                           1, 1, params.N_LGL), 2, 1, 0), 1, 1, params.N_LGL ** 2)

    Lq_eta_1      = af.moddims(af.tile(af.reorder(utils.polyval_1d(lagrange_coeffs,\
                            eta_LGL[-1]), 0, 2, 1), 1, 1, params.N_LGL), 1, 1, params.N_LGL ** 2)
    Lq_eta_minus1 = af.moddims(af.tile(af.reorder(utils.polyval_1d(lagrange_coeffs,\
                             eta_LGL[0]), 0, 2, 1), 1, 1, params.N_LGL), 1, 1, params.N_LGL ** 2)

    # xi = 1 boundary
    Lq_eta_1_boundary = af.broadcast(utils.multiply, Lq_eta, Lp_xi_1)
    Lq_eta_F_1_boundary = af.broadcast(utils.multiply, Lq_eta_1_boundary,\
                             f_xi_surface_term[-params.N_LGL:, :] * advec_var.sqrt_g[-params.N_LGL:, :])
    Lq_eta_F_1_boundary = af.reorder(Lq_eta_F_1_boundary, 0, 3, 2, 1)

    lag_interpolation_1 = af.sum(
        af.broadcast(utils.multiply, lagrange_coeffs, Lq_eta_F_1_boundary), 0)
    lag_interpolation_1 = af.reorder(lag_interpolation_1, 2, 1, 3, 0)
    lag_interpolation_1 = af.transpose(af.moddims(af.transpose(lag_interpolation_1),\
                                       params.N_LGL, params.N_LGL ** 2 * 100))

    surface_term_pq_xi_1 = lagrange.integrate(
        lag_interpolation_1, advec_var) * np.mean(advec_var.sqrt_det_g)
    surface_term_pq_xi_1 = af.moddims(surface_term_pq_xi_1, params.N_LGL**2,
                                      100)

    # xi = -1 boundary
    Lq_eta_minus1_boundary = af.broadcast(utils.multiply, Lq_eta, Lp_xi_minus1)
    Lq_eta_F_minus1_boundary = af.broadcast(utils.multiply, Lq_eta_minus1_boundary,\
                               f_xi_surface_term[:params.N_LGL, :] * advec_var.sqrt_g[:params.N_LGL, :])
    Lq_eta_F_minus1_boundary = af.reorder(Lq_eta_F_minus1_boundary, 0, 3, 2, 1)

    lag_interpolation_2 = af.sum(
        af.broadcast(utils.multiply, lagrange_coeffs,
                     Lq_eta_F_minus1_boundary), 0)
    lag_interpolation_2 = af.reorder(lag_interpolation_2, 2, 1, 3, 0)
    lag_interpolation_2 = af.transpose(af.moddims(af.transpose(lag_interpolation_2),\
                                       params.N_LGL, params.N_LGL ** 2 * 100))

    surface_term_pq_xi_minus1 = lagrange.integrate(lag_interpolation_2,
                                                   advec_var)

    surface_term_pq_xi_minus1 = af.moddims(surface_term_pq_xi_minus1,
                                           params.N_LGL**2, 100)

    # eta = -1 boundary
    Lp_xi_minus1_boundary = af.broadcast(utils.multiply, Lp_xi, Lq_eta_minus1)
    Lp_xi_F_minus1_boundary = af.broadcast(utils.multiply, Lp_xi_minus1_boundary,\
                              f_eta_surface_term[0:-params.N_LGL + 1:params.N_LGL]\
                              * advec_var.sqrt_g[0:-params.N_LGL + 1:params.N_LGL])
    Lp_xi_F_minus1_boundary = af.reorder(Lp_xi_F_minus1_boundary, 0, 3, 2, 1)

    lag_interpolation_3 = af.sum(
        af.broadcast(utils.multiply, lagrange_coeffs, Lp_xi_F_minus1_boundary),
        0)
    lag_interpolation_3 = af.reorder(lag_interpolation_3, 2, 1, 3, 0)
    lag_interpolation_3 = af.transpose(af.moddims(af.transpose(lag_interpolation_3),\
                                       params.N_LGL, params.N_LGL ** 2 * 100))

    surface_term_pq_eta_minus1 = lagrange.integrate(lag_interpolation_3,
                                                    advec_var)

    surface_term_pq_eta_minus1 = af.moddims(surface_term_pq_eta_minus1,
                                            params.N_LGL**2, 100)

    # eta = 1 boundary
    Lp_xi_1_boundary = af.broadcast(utils.multiply, Lp_xi, Lq_eta_1)
    Lp_xi_F_1_boundary = af.broadcast(utils.multiply, Lp_xi_1_boundary,\
                         f_eta_surface_term[params.N_LGL - 1:params.N_LGL ** 2:params.N_LGL]\
                         * advec_var.sqrt_g[params.N_LGL - 1:params.N_LGL ** 2:params.N_LGL])
    Lp_xi_F_1_boundary = af.reorder(Lp_xi_F_1_boundary, 0, 3, 2, 1)

    lag_interpolation_4 = af.sum(
        af.broadcast(utils.multiply, lagrange_coeffs, Lp_xi_F_1_boundary), 0)
    lag_interpolation_4 = af.reorder(lag_interpolation_4, 2, 1, 3, 0)
    lag_interpolation_4 = af.transpose(af.moddims(af.transpose(lag_interpolation_4),\
                                       params.N_LGL, params.N_LGL ** 2 * 100))

    surface_term_pq_eta_1 = lagrange.integrate(lag_interpolation_4, advec_var)

    surface_term_pq_eta_1 = af.moddims(surface_term_pq_eta_1, params.N_LGL**2,
                                       100)

    surface_term_e_pq = surface_term_pq_xi_1\
                      - surface_term_pq_xi_minus1\
                      + surface_term_pq_eta_1\
                      - surface_term_pq_eta_minus1

    return surface_term_e_pq