Beispiel #1
0
def integrate(integrand_coeffs):
    '''
    Performs integration according to the given quadrature method
    by taking in the coefficients of the polynomial and the number of
    quadrature points.
    The number of quadrature points and the quadrature scheme are set
    in params.py module.
    
    Parameters
    ----------
    
    integrand_coeffs : arrayfire.Array [M N 1 1]
                       The coefficients of M number of polynomials of order N
                       arranged in a 2D array.
    Returns
    -------
    
    Integral : arrayfire.Array [M 1 1 1]
               The value of the definite integration performed using the
               specified quadrature method for M polynomials.

    '''

    integrand = integrand_coeffs

    if (params.scheme == 'gauss_quadrature'):
        #print('gauss_quad')

        gaussian_nodes = params.gauss_points
        Gauss_weights = params.gauss_weights

        nodes_tile = af.transpose(
            af.tile(gaussian_nodes, 1, integrand.shape[1]))
        power = af.flip(af.range(integrand.shape[1]))
        nodes_power = af.broadcast(utils.power, nodes_tile, power)
        weights_tile = af.transpose(
            af.tile(Gauss_weights, 1, integrand.shape[1]))
        nodes_weight = nodes_power * weights_tile

        value_at_gauss_nodes = af.matmul(integrand, nodes_weight)
        integral = af.sum(value_at_gauss_nodes, 1)

    if (params.scheme == 'lobatto_quadrature'):
        #print('lob_quad')

        lobatto_nodes = params.lobatto_quadrature_nodes
        Lobatto_weights = params.lobatto_weights_quadrature

        nodes_tile = af.transpose(af.tile(lobatto_nodes, 1,
                                          integrand.shape[1]))
        power = af.flip(af.range(integrand.shape[1]))
        nodes_power = af.broadcast(utils.power, nodes_tile, power)
        weights_tile = af.transpose(
            af.tile(Lobatto_weights, 1, integrand.shape[1]))
        nodes_weight = nodes_power * weights_tile

        value_at_lobatto_nodes = af.matmul(integrand, nodes_weight)
        integral = af.sum(value_at_lobatto_nodes, 1)

    return integral
Beispiel #2
0
def polyval_2d(poly_2d, xi, eta):
    '''
    '''
    poly_2d_shape = poly_2d.shape
    poly_xy = af.tile(poly_2d, d0 = 1, d1 = 1, d2 = 1, d3 = xi.shape[0])
    poly_xy_shape = poly_xy.shape
    # print(poly_xy)

    xi_power = af.flip(af.range(poly_xy_shape[1], dtype = af.Dtype.u32))
    xi_power = af.tile(af.transpose(xi_power), d0 = poly_xy_shape[0])
    xi_power = af.tile(xi_power, d0 = 1, d1 = 1, d2 = xi.shape[0])

    eta_power = af.flip(af.range(poly_xy_shape[0], dtype = af.Dtype.u32))
    eta_power = af.tile(eta_power, d0 = 1, d1 = poly_xy_shape[1])
    eta_power = af.tile(eta_power, d0 = 1, d1 = 1, d2 = eta.shape[0])

    Xi = af.reorder(xi, d0 = 2, d1 = 1, d2 = 0)
    Xi = af.tile(Xi, d0 = poly_xy_shape[0], d1 = poly_xy_shape[1])
    Xi = af.pow(Xi, xi_power)
    Xi = af.reorder(Xi, d0 = 0, d1 = 1, d2 = 3, d3 = 2)
    # print(Xi)

    Eta = af.reorder(eta, d0 = 2, d1 = 1, d2 = 0)
    Eta = af.tile(Eta, d0 = poly_xy_shape[0], d1 = poly_xy_shape[1])
    Eta = af.pow(Eta, eta_power)
    Eta = af.reorder(Eta, d0 = 0, d1 = 1, d2 = 3, d3 = 2)
    # print(Eta)

    Xi_Eta = Xi * Eta

    poly_val = af.broadcast(multiply, poly_xy, Xi_Eta)
    poly_val = af.sum(af.sum(poly_val, dim = 1), dim = 0)
    poly_val = af.reorder(poly_val, d0 = 2, d1 = 3, d2 = 0, d3 = 1)

    return poly_val
Beispiel #3
0
def simple_data(verbose=False):
    display_func = _util.display_func(verbose)

    display_func(af.constant(100, 3, 3, dtype=af.Dtype.f32))
    display_func(af.constant(25, 3, 3, dtype=af.Dtype.c32))
    display_func(af.constant(2**50, 3, 3, dtype=af.Dtype.s64))
    display_func(af.constant(2+3j, 3, 3))
    display_func(af.constant(3+5j, 3, 3, dtype=af.Dtype.c32))

    display_func(af.range(3, 3))
    display_func(af.iota(3, 3, tile_dims=(2, 2)))

    display_func(af.identity(3, 3, 1, 2, af.Dtype.b8))
    display_func(af.identity(3, 3, dtype=af.Dtype.c32))

    a = af.randu(3, 4)
    b = af.diag(a, extract=True)
    c = af.diag(a, 1, extract=True)

    display_func(a)
    display_func(b)
    display_func(c)

    display_func(af.diag(b, extract=False))
    display_func(af.diag(c, 1, extract=False))

    display_func(af.join(0, a, a))
    display_func(af.join(1, a, a, a))

    display_func(af.tile(a, 2, 2))

    display_func(af.reorder(a, 1, 0))

    display_func(af.shift(a, -1, 1))

    display_func(af.moddims(a, 6, 2))

    display_func(af.flat(a))

    display_func(af.flip(a, 0))
    display_func(af.flip(a, 1))

    display_func(af.lower(a, False))
    display_func(af.lower(a, True))

    display_func(af.upper(a, False))
    display_func(af.upper(a, True))

    a = af.randu(5, 5)
    display_func(af.transpose(a))
    af.transpose_inplace(a)
    display_func(a)

    display_func(af.select(a > 0.3, a, -0.3))

    af.replace(a, a > 0.3, -0.3)
    display_func(a)

    display_func(af.pad(a, (1, 1, 0, 0), (2, 2, 0, 0)))
