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
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
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
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
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