Beispiel #1
0
def test_poly1d_prod():
    '''
    Checks the product of the polynomials of different degrees using the
    poly1d_product function and compares it to the analytically calculated
    product coefficients.
    '''

    N = 3

    N_a = 3
    poly_a = af.range(N * N_a, dtype=af.Dtype.u32)
    poly_a = af.moddims(poly_a, d0=N, d1=N_a)

    N_b = 2
    poly_b = af.range(N * N_b, dtype=af.Dtype.u32)
    poly_b = af.moddims(poly_b, d0=N, d1=N_b)

    ref_poly = af.np_to_af_array(
        np.array([[0., 0., 9., 18.], [1., 8., 23., 28.], [4., 20., 41., 40.]]))

    test_poly1d_prod = utils.poly1d_product(poly_a, poly_b)
    test_poly1d_prod_commutative = utils.poly1d_product(poly_b, poly_a)

    diff = af.abs(test_poly1d_prod - ref_poly)
    diff_commutative = af.abs(test_poly1d_prod_commutative - ref_poly)

    assert af.all_true(diff == 0.) and af.all_true(diff_commutative == 0.)
Beispiel #2
0
def test_integrate_1d():
    '''
    Tests the ``integrate_1d`` by comparing the integral agains the
    analytically calculated integral. The polynomials to be integrated
    are all the Lagrange polynomials obtained for the LGL points.
    
    The analytical integral is calculated in this `sage worksheet`_
    
    .. _sage worksheet: https://goo.gl/1uYyNJ
    '''

    threshold = 1e-12

    N_LGL = 8
    xi_LGL = lagrange.LGL_points(N_LGL)
    eta_LGL = lagrange.LGL_points(N_LGL)
    _, Li_xi = lagrange.lagrange_polynomials(xi_LGL)
    _, Lj_eta = lagrange.lagrange_polynomials(eta_LGL)

    Li_xi = af.np_to_af_array(Li_xi)
    Lp_xi = Li_xi.copy()

    Li_Lp = utils.poly1d_product(Li_xi, Lp_xi)

    test_integral_gauss = utils.integrate_1d(Li_Lp, order=9, scheme='gauss')

    test_integral_lobatto = utils.integrate_1d(Li_Lp,
                                               order=N_LGL + 1,
                                               scheme='lobatto')

    ref_integral = af.np_to_af_array(
        np.array([
            0.0333333333333, 0.196657278667, 0.318381179651, 0.384961541681,
            0.384961541681, 0.318381179651, 0.196657278667, 0.0333333333333
        ]))

    diff_gauss = af.abs(ref_integral - test_integral_gauss)
    diff_lobatto = af.abs(ref_integral - test_integral_lobatto)

    assert af.all_true(diff_gauss < threshold) and af.all_true(
        diff_lobatto < threshold)
Beispiel #3
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
Beispiel #4
0
def A_matrix(N_LGL, advec_var):
    '''
    Calculates the tensor product for the given ``params.N_LGL``.
    A tensor product element is given by:

    .. math:: [A^{pq}_{ij}] = \\iint L_p(\\xi) L_q(\\eta) \\
                                     L_i(\\xi) L_j(\\eta) d\\xi d\\eta

    This function finds :math:`L_p(\\xi) L_i(\\xi)` and
    :math:`L_q(\\eta) L_j(\\eta)` and passes it to the ``integrate_2d``
    function.

    Returns
    -------
    A : af.Array [N_LGL^2 N_LGL^2 1 1]
        The tensor product.
    '''
    xi_LGL = lagrange.LGL_points(N_LGL)
    lagrange_coeffs = af.np_to_af_array(
        lagrange.lagrange_polynomials(xi_LGL)[1])

    xi_LGL = lagrange.LGL_points(N_LGL)
    eta_LGL = lagrange.LGL_points(N_LGL)

    _, Lp_xi = lagrange.lagrange_polynomials(xi_LGL)
    _, Lq_eta = lagrange.lagrange_polynomials(eta_LGL)
    Lp_xi = af.np_to_af_array(Lp_xi)
    Lq_eta = af.np_to_af_array(Lq_eta)
    Li_xi = Lp_xi.copy()
    Lj_eta = Lq_eta.copy()

    Lp_xi_tp = af.reorder(Lp_xi, d0=2, d1=0, d2=1)
    Lp_xi_tp = af.tile(Lp_xi_tp, d0=N_LGL * N_LGL * N_LGL)
    Lp_xi_tp = af.moddims(Lp_xi_tp,
                          d0=N_LGL * N_LGL * N_LGL * N_LGL,
                          d1=1,
                          d2=N_LGL)
    Lp_xi_tp = af.reorder(Lp_xi_tp, d0=0, d1=2, d2=1)

    Lq_eta_tp = af.reorder(Lq_eta, d0=0, d1=2, d2=1)
    Lq_eta_tp = af.tile(Lq_eta_tp, d0=N_LGL, d1=N_LGL * N_LGL)
    Lq_eta_tp = af.moddims(af.transpose(Lq_eta_tp),
                           d0=N_LGL * N_LGL * N_LGL * N_LGL,
                           d1=1,
                           d2=N_LGL)
    Lq_eta_tp = af.reorder(Lq_eta_tp, d0=0, d1=2, d2=1)

    Li_xi_tp = af.reorder(Li_xi, d0=2, d1=0, d2=1)
    Li_xi_tp = af.tile(Li_xi_tp, d0=N_LGL)
    Li_xi_tp = af.moddims(Li_xi_tp, d0=N_LGL * N_LGL, d1=1, d2=N_LGL)
    Li_xi_tp = af.reorder(Li_xi_tp, d0=0, d1=2, d2=1)
    Li_xi_tp = af.tile(Li_xi_tp, d0=N_LGL * N_LGL)

    Lj_eta_tp = af.reorder(Lj_eta, d0=0, d1=2, d2=1)
    Lj_eta_tp = af.tile(Lj_eta_tp, d0=N_LGL)
    Lj_eta_tp = af.reorder(Lj_eta_tp, d0=0, d1=2, d2=1)
    Lj_eta_tp = af.tile(Lj_eta_tp, d0=N_LGL * N_LGL)

    Lp_Li_tp = utils.poly1d_product(Lp_xi_tp, Li_xi_tp)
    Lq_Lj_tp = utils.poly1d_product(Lq_eta_tp, Lj_eta_tp)

    Lp_Li_Lq_Lj_tp = utils.polynomial_product_coeffs(
        af.reorder(Lp_Li_tp, d0=1, d1=2, d2=0),
        af.reorder(Lq_Lj_tp, d0=1, d1=2, d2=0))

    A = utils.integrate_2d_multivar_poly(Lp_Li_Lq_Lj_tp, params.N_quad,
                                         'gauss', advec_var)

    A = af.moddims(A, d0=N_LGL * N_LGL, d1=N_LGL * N_LGL)

    return A