Beispiel #4
0
def simple_data(verbose=False):
    display_func = _util.display_func(verbose)
    print_func   = _util.print_func(verbose)

    display_func(af.constant(100, 3,3, dtype=af.Dtype.f32))
    display_func(af.constant(25, 3,3, dtype=af.Dtype.c32))
    display_func(af.constant(2**50, 3,3, dtype=af.Dtype.s64))
    display_func(af.constant(2+3j, 3,3))
    display_func(af.constant(3+5j, 3,3, dtype=af.Dtype.c32))

    display_func(af.range(3, 3))
    display_func(af.iota(3, 3, tile_dims=(2,2)))

    display_func(af.identity(3, 3, 1, 2, af.Dtype.b8))
    display_func(af.identity(3, 3, dtype=af.Dtype.c32))

    a = af.randu(3, 4)
    b = af.diag(a, extract=True)
    c = af.diag(a, 1, extract=True)

    display_func(a)
    display_func(b)
    display_func(c)

    display_func(af.diag(b, extract = False))
    display_func(af.diag(c, 1, extract = False))

    display_func(af.join(0, a, a))
    display_func(af.join(1, a, a, a))

    display_func(af.tile(a, 2, 2))


    display_func(af.reorder(a, 1, 0))

    display_func(af.shift(a, -1, 1))

    display_func(af.moddims(a, 6, 2))

    display_func(af.flat(a))

    display_func(af.flip(a, 0))
    display_func(af.flip(a, 1))

    display_func(af.lower(a, False))
    display_func(af.lower(a, True))

    display_func(af.upper(a, False))
    display_func(af.upper(a, True))

    a = af.randu(5,5)
    display_func(af.transpose(a))
    af.transpose_inplace(a)
    display_func(a)

    display_func(af.select(a > 0.3, a, -0.3))

    af.replace(a, a > 0.3, -0.3)
    display_func(a)
Beispiel #5
0
def polyval_1d(polynomials, xi):
    '''
    Finds the value of the polynomials at the given :math:`\\xi` coordinates.

    Parameters
    ----------
    polynomials : af.Array [number_of_polynomials N 1 1]
                 ``number_of_polynomials`` :math:`2D` polynomials of degree
                 :math:`N - 1` of the form

                 .. math:: P(x) = a_0x^0 + a_1x^1 + ... \\
                           a_{N - 1}x^{N - 1} + a_Nx^N
    xi      : af.Array [N 1 1 1]
              :math:`\\xi` coordinates at which the :math:`i^{th}` Lagrange
              basis polynomial is to be evaluated.

    Returns
    -------
    af.Array [i.shape[0] xi.shape[0] 1 1]
        Evaluated polynomials at given :math:`\\xi` coordinates
    '''

    N = int(polynomials.shape[1])
    xi_ = af.tile(af.transpose(xi), d0=N)
    power = af.tile(af.flip(af.range(N), dim=0), d0=1, d1=xi.shape[0])

    xi_power = xi_**power

    return af.matmul(polynomials, xi_power)
Beispiel #6
0
def test_polyval_2d():
    '''
    Tests the ``utils.polyval_2d`` function by evaluating the polynomial
    
    .. math:: P_0(\\xi) P_1(\\eta)
    
    here,
    
    .. math:: P_0(\\xi) = 3 \, \\xi^{2} + 2 \, \\xi + 1
    
    .. math:: P_1(\\eta) = 3 \, \\eta^{2} + 2 \, \\eta + 1
    
    at corresponding ``linspace`` points in :math:`\\xi \\in [-1, 1]` and
    :math:`\\eta \\in [-1, 1]`.
    
    This value is then compared with the reference value calculated analytically.
    The reference values are calculated in
    `polynomial_product_two_variables.sagews`_
    
    .. _polynomial_product_two_variables.sagews: https://goo.gl/KwG7k9
    
    '''
    threshold = 1e-12

    poly_xi_degree = 4
    poly_xi = af.flip(af.np_to_af_array(np.arange(1, poly_xi_degree)))

    poly_eta_degree = 4
    poly_eta = af.flip(af.np_to_af_array(np.arange(1, poly_eta_degree)))

    poly_xi_eta = utils.polynomial_product_coeffs(poly_xi, poly_eta)

    xi = utils.linspace(-1, 1, 8)
    eta = utils.linspace(-1, 1, 8)

    polyval_xi_eta = af.transpose(utils.polyval_2d(poly_xi_eta, xi, eta))

    polyval_xi_eta_ref = af.np_to_af_array(
        np.array([
            4.00000000000000, 1.21449396084962, 0.481466055810080,
            0.601416076634741, 1.81424406497291, 5.79925031236988,
            15.6751353602663, 36.0000000000000
        ]))

    diff = af.abs(polyval_xi_eta - polyval_xi_eta_ref)

    assert af.all_true(diff < threshold)
Beispiel #7
0
def polynomial_derivative(polynomial):
    '''
    '''
    derivtive_multiplier = af.tile(af.transpose(af.flip(
        af.range(polynomial.shape[1]))),
                                   d0 = polynomial.shape[0])
    
    return (polynomial * derivtive_multiplier)[:, : -1]
Beispiel #8
0
def contour_2d(u, index):
    '''
    '''
    color_levels = np.linspace(-1.1, 1.1, 100)
    u_plot = af.flip(af.moddims(u, params.N_LGL, params.N_LGL, 10, 10), 0)
    x_plot = af.flip(af.moddims(x_e_ij, params.N_LGL, params.N_LGL, 10, 10), 0)
    y_plot = af.flip(af.moddims(y_e_ij, params.N_LGL, params.N_LGL, 10, 10), 0)

    x_contour = af.np_to_af_array(
        np.zeros([params.N_LGL * 10, params.N_LGL * 10]))
    y_contour = af.np_to_af_array(
        np.zeros([params.N_LGL * 10, params.N_LGL * 10]))
    u_contour = af.np_to_af_array(
        np.zeros([params.N_LGL * 10, params.N_LGL * 10]))
    fig = pl.figure()
    #
    for i in range(100):
        p = int(i / 10)
        q = i - p * 10
        x_contour[p * params.N_LGL:params.N_LGL * (p + 1),\
                  q * params.N_LGL:params.N_LGL * (q + 1)] = x_plot[:, :, q, p]

        y_contour[p * params.N_LGL:params.N_LGL * (p + 1),\
                  q * params.N_LGL:params.N_LGL * (q + 1)] = y_plot[:, :, q, p]

        u_contour[p * params.N_LGL:params.N_LGL * (p + 1),\
                  q * params.N_LGL:params.N_LGL * (q + 1)] = u_plot[:, :, q, p]

    x_contour = np.array(x_contour)
    y_contour = np.array(y_contour)
    u_contour = np.array(u_contour)
    pl.contourf(x_contour,
                y_contour,
                u_contour,
                200,
                levels=color_levels,
                cmap='jet')
    pl.gca().set_aspect('equal')
    pl.colorbar()
    pl.title('Time = %.2f' % (index * 10 * delta_t_2d))
    fig.savefig('results/2D_Wave_images/%04d' % (index) + '.png')
    pl.close('all')
    return
def apply_mirror_bcs_fields(self, boundary):

    N_g = self.N_ghost

    if (boundary == 'left'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        self.cell_centered_EM_fields[:, :N_g] = \
            af.flip(self.cell_centered_EM_fields[:, N_g:2 * N_g], 1)

    elif (boundary == 'right'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;

        self.cell_centered_EM_fields[:, -N_g:] = \
            af.flip(self.cell_centered_EM_fields[:, -2 * N_g:-N_g], 1)

    elif (boundary == 'bottom'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;

        self.cell_centered_EM_fields[:, :, :N_g] = \
            af.flip(self.cell_centered_EM_fields[:, :, N_g:2 * N_g], 2)

    elif (boundary == 'top'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;

        self.cell_centered_EM_fields[:, :, -N_g:] = \
            af.flip(self.cell_centered_EM_fields[:, :, -2 * N_g:-N_g], 2)

    else:
        raise Exception('Invalid choice for boundary')

    return
Beispiel #10
0
def dct1(arr, norm=None):
    N = arr.dims()[0]
    out = 2 * af.real(
        af.exp(-0.5j * np.pi / N *
               af.range(*arr.dims(), dim=0, dtype=arr.dtype())) *
        af.fft(af.join(0, arr[0:N:2], af.flip(arr[1:N:2]))))
    if norm == 'ortho':
        out /= np.sqrt(2 * N)
        out[0] /= np.sqrt(2)
    return out
def test_mirror():

    obj = test('mirror', 'mirror')
    obj.f[obj.N_ghost:-obj.N_ghost,obj.N_ghost:-obj.N_ghost] = \
    af.sin(2 * np.pi * obj.q1_center + 4 * np.pi * obj.q2_center)[obj.N_ghost:
                                                                  -obj.N_ghost,
                                                                  obj.N_ghost:
                                                                  -obj.N_ghost
                                                                 ]

    apply_bcs_f(obj)

    expected = af.sin(2 * np.pi * obj.q1_center + 4 * np.pi * obj.q2_center)
    N_g = obj.N_ghost

    expected[:N_g, :] = af.flip(expected[N_g:2 * N_g], 0)
    expected[-N_g:, :] = af.flip(expected[-2 * N_g:-N_g], 0)
    expected[:, -N_g:] = af.flip(expected[:, -2 * N_g:-N_g], 1)
    expected[:, :N_g] = af.flip(expected[:, N_g:2 * N_g], 1)

    assert (af.max(af.abs(obj.f - expected)) < 5e-14)
Beispiel #12
0
def multivariable_poly_value(poly_2d, x, y):
    '''
    '''
    polynomial_coeffs = af.transpose(af.moddims(poly_2d, poly_2d.shape[0] ** 2, poly_2d.shape[2]))

    power_index     = af.flip(af.np_to_af_array(np.arange(poly_2d.shape[0])))
    x_power_indices = af.flat(af.transpose(af.tile(power_index, 1, poly_2d.shape[0])))
    y_power_indices = af.tile(power_index, poly_2d.shape[0])

    x_power = af.broadcast(power, af.transpose(x), x_power_indices)
    y_power = af.broadcast(power, af.transpose(y), y_power_indices)

    polynomial_value = af.matmul(polynomial_coeffs, x_power * y_power)


    return polynomial_value
Beispiel #13
0
def idct1(arr, norm=None):
    N = arr.dims()[0]
    tmp = arr.copy()
    offset = af.tile(tmp[0], N)
    tmp[0] = 0.
    tmp = 2 * af.real(
        af.ifft(
            af.exp(0.5j * np.pi / N *
                   af.range(*arr.dims(), dim=0, dtype=arr.dtype())) * tmp) * N)
    out = af.constant(0, *arr.dims(), dtype=arr.dtype())
    out[0:N:2] = tmp[:N // 2]
    out[1:N:2] = af.flip(tmp[N // 2:])
    if norm == 'ortho':
        offset /= np.sqrt(N)
        out /= np.sqrt(2 * N)
    out += offset
    tmp = offset = None
    return out
Beispiel #14
0
def lagrange_function_value(lagrange_coeff_array):
    '''

    Funtion to calculate the value of lagrange basis functions over LGL
    nodes.

    Parameters
    ----------
    
    lagrange_coeff_array : arrayfire.Array[N_LGL N_LGL 1 1]
                           Contains the coefficients of the
                           Lagrange basis polynomials
    
    Returns
    -------
    
    L_i : arrayfire.Array [N 1 1 1]
          The value of lagrange basis functions calculated over the LGL
          nodes.

    **Examples**
    
    lagrange_function_value(4) gives the value of the four
    Lagrange basis functions evaluated over 4 LGL points
    arranged in a 2D array where Lagrange polynomials
    evaluated at the same LGL point are in the same column.
    
    Also the value lagrange basis functions at LGL points has the property,
    
    L_i(xi_k) = 0 for i != k
              = 1 for i  = k
    
    It follows then that lagrange_function_value returns an identity matrix.
    
    '''
    xi_tile = af.transpose(af.tile(params.xi_LGL, 1, params.N_LGL))
    power = af.flip(af.range(params.N_LGL))
    power_tile = af.tile(power, 1, params.N_LGL)
    xi_pow = af.arith.pow(xi_tile, power_tile)
    index = af.range(params.N_LGL)
    L_i = af.blas.matmul(lagrange_coeff_array[index], xi_pow)

    return L_i
def contour_plot(u, v, t_n):
    '''
    '''
    u_map = af.moddims(u, params.n, params.n)
    v_map = af.moddims(v, params.n, params.n)

    scale = af.np_to_af_array(np.linspace(0, 1, params.n))
    x_tile = af.tile(scale, 1, params.n)
    y_tile = af.transpose(x_tile)

    speed_tile = (af.transpose(u_map)**2 + af.transpose(v_map)**2)**0.5
    x_tile = np.array(x_tile)
    y_tile = np.array(y_tile)
    speed_tile = np.array(af.flip(speed_tile, 0))

    pl.contourf(y_tile, x_tile, speed_tile, cmap='jet')
    pl.gca().set_aspect('equal')
    pl.title('Time = %.2f' % (t_n * params.delta_t))
    pl.xlabel('x')
    pl.ylabel('y')
    pl.colorbar()
    pl.savefig('results/images/%04d' % (t_n) + '.png')
    pl.close('all')
Beispiel #16
0
    af.display(B)
    A[1,:] = B[2,:]
    af.display(A)

    print("\n---- Bitwise operations\n")
    af.display(A & B)
    af.display(A | B)
    af.display(A ^ B)

    print("\n---- Transpose\n")
    af.display(A)
    af.display(af.transpose(A))

    print("\n---- Flip Vertically / Horizontally\n")
    af.display(A)
    af.display(af.flip(A, 0))
    af.display(af.flip(A, 1))

    print("\n---- Sum, Min, Max along row / columns\n")
    af.display(A)
    af.display(af.sum(A, 0))
    af.display(af.min(A, 0))
    af.display(af.max(A, 0))
    af.display(af.sum(A, 1))
    af.display(af.min(A, 1))
    af.display(af.max(A, 1))

    print("\n---- Get minimum with index\n")
    (min_val, min_idx) = af.imin(A, 0)
    af.display(min_val)
    af.display(min_idx)
a = af.randu(3, 4)
b = af.diag(a, extract=True)
c = af.diag(a, 1, extract=True)

af.print_array(a)
af.print_array(b)
af.print_array(c)

af.print_array(af.diag(b, extract = False))
af.print_array(af.diag(c, 1, extract = False))

af.print_array(af.tile(a, 2, 2))

af.print_array(af.reorder(a, 1, 0))

af.print_array(af.shift(a, -1, 1))

af.print_array(af.moddims(a, 6, 2))

af.print_array(af.flat(a))

af.print_array(af.flip(a, 0))
af.print_array(af.flip(a, 1))

af.print_array(af.lower(a, False))
af.print_array(af.lower(a, True))

af.print_array(af.upper(a, False))
af.print_array(af.upper(a, True))
Beispiel #18
0
 def flip(arr, axis=None):
     if axis is None:
         return af.flip(af.flip(af.flip(arr, 0), 1), 2)
     else:
         return af.flip(arr, axis)
Beispiel #19
0
def apply_mirror_bcs_fields(self, boundary, on_fdtd_grid):
    """
    Applies the mirror boundary conditions along boundary specified 
    for the EM fields
    
    Parameters
    ----------
    boundary: str
              Boundary along which the boundary condition is to be applied.
    
    on_fdtd_grid: bool
                  Flag which dictates if boundary conditions are to be applied to the 
                  fields on the Yee grid or on the cell centered grid.
    """

    N_g_q = self.N_ghost_q

    if (boundary == 'left'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        if (on_fdtd_grid == True):
            self.yee_grid_EM_fields[:, :, :N_g_q] = \
                af.flip(self.yee_grid_EM_fields[:, :, N_g_q:2 * N_g_q], 2)
        else:
            self.cell_centered_EM_fields[:, :, :N_g_q] = \
                af.flip(self.cell_centered_EM_fields[:, :, N_g_q:2 * N_g_q], 2)

    elif (boundary == 'right'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;

        if (on_fdtd_grid == True):
            self.yee_grid_EM_fields[:, :, -N_g_q:] = \
                af.flip(self.yee_grid_EM_fields[:, :, -2 * N_g_q:-N_g_q], 2)
        else:
            self.cell_centered_EM_fields[:, :, -N_g_q:] = \
                af.flip(self.cell_centered_EM_fields[:, :, -2 * N_g_q:-N_g_q], 2)

    elif (boundary == 'bottom'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;

        if (on_fdtd_grid == True):
            self.yee_grid_EM_fields[:, :, :, :N_g_q] = \
                af.flip(self.yee_grid_EM_fields[:, :, :, N_g_q:2 * N_g_q], 3)

        else:
            self.cell_centered_EM_fields[:, :, :, :N_g_q] = \
                af.flip(self.cell_centered_EM_fields[:, :, :, N_g_q:2 * N_g_q], 3)

    elif (boundary == 'top'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;

        if (on_fdtd_grid == True):
            self.yee_grid_EM_fields[:, :, :, -N_g_q:] = \
                af.flip(self.yee_grid_EM_fields[:, :, :, -2 * N_g_q:-N_g_q], 3)

        else:
            self.cell_centered_EM_fields[:, :, :, -N_g_q:] = \
                af.flip(self.cell_centered_EM_fields[:, :, :, -2 * N_g_q:-N_g_q], 3)

    else:
        raise Exception('Invalid choice for boundary')

    return
Beispiel #20
0
def apply_mirror_bcs_f_polar2D(self, boundary):
    """
    Applies mirror boundary conditions along boundary specified 
    for the distribution function when momentum space is on a 2D polar grid
    
    Parameters
    ----------
    boundary: str
              Boundary along which the boundary condition is to be applied.
    """

    N_g = self.N_ghost

    if (boundary == 'left'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        self.f[:, :, :N_g] = af.flip(self.f[:, :, N_g:2 * N_g], 2)

        # For a particle moving with initial momentum at an angle \theta
        # with the x-axis, a collision with the left boundary changes
        # the angle of momentum after reflection to (pi - \theta)
        # To do this, we split the array into to equal halves,
        # flip each of the halves along the p_theta axis and then
        # join the two flipped halves together.

        N_theta = self.N_p2

        tmp1 = self._convert_to_p_expanded(self.f)[:, :N_theta / 2, :, :]
        tmp1 = af.flip(tmp1, 1)
        tmp2 = self._convert_to_p_expanded(self.f)[:, N_theta / 2:, :, :]
        tmp2 = af.flip(tmp2, 1)
        tmp = af.join(1, tmp1, tmp2)

        self.f[:, :, :N_g] = \
                self._convert_to_q_expanded(tmp)[:, :, :N_g]

    elif (boundary == 'right'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;
        self.f[:, :, -N_g:] = af.flip(self.f[:, :, -2 * N_g:-N_g], 2)

        # For a particle moving with initial momentum at an angle \theta
        # with the x-axis, a collision with the right boundary changes
        # the angle of momentum after reflection to (pi - \theta)
        # To do this, we split the array into to equal halves,
        # flip each of the halves along the p_theta axis and then
        # join the two flipped halves together.

        N_theta = self.N_p2

        tmp1 = self._convert_to_p_expanded(self.f)[:, :N_theta / 2, :, :]
        tmp1 = af.flip(tmp1, 1)
        tmp2 = self._convert_to_p_expanded(self.f)[:, N_theta / 2:, :, :]
        tmp2 = af.flip(tmp2, 1)
        tmp = af.join(1, tmp1, tmp2)

        self.f[:, :, -N_g:] = \
                self._convert_to_q_expanded(tmp)[:, :, -N_g:]

    elif (boundary == 'bottom'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        self.f[:, :, :, :N_g] = af.flip(self.f[:, :, :, N_g:2 * N_g], 3)

        # For a particle moving with initial momentum at an angle \theta
        # with the x-axis, a collision with the bottom boundary changes
        # the angle of momentum after reflection to (2*pi - \theta) = (-\theta)
        # To do this we flip the axis that contains the variation in p_theta
        self.f[:, :, :, :N_g] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                1
                                               )
                                       )[:, :, :, :N_g]

    elif (boundary == 'top'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;
        self.f[:, :, :, -N_g:] = af.flip(self.f[:, :, :, -2 * N_g:-N_g], 3)

        # For a particle moving with initial momentum at an angle \theta
        # with the x-axis, a collision with the top boundary changes
        # the angle of momentum after reflection to (2*pi - \theta) = (-\theta)
        # To do this we flip the axis that contains the variation in p_theta
        self.f[:, :, :, -N_g:] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                1
                                               )
                                       )[:, :, :, -N_g:]

    else:
        raise Exception('Invalid choice for boundary')

    return
Beispiel #21
0
def apply_mirror_bcs_f_cartesian(self, boundary):
    """
    Applies mirror boundary conditions along boundary specified 
    for the distribution function when momentum space is on a cartesian grid
    
    Parameters
    ----------
    boundary: str
              Boundary along which the boundary condition is to be applied.
    """

    N_g = self.N_ghost

    if (boundary == 'left'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        self.f[:, :, :N_g] = af.flip(self.f[:, :, N_g:2 * N_g], 2)

        # The points in the ghost zone need to have direction
        # of velocity reversed as compared to the physical zones
        # they are mirroring. To do this we flip the axis that
        # contains the variation in p1
        self.f[:, :, :N_g] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                0
                                               )
                                       )[:, :, :N_g]

    elif (boundary == 'right'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;
        self.f[:, :, -N_g:] = af.flip(self.f[:, :, -2 * N_g:-N_g], 2)

        # The points in the ghost zone need to have direction
        # of velocity reversed as compared to the physical zones
        # they are mirroring. To do this we flip the axis that
        # contains the variation in p1
        self.f[:, :, -N_g:] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                0
                                               )
                                       )[:, :, -N_g:]

    elif (boundary == 'bottom'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        self.f[:, :, :, :N_g] = af.flip(self.f[:, :, :, N_g:2 * N_g], 3)

        # The points in the ghost zone need to have direction
        # of velocity reversed as compared to the physical zones
        # they are mirroring. To do this we flip the axis that
        # contains the variation in p2
        self.f[:, :, :, :N_g] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                1
                                               )
                                       )[:, :, :, :N_g]

    elif (boundary == 'top'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;
        self.f[:, :, :, -N_g:] = af.flip(self.f[:, :, :, -2 * N_g:-N_g], 3)

        # The points in the ghost zone need to have direction
        # of velocity reversed as compared to the physical zones
        # they are mirroring. To do this we flip the axis that
        # contains the variation in p2
        self.f[:, :, :, -N_g:] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                1
                                               )
                                       )[:, :, :, -N_g:]

    else:
        raise Exception('Invalid choice for boundary')

    return
def change_parameters(LGL, Elements, quad, wave='sin'):
    '''
    Changes the parameters of the simulation. Used only for convergence tests.
    Parameters
    ----------
    LGL      : int
               The new N_LGL.
    Elements : int
               The new N_Elements.
    '''
    # The domain of the function.
    params.x_nodes = af.np_to_af_array(np.array([-1., 1.]))

    # The number of LGL points into which an element is split.
    params.N_LGL = LGL

    # Number of elements the domain is to be divided into.
    params.N_Elements = Elements

    # The number quadrature points to be used for integration.
    params.N_quad = quad

    # Array containing the LGL points in xi space.
    params.xi_LGL = lagrange.LGL_points(params.N_LGL)

    # The weights of the lgl points
    params.weight_arr = lagrange.weight_arr_fun(params.xi_LGL)

    # N_Gauss number of Gauss nodes.
    params.gauss_points  = af.np_to_af_array(lagrange.gauss_nodes\
                                                    (params.N_quad))
    # The Gaussian weights.
    params.gauss_weights = lagrange.gaussian_weights(params.N_quad)

    # The lobatto nodes to be used for integration.
    params.lobatto_quadrature_nodes = lagrange.LGL_points(params.N_quad)

    # The lobatto weights to be used for integration.
    params.lobatto_weights_quadrature = lagrange.lobatto_weights\
                                        (params.N_quad)

    #The b matrix
    params.b_matrix = lagrange.b_matrix_eval()

    # A list of the Lagrange polynomials in poly1d form.
    #params.lagrange_product = lagrange.product_lagrange_poly(params.xi_LGL)

    # An array containing the coefficients of the lagrange basis polynomials.
    params.lagrange_coeffs  = af.np_to_af_array(\
                              lagrange.lagrange_polynomials(params.xi_LGL)[1])

    # Refer corresponding functions.
    params.lagrange_basis_value = lagrange.lagrange_function_value\
                                           (params.lagrange_coeffs)

    # While evaluating the volume integral using N_LGL
    # lobatto quadrature points, The integration can be vectorized
    # and in this case the coefficients of the differential of the
    # Lagrange polynomials is required
    params.diff_pow = (af.flip(af.transpose(af.range(params.N_LGL - 1) + 1),
                               1))
    params.dl_dxi_coeffs = (af.broadcast(utils.multiply,
                                         params.lagrange_coeffs[:, :-1],
                                         params.diff_pow))

    # Obtaining an array consisting of the LGL points mapped onto the elements.

    params.element_size    = af.sum((params.x_nodes[1] - params.x_nodes[0])\
                                                        / params.N_Elements)
    params.elements_xi_LGL = af.constant(0, params.N_Elements, params.N_LGL)
    params.elements        = utils.linspace(af.sum(params.x_nodes[0]),
                             af.sum(params.x_nodes[1] - params.element_size),\
                                                            params.N_Elements)
    params.np_element_array   = np.concatenate((af.transpose(params.elements),
                                   af.transpose(params.elements +\
                                                       params.element_size)))

    params.element_mesh_nodes = utils.linspace(af.sum(params.x_nodes[0]),
                                        af.sum(params.x_nodes[1]),\
                                               params.N_Elements + 1)

    params.element_array = af.transpose(af.np_to_af_array\
                                       (params.np_element_array))
    params.element_LGL   = wave_equation.mapping_xi_to_x(af.transpose\
                                          (params.element_array), params.xi_LGL)

    # The minimum distance between 2 mapped LGL points.
    params.delta_x = af.min(
        (params.element_LGL - af.shift(params.element_LGL, 1, 0))[1:, :])

    # dx_dxi for elements of equal size.
    params. dx_dxi = af.mean(wave_equation.dx_dxi_numerical((params.element_mesh_nodes[0 : 2]),\
                                   params.xi_LGL))

    # The value of time-step.
    params.delta_t = params.delta_x / (4 * params.c)

    # Array of timesteps seperated by delta_t.
    params.time = utils.linspace(
        0,
        int(params.total_time / params.delta_t) * params.delta_t,
        int(params.total_time / params.delta_t))

    # Initializing the amplitudes. Change u_init to required initial conditions.
    if (wave == 'sin'):
        params.u_init = af.sin(2 * np.pi * params.element_LGL)

    if (wave == 'gaussian'):
        params.u_init = np.e**(-(params.element_LGL)**2 / 0.4**2)

    params.u          = af.constant(0, params.N_LGL, params.N_Elements, params.time.shape[0],\
                                     dtype = af.Dtype.f64)
    params.u[:, :, 0] = params.u_init

    return
Beispiel #23
0
def apply_mirror_bcs_fields(self, boundary, on_fdtd_grid):
    """
    Applies the mirror boundary conditions along boundary specified 
    for the EM fields
    
    Parameters
    ----------
    boundary: str
              Boundary along which the boundary condition is to be applied.
    
    on_fdtd_grid: bool
                  Flag which dictates if boundary conditions are to be applied to the 
                  fields on the Yee grid or on the cell centered grid.
    """

    N_g = self.N_g
    if (boundary == 'left'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        if (on_fdtd_grid == True):
            # Reflecting E2 and E3 about y-axis:
            # E2 --> (i + 1/2, j)
            # E3 --> (i + 1/2, j + 1/2)
            # As an implication of this, dB3/dt(x = 0) = 0
            #                            dB2/dt(x = 0) = 0
            self.yee_grid_EM_fields[1:3, :, :N_g] = \
                af.flip(self.yee_grid_EM_fields[1:3, :, N_g:2 * N_g], 2)

            # ALTERNATE: Trying out:
            # Setting electric fields within boundaries to zero:
            # self.yee_grid_EM_fields[0, :, :(N_g+1)] = 0 # E1 --> (i, j + 1/2)
            # self.yee_grid_EM_fields[1, :, :N_g] = 0 # E2 --> (i + 1/2, j)
            # self.yee_grid_EM_fields[2, :, :N_g] = 0 # E3 --> (i + 1/2, j + 1/2)

            # Since dB/dt = -(∇ x E), the values in the boundaries should remain unchanged:
            # initial_magnetic_fields = self.initialize_magnetic_fields(False)
            # self.yee_grid_EM_fields[3, :, :N_g]     = initial_magnetic_fields[0, :, :N_g] # B1 --> (i + 1/2, j)
            # self.yee_grid_EM_fields[4, :, :(N_g+1)] = initial_magnetic_fields[1, :, :(N_g+1)] # B2 --> (i, j + 1/2)
            # self.yee_grid_EM_fields[5, :, :(N_g+1)] = initial_magnetic_fields[2, :, :(N_g+1)] # B3 --> (i, j)

        else:
            self.cell_centered_EM_fields[:, :, :N_g] = \
                af.flip(self.cell_centered_EM_fields[:, :, N_g:2 * N_g], 2)

    elif (boundary == 'right'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;

        if (on_fdtd_grid == True):
            # Reflecting E2 and E3 about y-axis:
            # E2 --> (i + 1/2, j)
            # E3 --> (i + 1/2, j + 1/2)
            # As an implication of this, dB3/dt(x = L) = 0
            #                            dB2/dt(x = L) = 0
            self.yee_grid_EM_fields[1:3, :, -N_g:] = \
                af.flip(self.yee_grid_EM_fields[1:3, :, -2 * N_g:-N_g], 2)

            # ALTERNATE: Trying out:
            # Setting electric fields within boundaries to zero:
            # self.yee_grid_EM_fields[0, :, -N_g:] = 0 * self.yee_grid_EM_fields[0, :, -N_g:] # E1 --> (i, j + 1/2)
            # self.yee_grid_EM_fields[1, :, -N_g:] = 0 * self.yee_grid_EM_fields[1, :, -N_g:] # E2 --> (i + 1/2, j)
            # self.yee_grid_EM_fields[2, :, -N_g:] = 0 * self.yee_grid_EM_fields[2, :, -N_g:] # E3 --> (i + 1/2, j + 1/2)

            # Since dB/dt = -(∇ x E), the values in the boundaries should remain unchanged:
            # initial_magnetic_fields = self.initialize_magnetic_fields(False)
            # self.yee_grid_EM_fields[3, :, -N_g:] = initial_magnetic_fields[0, :, -N_g:] # B1 --> (i + 1/2, j)
            # self.yee_grid_EM_fields[4, :, -N_g:] = initial_magnetic_fields[1, :, -N_g:] # B2 --> (i, j + 1/2)
            # self.yee_grid_EM_fields[5, :, -N_g:] = initial_magnetic_fields[2, :, -N_g:] # B3 --> (i, j)

        else:
            self.cell_centered_EM_fields[:, :, -N_g:] = \
                af.flip(self.cell_centered_EM_fields[:, :, -2 * N_g:-N_g], 2)

    elif (boundary == 'bottom'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;

        if (on_fdtd_grid == True):
            # Reflecting E1 and E3 about x-axis:
            # E2 --> (i, j + 1/2)
            # E3 --> (i + 1/2, j + 1/2)
            # As an implication of this, dB3/dt(y = 0) = 0
            #                            dB1/dt(y = 0) = 0
            self.yee_grid_EM_fields[0, :, :, :N_g] = \
                af.flip(self.yee_grid_EM_fields[0, :, :, N_g:2 * N_g], 3)
            self.yee_grid_EM_fields[2, :, :, :N_g] = \
                af.flip(self.yee_grid_EM_fields[2, :, :, N_g:2 * N_g], 3)

            # ALTERNATE: Trying out:
            # Setting electric fields within boundaries to zero:
            # self.yee_grid_EM_fields[0, :, :, :(N_g+1)] = 0 # E1 --> (i, j + 1/2)
            # self.yee_grid_EM_fields[1, :, :, :N_g] = 0 # E2 --> (i + 1/2, j)
            # self.yee_grid_EM_fields[2, :, :, :N_g] = 0 # E3 --> (i + 1/2, j + 1/2)

            # Since dB/dt = -(∇ x E), the values in the boundaries should remain unchanged:
            # initial_magnetic_fields = self.initialize_magnetic_fields(False)
            # self.yee_grid_EM_fields[3, :, :, :N_g]     = initial_magnetic_fields[0, :, :, :N_g] # B1 --> (i + 1/2, j)
            # self.yee_grid_EM_fields[4, :, :, :(N_g+1)] = initial_magnetic_fields[1, :, :, :(N_g+1)] # B2 --> (i, j + 1/2)
            # self.yee_grid_EM_fields[5, :, :, :(N_g+1)] = initial_magnetic_fields[2, :, :, :(N_g+1)] # B3 --> (i, j)

        else:
            self.cell_centered_EM_fields[:, :, :, :N_g] = \
                af.flip(self.cell_centered_EM_fields[:, :, :, N_g:2 * N_g], 3)

    elif (boundary == 'top'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;

        if (on_fdtd_grid == True):
            # Reflecting E1 and E3 about x-axis:
            # E2 --> (i, j + 1/2)
            # E3 --> (i + 1/2, j + 1/2)
            # As an implication of this, dB3/dt(y = L) = 0
            #                            dB1/dt(y = L) = 0

            self.yee_grid_EM_fields[0, :, :, -N_g:] = \
                af.flip(self.yee_grid_EM_fields[0, :, :, -2 * N_g:-N_g], 3)

            self.yee_grid_EM_fields[2, :, :, -N_g:] = \
                af.flip(self.yee_grid_EM_fields[2, :, :, -2 * N_g:-N_g], 3)

            # ALTERNATE: Trying out:
            # Setting electric fields within boundaries to zero:
            # self.yee_grid_EM_fields[0, :, :, -N_g:] = 0 * self.yee_grid_EM_fields[0, :, :, -N_g:] # E1 --> (i, j + 1/2)
            # self.yee_grid_EM_fields[1, :, :, -N_g:] = 0 * self.yee_grid_EM_fields[1, :, :, -N_g:] # E2 --> (i + 1/2, j)
            # self.yee_grid_EM_fields[2, :, :, -N_g:] = 0 * self.yee_grid_EM_fields[2, :, :, -N_g:] # E3 --> (i + 1/2, j + 1/2)

            # Since dB/dt = -(∇ x E), the values in the boundaries should remain unchanged:
            # initial_magnetic_fields = self.initialize_magnetic_fields(False)
            # self.yee_grid_EM_fields[3, :, :, -N_g:] = initial_magnetic_fields[0, :, :, -N_g:] # B1 --> (i + 1/2, j)
            # self.yee_grid_EM_fields[4, :, :, -N_g:] = initial_magnetic_fields[1, :, :, -N_g:] # B2 --> (i, j + 1/2)
            # self.yee_grid_EM_fields[5, :, :, -N_g:] = initial_magnetic_fields[2, :, :, -N_g:] # B3 --> (i, j)

        else:
            self.cell_centered_EM_fields[:, :, :, -N_g:] = \
                af.flip(self.cell_centered_EM_fields[:, :, :, -2 * N_g:-N_g], 3)

    else:
        raise Exception('Invalid choice for boundary')

    return
Beispiel #24
0
    af.display(B)
    A[1, :] = B[2, :]
    af.display(A)

    print("\n---- Bitwise operations\n")
    af.display(A & B)
    af.display(A | B)
    af.display(A ^ B)

    print("\n---- Transpose\n")
    af.display(A)
    af.display(af.transpose(A))

    print("\n---- Flip Vertically / Horizontally\n")
    af.display(A)
    af.display(af.flip(A, 0))
    af.display(af.flip(A, 1))

    print("\n---- Sum, Min, Max along row / columns\n")
    af.display(A)
    af.display(af.sum(A, 0))
    af.display(af.min(A, 0))
    af.display(af.max(A, 0))
    af.display(af.sum(A, 1))
    af.display(af.min(A, 1))
    af.display(af.max(A, 1))

    print("\n---- Get minimum with index\n")
    (min_val, min_idx) = af.imin(A, 0)
    af.display(min_val)
    af.display(min_idx)
def apply_mirror_bcs_f(self, boundary):

    N_g = self.N_ghost

    if (boundary == 'left'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        self.f[:, :N_g] = af.flip(self.f[:, N_g:2 * N_g], 1)

        # The points in the ghost zone need to have direction
        # of velocity reversed as compared to the physical zones
        # they are mirroring. To do this we flip the axis that
        # contains the variation in p1
        self.f[:, :N_g] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                0
                                               )
                                       )[:, :N_g]

    elif (boundary == 'right'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;
        self.f[:, -N_g:] = af.flip(self.f[:, -2 * N_g:-N_g], 1)

        # The points in the ghost zone need to have direction
        # of velocity reversed as compared to the physical zones
        # they are mirroring. To do this we flip the axis that
        # contains the variation in p1
        self.f[:, -N_g:] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                0
                                               )
                                       )[:, -N_g:]

    elif (boundary == 'bottom'):
        # x-0-x-0-x-0-|-0-x-0-x-0-x-....
        #   0   1   2   3   4   5
        # For mirror boundary conditions:
        # 0 = 5; 1 = 4; 2 = 3;
        self.f[:, :, :N_g] = af.flip(self.f[:, :, N_g:2 * N_g], 2)

        # The points in the ghost zone need to have direction
        # of velocity reversed as compared to the physical zones
        # they are mirroring. To do this we flip the axis that
        # contains the variation in p2
        self.f[:, :, :N_g] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                1
                                               )
                                       )[:, :, :N_g]

    elif (boundary == 'top'):
        # ...-x-0-x-0-x-0-|-0-x-0-x-0-x
        #      -6  -5  -4  -3  -2  -1
        # For mirror boundary conditions:
        # -1 = -6; -2 = -5; -3 = -4;
        self.f[:, :, -N_g:] = af.flip(self.f[:, :, -2 * N_g:-N_g], 2)

        # The points in the ghost zone need to have direction
        # of velocity reversed as compared to the physical zones
        # they are mirroring. To do this we flip the axis that
        # contains the variation in p2
        self.f[:, :, -N_g:] = \
            self._convert_to_q_expanded(af.flip(self._convert_to_p_expanded(self.f),
                                                1
                                               )
                                       )[:, :, -N_g:]

    else:
        raise Exception('Invalid choice for boundary')

    return
Beispiel #26
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)

    # 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
a = af.randu(3, 4)
b = af.diag(a, extract=True)
c = af.diag(a, 1, extract=True)

af.display(a)
af.display(b)
af.display(c)

af.display(af.diag(b, extract = False))
af.display(af.diag(c, 1, extract = False))

af.display(af.tile(a, 2, 2))

af.display(af.reorder(a, 1, 0))

af.display(af.shift(a, -1, 1))

af.display(af.moddims(a, 6, 2))

af.display(af.flat(a))

af.display(af.flip(a, 0))
af.display(af.flip(a, 1))

af.display(af.lower(a, False))
af.display(af.lower(a, True))

af.display(af.upper(a, False))
af.display(af.upper(a, True))
Beispiel #28
0
 def flip(arr, axis=None):
     if axis is None:
         raise NotImplementedError
     else:
         return af.flip(arr, axis)
Beispiel #29
0
# An array containing the coefficients of the lagrange basis polynomials.
lagrange_coeffs            = af.np_to_af_array(\
                                lagrange.lagrange_polynomials(xi_LGL)[1])

# Refer corresponding functions.
lagrange_basis_value = lagrange.lagrange_function_value(lagrange_coeffs)


# While evaluating the volume integral using N_LGL
# lobatto quadrature points, The integration can be vectorized
# and in this case the coefficients of the differential of the
# Lagrange polynomials is required


diff_pow      = (af.flip(af.transpose(af.range(N_LGL - 1) + 1), 1))
dl_dxi_coeffs = (af.broadcast(utils.multiply, lagrange_coeffs[:, :-1], diff_pow))

# Obtaining an array consisting of the LGL points mapped onto the elements.

element_size    = af.sum((x_nodes[1] - x_nodes[0]) / N_Elements)
elements_xi_LGL = af.constant(0, N_Elements, N_LGL)
elements        = utils.linspace(af.sum(x_nodes[0]),
                  af.sum(x_nodes[1] - element_size), N_Elements)

np_element_array   = np.concatenate((af.transpose(elements),
                                     af.transpose(elements + element_size)))
element_mesh_nodes = utils.linspace(af.sum(x_nodes[0]),
                                    af.sum(x_nodes[1]),
                                    N_Elements + 1)
Beispiel #30
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