示例#1
0
def initialize_f(q1, q2, p1, p2, p3, params):

    m = params.mass_particle
    k = params.boltzmann_constant

    rho = af.select(af.abs(q2) > 0.25, q1**0, 2)

    try:
        p1_bulk = af.select(
            af.abs(q2) > 0.25, -0.5 - 0.01 *
            (af.randu(1, q1.shape[1], q2.shape[2], dtype=af.Dtype.f64) - 0.5),
            +0.5 + 0.01 *
            (af.randu(1, q1.shape[1], q2.shape[2], dtype=af.Dtype.f64) - 0.5))

        p2_bulk = 0.01 * (
            af.randu(1, q1.shape[1], q2.shape[2], dtype=af.Dtype.f64) - 0.5)
    except:
        p1_bulk = af.select(
            af.abs(q2) > 0.25, -0.5 - 0.01 *
            (af.randu(q1.shape[0], q2.shape[1], dtype=af.Dtype.f64) - 0.5),
            +0.5 + 0.01 *
            (af.randu(q1.shape[0], q2.shape[1], dtype=af.Dtype.f64) - 0.5))

        p2_bulk = 0.01 * (
            af.randu(q1.shape[0], q2.shape[1], dtype=af.Dtype.f64) - 0.5)

    T = (2.5 / rho)

    f = rho * (m / (2 * np.pi * k * T))**(3 / 2) \
            * af.exp(-m * (p1 - p1_bulk)**2 / (2 * k * T)) \
            * af.exp(-m * (p2 - p2_bulk)**2 / (2 * k * T)) \
            * af.exp(-m * p3**2 / (2 * k * T))

    af.eval(f)
    return (f)
示例#2
0
def initialize_f(q1, q2, v1, v2, v3, params):

    m = params.mass
    k = params.boltzmann_constant

    n = af.select(af.abs(q2)>0.25, q1**0, 2)

    # Random Numbers under to seed the instability:
    seeding_velocities = 0.01 * (af.randu(1, 1, q1.shape[2], q1.shape[3], 
                                          dtype = af.Dtype.f64
                                         ) - 0.5
                                )

    v1_bulk = af.select(af.abs(q2)>0.25, 
                        -0.5 - seeding_velocities,
                        +0.5 + seeding_velocities
                       )
       
    v2_bulk = seeding_velocities

    T = (2.5 / n)

    f = n * (m / (2 * np.pi * k * T))**(3 / 2) \
          * af.exp(-m * (v1 - v1_bulk)**2 / (2 * k * T)) \
          * af.exp(-m * (v2 - v2_bulk)**2 / (2 * k * T)) \
          * af.exp(-m * v3**2 / (2 * k * T))

    af.eval(f)
    return (f)
def test_dirichlet():

    obj = test('dirichlet', 'dirichlet')

    obj._A_q1, obj._A_q2 = af.Array([100]), af.Array([100])

    obj._A_q1 = af.tile(obj._A_q1, 1, 1, obj.q1_center.shape[2])
    obj._A_q2 = af.tile(obj._A_q2, 1, 1, obj.q1_center.shape[2])

    obj.dt = 0.001

    obj.f = af.constant(0,
                        obj.q1_center.shape[0],
                        obj.q1_center.shape[1],
                        obj.q1_center.shape[2],
                        dtype=af.Dtype.f64)

    apply_bcs_f(obj)

    expected = af.constant(0,
                           obj.q1_center.shape[0],
                           obj.q1_center.shape[1],
                           obj.q1_center.shape[2],
                           dtype=af.Dtype.f64)

    N_g = obj.N_ghost

    # Only ingoing characteristics should be affected:
    expected[:N_g] = af.select(obj.q1_center < obj.q1_start, 1, expected)[:N_g]
    expected[:, :N_g] = af.select(obj.q2_center < obj.q2_start, 2,
                                  expected)[:, :N_g]

    assert (af.max(af.abs(obj.f[:, N_g:-N_g] - expected[:, N_g:-N_g])) < 5e-14)
    assert (af.max(af.abs(obj.f[N_g:-N_g, :] - expected[N_g:-N_g, :])) < 5e-14)
示例#4
0
def initialize_f(q1, q2, p1, p2, p3, params):

    m     = params.mass
    k     = params.boltzmann_constant

    rho = af.select(q1<0.5, q1**0, 0.125)
    T   = af.select(q1<0.5, q1**0, 0.8)

    f = rho * af.sqrt(m / (2 * np.pi * k * T))**3 \
            * af.exp(-m * p1**2 / (2 * k * T)) \
            * af.exp(-m * p2**2 / (2 * k * T)) \
            * af.exp(-m * p3**2 / (2 * k * T))

    af.eval(f)
    return (f)
示例#5
0
def initialize_f(q1, q2, v1, v2, v3, params):

    m = params.mass
    k = params.boltzmann_constant

    n = af.select(q1 < 0.5, q1**0, 0.125)
    T = af.select(q1 < 0.5, q1**0, 0.8)

    f = n * (m / (2 * np.pi * k * T))**(3 / 2) \
          * af.exp(-m * v1**2 / (2 * k * T)) \
          * af.exp(-m * v2**2 / (2 * k * T)) \
          * af.exp(-m * v3**2 / (2 * k * T))

    af.eval(f)
    return (f)
示例#6
0
def initialize_f(q1, q2, v1, v2, v3, params):

    m = params.mass
    k = params.boltzmann_constant

    # Calculating the perturbed density:
    n = af.select(q1 + q2 > 0.15, q1**0, 0.125)
    T = af.select(q1 + q2 > 0.15, q1**0, 0.373)

    f = n * (m / (2 * np.pi * k * T)) \
          * af.exp(-m * v1**2 / (2 * k * T)) \
          * af.exp(-m * v2**2 / (2 * k * T))

    af.eval(f)
    return (f)
示例#7
0
def initialize_f(q1, q2, p1, p2, p3, params):

    m = params.mass_particle
    k = params.boltzmann_constant

    rho = af.select(af.abs(q2) > 0.25, q1**0, 2)

    # Seeding the instability
    p1_bulk = af.reorder(p1_bulk, 1, 2, 0, 3)
    p1_bulk += af.to_array(
        np.random.rand(1, q1.shape[1], q1.shape[2]) *
        np.random.choice([-1, 1], size=(1, q1.shape[1], q1.shape[2]))) * 0.005

    p2_bulk = af.to_array(
        np.random.rand(1, q1.shape[1], q1.shape[2]) *
        np.random.choice([-1, 1], size=(1, q1.shape[1], q1.shape[2]))) * 0.005

    p1_bulk = af.reorder(p1_bulk, 2, 0, 1, 3)
    p2_bulk = af.reorder(p2_bulk, 2, 0, 1, 3)

    T = (2.5 / rho)

    f = rho * (m / (2 * np.pi * k * T))**(3 / 2) \
            * af.exp(-m * (p1 - p1_bulk)**2 / (2 * k * T)) \
            * af.exp(-m * (p2 - p2_bulk)**2 / (2 * k * T)) \
            * af.exp(-m * (p3)**2 / (2 * k * T))

    af.eval(f)
    return (f)
示例#8
0
def initialize_f(q1, q2, p1, p2, p3, params):

    m = params.mass_particle
    k = params.boltzmann_constant

    # Calculating the perturbed density:
    rho = af.select(q1 + q2 > 0.15, q1**0, 0.125)
    T = af.select(q1 + q2 > 0.15, q1**0, 0.373)

    f = rho * (m / (2 * np.pi * T))**(3 / 2) \
            * af.exp(-p1**2 / (2 * T)) \
            * af.exp(-p2**2 / (2 * T)) \
            * af.exp(-p3**2 / (2 * T))

    af.eval(f)
    return (f)
示例#9
0
def BGK(f, q1, q2, p1, p2, p3, moments, params):
    """Return BGK operator -(f-f0)/tau."""
    n = moments('density')

    # Floor used to avoid 0/0 limit:
    eps = 1e-15

    p1_bulk = moments('mom_p1_bulk') / (n + eps)
    p2_bulk = moments('mom_p2_bulk') / (n + eps)
    p3_bulk = moments('mom_p3_bulk') / (n + eps)

    T =   (1 / params.p_dim) \
        * (  moments('energy')
           - n * p1_bulk**2
           - n * p2_bulk**2
           - n * p3_bulk**2
          ) / (n + eps) + eps

    C_f = -(f - f0(p1, p2, p3, n, T, p1_bulk, p2_bulk, p3_bulk,
                   params)) / params.tau(q1, q2, p1, p2, p3)

    # When (f - f0) is NaN. Dividing by np.inf doesn't give 0
    # WORKAROUND:
    C_f = af.select(params.tau(q1, q2, p1, p2, p3) == np.inf, 0, C_f)

    af.eval(C_f)
    return (C_f)
示例#10
0
def initialize_f(q1, q2, p1, p2, p3, params):

    m = params.mass_particle
    k = params.boltzmann_constant

    rho = af.select(q1 < 0.5, q1**0, 2 / 3)
    T = af.select(q1 < 0.5, 2 / 3 * q1**0, 1 / 4)
    p1_b = af.select(q1 < 0.5, q1**0, 1.5)

    f = rho * af.sqrt(m / (2 * np.pi * k * T))**3 \
            * af.exp(-m * (p1-p1_b)**2 / (2 * k * T)) \
            * af.exp(-m * p2**2 / (2 * k * T)) \
            * af.exp(-m * p3**2 / (2 * k * T))

    af.eval(f)
    return (f)
示例#11
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)
示例#12
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)))
示例#13
0
def initialize_B(q1, q2, params):

    B1 = 0 * q1**0
    B2 = af.select(q1 < 0.5, params.B0 * 1 * q1**0, -params.B0)
    B3 = 0 * q1**0

    af.eval(B1, B2, B3)
    return (B1, B2, B3)
示例#14
0
def initialize_f(r, theta, rdot, thetadot, phidot, params):

    # The initialization is performed to setup particles
    # between r = 0.9 and 1.1 at theta = 0
    rho = af.select(r < 2, 1 * r**0, 0)
    rho = af.select(r > 1, rho, 0)
    rho = af.select(theta == 0, rho, 0)

    # Getting f at the right shape:
    f = rdot * rho

    f[:] = 0

    # Changing to velocities_expanded form:
    f = af.moddims(f, N_p1, N_p2, N_p3, r.shape[2] * r.shape[3])
    rdot = af.moddims(rdot, N_p1, N_p2, N_p3)
    thetadot = af.moddims(thetadot, N_p1, N_p2, N_p3)

    # Assigning the velocities such that thetadot ∝ 1 / r
    for i in range(r.shape[2]):
        for j in range(r.shape[3]):

            rho_new = rho * 0
            rho_new[:, :, i, j] = rho[:, :, i, j]
            rho_new = af.moddims(rho_new, 1, 1, 1, r.shape[2] * r.shape[3])

            # We set rdot = rdot[64] for all particles and
            # thetadot is inversely proportional to r
            # At initialization:
            thetadot1d = af.flat(thetadot[0, :, 0])
            ind = af.imin(af.abs(thetadot1d - 1 / af.sum(r[:, :, i, j])))[1]

            print('rdot     =', af.sum(rdot[64, ind, 0]))
            print('thetadot =', af.sum(thetadot[64, ind, 0]))
            f[64, ind, 0] += rho_new

    f = af.moddims(f, N_p1 * N_p2 * N_p3, 1, r.shape[2], r.shape[3])

    af.eval(f)
    return (f)
示例#15
0
def lowpass_filter(f):
    f_hat = af.fft(f)
    dp1 = (domain.p1_end[0] - domain.p1_start[0]) / domain.N_p1
    k_v = af.tile(af.to_array(np.fft.fftfreq(domain.N_p1, dp1)), 1, 1,
                  f.shape[2], f.shape[3])

    # Applying the filter:
    f_hat_filtered = 0.5 * (f_hat * (af.tanh(
        (k_v + 0.9 * af.max(k_v)) / 0.5) - af.tanh(
            (k_v + 0.9 * af.min(k_v)) / 0.5)))

    f_hat = af.select(af.abs(k_v) < 0.8 * af.max(k_v), f_hat, f_hat_filtered)
    f = af.real(af.ifft(f_hat))
    return (f)
示例#16
0
def f_interp(config, dt, x, vel_x, f):
  x_new     = x - vel_x*dt
  step_size = af.sum(x[1,0] - x[0,0])
  
  f_interp  = af.constant(0, N_positions + 2*ghost_zones, N_velocity)
  f_interp  = af.Array.as_type(f_interp, af.Dtype.f64)
  
  # Interpolating:
  
  x_temp = x_new[ghost_zones:-ghost_zones, :].copy()
  
  while(af.sum(x_temp<left_boundary)!=0):
      x_temp = af.select(x_temp<left_boundary,
                         x_temp + length,
                         x_temp
                        )
  while(af.sum(x_temp>right_boundary)!=0):
      x_temp = af.select(x_temp>right_boundary,
                         x_temp - length,
                         x_temp
                        )

  x_temp        = af.Array.as_type(x_temp, af.Dtype.f64)
  
  x_interpolant = x_temp/step_size + ghost_zones
  
  x_interpolant = af.Array.as_type(x_interpolant, af.Dtype.f64)
  f             = af.Array.as_type(f, af.Dtype.f64)
  
  f_interp[ghost_zones:-ghost_zones, :] = af.approx1(f, x_interpolant,\
                                                     af.INTERP.CUBIC_SPLINE
                                                    )
  
  f_interp          = af.Array.as_type(f_interp, af.Dtype.f64)
  
  af.eval(f_interp)
  return f_interp
示例#17
0
文件: riemann.py 项目: mchandra/Bolt
def riemann_solver(self, left_state, right_state, velocity):
    """
    Returns the upwinded state, using the 1st order upwind Riemann solver.

    Parameters
    ----------
    left_state : af.Array
                 Array holding the values for the state at the left edge of the cells.

    right_state : af.Array
                 Array holding the values for the state at the right edge of the cells.
    
    velocity : af.Array
               Velocity array whose sign will be used to determine whether the 
               left or right state is chosen.
    """
    if (self.performance_test_flag == True):
        tic = af.time()

    # Checking if array isn't 4D:
    try:
        size_axis_2 = left_state.shape[2]
    except:
        size_axis_2 = 1

    try:
        size_axis_3 = left_state.shape[3]
    except:
        size_axis_3 = 1

    # Tiling to get to appropriate shape:
    try:
        assert (velocity.shape[2] == left_state.shape[2])
    except:
        velocity = af.tile(velocity, 1, 1, size_axis_2, size_axis_3)

    upwind_state = af.select(velocity > 0, left_state, right_state)

    af.eval(upwind_state)

    if (self.performance_test_flag == True):
        af.sync()
        toc = af.time()
        self.time_riemann += toc - tic

    return (upwind_state)
示例#18
0
def initialize_f(q1, q2, v1, v2, v3, params):

    m = params.mass
    k = params.boltzmann_constant

    n_b = params.density_background
    T_b = params.temperature_background

    n = n_b + 0 * q1**0
    T = af.select((q1**2 + q2**2) < 0.01, 100 * T_b * q1**0, T_b)

    f = n * (m / (2 * np.pi * k * T)) \
          * af.exp(-m * v1**2 / (2 * k * T)) \
          * af.exp(-m * v2**2 / (2 * k * T))

    af.eval(f)
    return (f)
示例#19
0
def BGK(f, q1, q2, p1, p2, p3, moments, params, flag = False):
    """Return BGK operator -(f-f0)/tau."""
    n = moments('density', f)

    # Floor used to avoid 0/0 limit:
    eps = 1e-30

    p1_bulk = moments('mom_p1_bulk', f) / (n + eps)
    p2_bulk = moments('mom_p2_bulk', f) / (n + eps)
    p3_bulk = moments('mom_p3_bulk', f) / (n + eps)

    T = (1 / params.p_dim) * (  2 * moments('energy', f) 
                              - n * p1_bulk**2
                              - n * p2_bulk**2
                              - n * p3_bulk**2
                             ) / (n + eps) + eps

    if(af.any_true(params.tau(q1, q2, p1, p2, p3) == 0)):

        f_MB = f0(p1, p2, p3, n, T, p1_bulk, p2_bulk, p3_bulk, params)
      
        if(flag == False):
            f_MB[:] = 0        

        return(f_MB)
            
    else:

        C_f = -(  f
                - f0(p1, p2, p3, n, T, p1_bulk, p2_bulk, p3_bulk, params)
               ) / params.tau(q1, q2, p1, p2, p3)

        # When (f - f0) is NaN. Dividing by np.inf doesn't give 0
        # Setting when tau is zero we assign f = f0 manually
        # WORKAROUND:
        if(isinstance(params.tau(q1, q2, p1, p2, p3), af.Array) is True):
            C_f = af.select(params.tau(q1, q2, p1, p2, p3) == np.inf, 0, C_f)
            af.eval(C_f)
        
        else:
            if(params.tau(q1, q2, p1, p2, p3) == np.inf):
                C_f = 0

        return(C_f)
示例#20
0
文件: timestep.py 项目: shyams2/Bolt
def RK5_step(self, dt):
    """
    Evolves the physical system defined using an RK5
    integrator. This method is 5th order accurate.

    Parameters
    ----------

    dt: double
        The timestep size.

    """
    # For purely collisional cases:
    tau = self.physical_system.params.tau(self.q1_center, self.q2_center,
                                          self.p1, self.p2, self.p3)
    if (af.any_true(tau == 0)):

        f0 = self._source(
            0.5 * self.N_q1 * self.N_q2 * af.real(ifft2(self.f_hat)),
            self.time_elapsed, self.q1_center, self.q2_center, self.p1,
            self.p2, self.p3, self.compute_moments,
            self.physical_system.params, True)

        self.f_hat = af.select(tau == 0,
                               2 * fft2(f0) / (self.N_q1 * self.N_q2),
                               self.f_hat)

    if (self.physical_system.params.EM_fields_enabled == True
            and self.physical_system.params.fields_type == 'electrodynamic'):
        # Since the fields and the distribution function are coupled,
        # we evolve the system by making use of a coupled integrator
        # which ensures that throughout the timestepping they are
        # evaluated at the same temporal locations.
        self.f_hat, self.fields_solver.fields_hat = \
            integrators.RK5_coupled(df_hat_dt, self.f_hat,
                                    dfields_hat_dt, self.fields_solver.fields_hat,
                                    dt, self
                                   )

    else:
        self.f_hat = integrators.RK5(df_hat_dt, self.f_hat, dt,
                                     self.fields_solver.fields_hat, self)

    return
示例#21
0
文件: riemann.py 项目: shyams2/Bolt
def upwind_flux(left_flux, right_flux, velocity):
    """
    Returns the flux, using the 1st order upwind flux Riemann solver.

    Parameters
    ----------

    left_flux : af.Array
                Array holding the values for the flux at the left edge of the cells.

    right_flux : af.Array
                Array holding the values for the flux at the right edge of the cells.
    
    velocity : af.Array
               Velocity array whose sign will be used to determine whether the 
               left or right flux is chosen.
    """
    flux = af.select(velocity > 0, left_flux, right_flux)

    af.eval(flux)
    return (flux)
示例#22
0
def op_solve_src(self, dt):
    """
    Evolves the source term of the equations specified:
    
    df/dt = source
    
    Parameters
    ----------

    dt : double
         Time-step size to evolve the system
    """

    if (self.performance_test_flag == True):
        tic = af.time()

    # Solving for tau = 0 systems:
    tau = self.physical_system.params.tau(self.q1_center, self.q2_center,
                                          self.p1_center, self.p2_center,
                                          self.p3_center)
    if (af.any_true(tau == 0)):

        self.f = af.select(
            tau == 0,
            self._source(self.f, self.time_elapsed, self.q1_center,
                         self.q2_center, self.p1_center, self.p2_center,
                         self.p3_center, self.compute_moments,
                         self.physical_system.params, True), self.f)

    self.f = integrators.RK2(self._source, self.f, dt, self.time_elapsed,
                             self.q1_center, self.q2_center, self.p1_center,
                             self.p2_center, self.p3_center,
                             self.compute_moments, self.physical_system.params)

    if (self.performance_test_flag == True):
        af.sync()
        toc = af.time()
        self.time_sourcets += toc - tic

    return
示例#23
0
文件: main.py 项目: mchandra/Bolt
assert(params.dt_dump_moments > dt)
assert(params.dt_dump_fields > dt)


#if (params.restart):
#    nls.load_distribution_function(params.restart_file)

density = nls.compute_moments('density')
print("rank = ", params.rank, "\n",
      "     <mu>    = ", af.mean(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n",
      "     max(mu) = ", af.max(params.mu[0, 0, N_g:-N_g, N_g:-N_g]), "\n",
      "     <n>     = ", af.mean(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n",
      "     max(n)  = ", af.max(density[0, 0, N_g:-N_g, N_g:-N_g]), "\n"
     )

nls.f = af.select(nls.f < 1e-20, 1e-20, nls.f)
while(time_elapsed < t_final):

    # Refine to machine error
    if (time_step==0):
        params.collision_nonlinear_iters = 10
    else:
        params.collision_nonlinear_iters = params.collision_operator_nonlinear_iters

    dump_steps = params.dump_steps

    if(params.dt_dump_moments != 0):
        # We step by delta_dt to get the values at dt_dump
        delta_dt =   (1 - math.modf(time_elapsed/params.dt_dump_moments)[0]) \
                   * params.dt_dump_moments
示例#24
0
def initialize_f(q1, q2, p1, p2, p3, params):
    f = af.select(af.abs(p1)<2.5, q1**0 * p1**0, 0)
    af.eval(f)
    return (f)
示例#25
0
def apply_dirichlet_bcs_f(self, boundary):
    """
    Applies Dirichlet boundary conditions along boundary specified 
    for the distribution function
    
    Parameters
    ----------
    boundary: str
              Boundary along which the boundary condition is to be applied.
    """

    N_g = self.N_ghost

    if (self.physical_system.params.solver_method_in_q == 'FVM'):
        velocity_q1, velocity_q2 = \
            af.broadcast(self._C_q, self.time_elapsed,
                         self.q1_center, self.q2_center,
                         self.p1_center, self.p2_center, self.p3_center,
                         self.physical_system.params
                        )

    else:
        velocity_q1, velocity_q2 = \
            af.broadcast(self._A_q, self.time_elapsed,
                         self.q1_center, self.q2_center,
                         self.p1_center, self.p2_center, self.p3_center,
                         self.physical_system.params
                        )

    if (velocity_q1.elements() == self.N_species * self.N_p1 * self.N_p2 *
            self.N_p3):
        # If velocity_q1 is of shape (Np1 * Np2 * Np3)
        # We tile to get it to form (Np1 * Np2 * Np3, 1, Nq1, Nq2)
        velocity_q1 = af.tile(velocity_q1, 1, 1, self.f.shape[2],
                              self.f.shape[3])

    if (velocity_q2.elements() == self.N_species * self.N_p1 * self.N_p2 *
            self.N_p3):
        # If velocity_q2 is of shape (Np1 * Np2 * Np3)
        # We tile to get it to form (Np1 * Np2 * Np3, 1, Nq1, Nq2)
        velocity_q2 = af.tile(velocity_q2, 1, 1, self.f.shape[2],
                              self.f.shape[3])

    # Arguments that are passing to the called functions:
    args = (self.f, self.time_elapsed, self.q1_center, self.q2_center,
            self.p1_center, self.p2_center, self.p3_center,
            self.physical_system.params)

    if (boundary == 'left'):
        f_left = self.boundary_conditions.f_left(*args)
        # Only changing inflowing characteristics:
        f_left = af.select(velocity_q1 > 0, f_left, self.f)
        self.f[:, :, :N_g] = f_left[:, :, :N_g]

    elif (boundary == 'right'):
        f_right = self.boundary_conditions.f_right(*args)
        # Only changing inflowing characteristics:
        f_right = af.select(velocity_q1 < 0, f_right, self.f)
        self.f[:, :, -N_g:] = f_right[:, :, -N_g:]

    elif (boundary == 'bottom'):
        f_bottom = self.boundary_conditions.f_bottom(*args)
        # Only changing inflowing characteristics:
        f_bottom = af.select(velocity_q2 > 0, f_bottom, self.f)
        self.f[:, :, :, :N_g] = f_bottom[:, :, :, :N_g]

    elif (boundary == 'top'):
        f_top = self.boundary_conditions.f_top(*args)
        # Only changing inflowing characteristics:
        f_top = af.select(velocity_q2 < 0, f_top, self.f)
        self.f[:, :, :, -N_g:] = f_top[:, :, :, -N_g:]

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

    return
示例#26
0
def apply_shearing_box_bcs_f(self, boundary):
    """
    Applies the shearing box boundary conditions along boundary specified 
    for the distribution function
    
    Parameters
    ----------
    boundary: str
              Boundary along which the boundary condition is to be applied.
    """

    N_g = self.N_ghost
    q = self.physical_system.params.q
    omega = self.physical_system.params.omega

    L_q1 = self.q1_end - self.q1_start
    L_q2 = self.q2_end - self.q2_start

    if (boundary == 'left'):
        sheared_coordinates = self.q2_center[:, :, :
                                             N_g] - q * omega * L_q1 * self.time_elapsed

        # Applying periodic boundary conditions to the points which are out of domain:
        while (af.sum(sheared_coordinates > self.q2_end) != 0):
            sheared_coordinates = af.select(sheared_coordinates > self.q2_end,
                                            sheared_coordinates - L_q2,
                                            sheared_coordinates)

        while (af.sum(sheared_coordinates < self.q2_start) != 0):
            sheared_coordinates = af.select(
                sheared_coordinates < self.q2_start,
                sheared_coordinates + L_q2, sheared_coordinates)

        # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
        # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)

        self.f[:, :, :N_g] = af.reorder(
            af.approx2(af.reorder(self.f[:, :, :N_g], 2, 3, 0, 1),
                       af.reorder(self.q1_center[:, :, :N_g], 2, 3, 0, 1),
                       af.reorder(sheared_coordinates, 2, 3, 0, 1),
                       af.INTERP.BICUBIC_SPLINE,
                       xp=af.reorder(self.q1_center[:, :, :N_g], 2, 3, 0, 1),
                       yp=af.reorder(self.q2_center[:, :, :N_g], 2, 3, 0, 1)),
            2, 3, 0, 1)

    elif (boundary == 'right'):
        sheared_coordinates = self.q2_center[:, :,
                                             -N_g:] + q * omega * L_q1 * self.time_elapsed

        # Applying periodic boundary conditions to the points which are out of domain:
        while (af.sum(sheared_coordinates > self.q2_end) != 0):
            sheared_coordinates = af.select(sheared_coordinates > self.q2_end,
                                            sheared_coordinates - L_q2,
                                            sheared_coordinates)

        while (af.sum(sheared_coordinates < self.q2_start) != 0):
            sheared_coordinates = af.select(
                sheared_coordinates < self.q2_start,
                sheared_coordinates + L_q2, sheared_coordinates)

        # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
        # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)

        self.f[:, :, -N_g:] = af.reorder(
            af.approx2(af.reorder(self.f[:, :, -N_g:], 2, 3, 0, 1),
                       af.reorder(self.q1_center[:, :, -N_g:], 2, 3, 0, 1),
                       af.reorder(sheared_coordinates, 2, 3, 0, 1),
                       af.INTERP.BICUBIC_SPLINE,
                       xp=af.reorder(self.q1_center[:, :, -N_g:], 2, 3, 0, 1),
                       yp=af.reorder(self.q2_center[:, :, -N_g:], 2, 3, 0, 1)),
            2, 3, 0, 1)

    elif (boundary == 'bottom'):

        sheared_coordinates = self.q1_center[:, :, :, :
                                             N_g] - q * omega * L_q2 * self.time_elapsed

        # Applying periodic boundary conditions to the points which are out of domain:
        while (af.sum(sheared_coordinates > self.q1_end) != 0):
            sheared_coordinates = af.select(sheared_coordinates > self.q1_end,
                                            sheared_coordinates - L_q1,
                                            sheared_coordinates)

        while (af.sum(sheared_coordinates < self.q1_start) != 0):
            sheared_coordinates = af.select(
                sheared_coordinates < self.q1_start,
                sheared_coordinates + L_q1, sheared_coordinates)

        # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
        # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)

        self.f[:, :, :, :N_g] = af.reorder(
            af.approx2(af.reorder(self.f[:, :, :, :N_g], 2, 3, 0, 1),
                       af.reorder(sheared_coordinates, 2, 3, 0, 1),
                       af.reorder(self.q2_center[:, :, :, :N_g], 2, 3, 0, 1),
                       af.INTERP.BICUBIC_SPLINE,
                       xp=af.reorder(self.q1_center[:, :, :, :N_g], 2, 3, 0,
                                     1),
                       yp=af.reorder(self.q2_center[:, :, :, :N_g], 2, 3, 0,
                                     1)), 2, 3, 0, 1)

    elif (boundary == 'top'):

        sheared_coordinates = self.q1_center[:, :, :,
                                             -N_g:] + q * omega * L_q2 * self.time_elapsed

        # Applying periodic boundary conditions to the points which are out of domain:
        while (af.sum(sheared_coordinates > self.q1_end) != 0):
            sheared_coordinates = af.select(sheared_coordinates > self.q1_end,
                                            sheared_coordinates - L_q1,
                                            sheared_coordinates)

        while (af.sum(sheared_coordinates < self.q1_start) != 0):
            sheared_coordinates = af.select(
                sheared_coordinates < self.q1_start,
                sheared_coordinates + L_q1, sheared_coordinates)

        # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
        # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)

        self.f[:, :, :, -N_g:] = af.reorder(
            af.approx2(af.reorder(self.f[:, :, :, -N_g:], 2, 3, 0, 1),
                       af.reorder(sheared_coordinates, 2, 3, 0, 1),
                       af.reorder(self.q2_center[:, :, :, -N_g:], 2, 3, 0, 1),
                       af.INTERP.BICUBIC_SPLINE,
                       xp=af.reorder(self.q1_center[:, :, :, -N_g:], 2, 3, 0,
                                     1),
                       yp=af.reorder(self.q2_center[:, :, :, -N_g:], 2, 3, 0,
                                     1)), 2, 3, 0, 1)

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

    return
示例#27
0
def dY_dt_multimode_evolution(Y, self):
    """
    Returns the value of the derivative of the fourier mode quantities 
    of the distribution function, and the field quantities with 
    respect to time. This is used to evolve the system in time.

    Input:
    ------

      Y  : The array Y is the state of the system as given by the result of 
           the last time-step's integration. The elements of Y, hold the 
           following data:
     
           f_hat  = Y[:, :, :, 0]
           E1_hat = Y[:, :, :, 1]
           E2_hat = Y[:, :, :, 2]
           E3_hat = Y[:, :, :, 3]
           B1_hat = Y[:, :, :, 4]
           B2_hat = Y[:, :, :, 5]
           B3_hat = Y[:, :, :, 6]
     
           At t = 0 the initial state of the system is passed to this function:

    Output:
    -------
    dY_dt : The time-derivatives of all the quantities stored in Y
    
    """
    f_hat = Y[:, :, :, 0]
    
    self.E1_hat = Y[:, :, :, 1]
    self.E2_hat = Y[:, :, :, 2]
    self.E3_hat = Y[:, :, :, 3]
    self.B1_hat = Y[:, :, :, 4]
    self.B2_hat = Y[:, :, :, 5]
    self.B3_hat = Y[:, :, :, 6]

    # Scaling Appropriately:
    f       = af.real(af.ifft2(0.5 * self.N_q2 * self.N_q1 * f_hat))
    C_f_hat = 2 * af.fft2(self._source(f, self.q1_center, self.q2_center,
                                       self.p1, self.p2, self.p3,
                                       self.compute_moments, 
                                       self.physical_system.params
                                      )
                         )/(self.N_q2 * self.N_q1)

    if(   self.physical_system.params.fields_solver == 'electrostatic'
       or self.physical_system.params.fields_solver == 'fft'
      ):
        compute_electrostatic_fields(self, f_hat=f_hat)

    # When method is FDTD, this function returns the timederivatives
    # of the field quantities which is stepped using a numerical integrator:
    elif(self.physical_system.params.fields_solver == 'fdtd'):
        pass

    else:
        raise NotImplementedError('Method invalid/not-implemented')
    
    mom_bulk_p1 = self.compute_moments('mom_p1_bulk', f_hat=f_hat)
    mom_bulk_p2 = self.compute_moments('mom_p2_bulk', f_hat=f_hat)
    mom_bulk_p3 = self.compute_moments('mom_p3_bulk', f_hat=f_hat)

    J1_hat = 2 * af.fft2(  self.physical_system.params.charge_electron 
                         * mom_bulk_p1
                        )/(self.N_q1 * self.N_q2)
    
    J2_hat = 2 * af.fft2(  self.physical_system.params.charge_electron
                         * mom_bulk_p2
                        )/(self.N_q1 * self.N_q2)

    J3_hat = 2 * af.fft2(  self.physical_system.params.charge_electron
                         * mom_bulk_p3
                        )/(self.N_q1 * self.N_q2)

    # Defining lambda functions to perform broadcasting operations:
    # This is done using af.broadcast, which allows us to perform 
    # batched operations when operating on arrays of different sizes:

    multiply = lambda a,b:a * b
    addition = lambda a,b:a + b
    
    # af.broadcast(function, *args) performs batched operations on
    # function(*args):

    dE1_hat_dt = af.broadcast(addition, 
                              af.broadcast(multiply, self.B3_hat, 1j * self.k_q2),
                              - J1_hat
                             )

    dE2_hat_dt = af.broadcast(addition,
                              af.broadcast(multiply,-self.B3_hat, 1j * self.k_q1),
                              - J2_hat
                             )

    dE3_hat_dt = af.broadcast(addition, 
                                af.broadcast(multiply, self.B2_hat, 1j * self.k_q1)
                              - af.broadcast(multiply, self.B1_hat, 1j * self.k_q2), 
                              - J3_hat
                             )

    dB1_hat_dt = af.broadcast(multiply, -self.E3_hat, 1j * self.k_q2)
    dB2_hat_dt = af.broadcast(multiply, self.E3_hat, 1j * self.k_q1)
    dB3_hat_dt =   af.broadcast(multiply, self.E1_hat, 1j * self.k_q2) \
                 - af.broadcast(multiply, self.E2_hat, 1j * self.k_q1)

    (A_p1, A_p2, A_p3) = af.broadcast(self._A_p, self.q1_center, self.q2_center,
                                      self.p1, self.p2, self.p3,
                                      self.E1_hat, self.E2_hat, self.E3_hat,
                                      self.B1_hat, self.B2_hat, self.B3_hat,
                                      self.physical_system.params
                                     )

    df_hat_dt  = -1j * (  af.broadcast(multiply, self.k_q1, self._A_q1)
                        + af.broadcast(multiply, self.k_q2, self._A_q2)
                       ) * f_hat

    
    # Adding the fields term only when charge is non-zero
    if(self.physical_system.params.charge_electron != 0):

        fields_term =   af.broadcast(multiply, A_p1, self.dfdp1_background) \
                      + af.broadcast(multiply, A_p2, self.dfdp2_background) \
                      + af.broadcast(multiply, A_p3, self.dfdp3_background)

        df_hat_dt  -= fields_term

    # Avoiding addition of the collisional term when tau != inf
    tau = self.physical_system.params.tau(self.q1_center, 
                                          self.q2_center,
                                          self.p1, self.p2, self.p3
                                         )

    df_hat_dt += af.select(tau != np.inf,\
                           C_f_hat,\
                           0
                          )
    
    # Obtaining the dY_dt vector by joining the derivative quantities of
    # the individual distribution function and field modes:
    dY_dt = af.join(3, af.join(3, df_hat_dt, dE1_hat_dt, dE2_hat_dt, dE3_hat_dt),
                    dB1_hat_dt, dB2_hat_dt, dB3_hat_dt
                   )

    af.eval(dY_dt)
    return(dY_dt)
示例#28
0
文件: post.py 项目: mchandra/Bolt
y = r * np.sin(theta)

for time_index, t0 in enumerate(time):

    h5f = h5py.File('dump/%04d' % (time_index) + '.h5', 'r')
    n = np.swapaxes(h5f['moments'][:], 0, 1)[:, :, 0]
    h5f.close()

    pl.plot(x_analytic[time_index],
            y_analytic[time_index],
            'o',
            color='white',
            alpha=0.05)

    import arrayfire as af
    n = np.array(af.select(af.to_array(n) < 0, 0, af.to_array(n)))

    pl.contourf(x, y, n, 200)
    pl.gca().set_aspect('equal')
    pl.xlim(0, 4)
    pl.ylim(-4, 4)
    pl.xlabel(r'$x$')
    pl.ylabel(r'$y$')
    pl.title('Time = %.3f' % t0)
    pl.savefig('images/%04d' % time_index + '.png')
    pl.clf()

# ax2 = fig.add_subplot(1, 2, 2)
# ax2.plot(x_analytic[time_index+1], y_analytic[time_index+1], 'or')
# ax2.set_xlim(0, 4)
# ax2.set_ylim(-4, 4)
示例#29
0
def test_shear_y():

    t = np.random.rand(1)[0]
    N = 2**np.arange(5, 10)
    error = np.zeros(N.size)

    for i in range(N.size):
        domain.N_q1 = int(N[i])
        domain.N_q2 = int(N[i])

        # Defining the physical system to be solved:
        system = physical_system(domain, boundary_conditions_y, params,
                                 initialize_y, advection_terms,
                                 collision_operator.BGK, moment_defs)

        L_q1 = domain.q1_end - domain.q1_start
        L_q2 = domain.q2_end - domain.q2_start

        nls = nonlinear_solver(system)
        N_g = nls.N_ghost_q

        # For left:
        f_reference_bot = af.broadcast(
            initialize_y.initialize_f,
            af.select(
                nls.q1_center - t < domain.q1_start,  # Periodic domain
                nls.q1_center - t + L_q1,
                nls.q1_center - t),
            nls.q2_center,
            nls.p1_center,
            nls.p2_center,
            nls.p3_center,
            params)[:, N_g:-N_g, -2 * N_g:-N_g]

        # For right:
        f_reference_top = af.broadcast(
            initialize_y.initialize_f,
            af.select(nls.q1_center + t > domain.q1_end,
                      nls.q1_center + t - L_q1, nls.q1_center + t),
            nls.q2_center, nls.p1_center, nls.p2_center, nls.p3_center,
            params)[:, N_g:-N_g, N_g:2 * N_g]

        nls.time_elapsed = t
        nls._communicate_f()
        nls._apply_bcs_f()

        error[i] =   af.mean(af.abs(nls.f[:, N_g:-N_g, :N_g] - f_reference_bot)) \
                   + af.mean(af.abs(nls.f[:, N_g:-N_g, -N_g:] - f_reference_top))

    pl.loglog(N, error, '-o', label='Numerical')
    pl.loglog(N,
              error[0] * 32**3 / N**3,
              '--',
              color='black',
              label=r'$O(N^{-3})$')
    pl.xlabel(r'$N$')
    pl.ylabel('Error')
    pl.legend()
    pl.savefig('plot2.png')

    poly = np.polyfit(np.log10(N), np.log10(error), 1)
    assert (abs(poly[0] + 3) < 0.3)
示例#30
0
def apply_dirichlet_bcs_f(self, boundary):

    N_g = self.N_ghost

    if (self._A_q1.elements() == self.N_p1 * self.N_p2 * self.N_p3):
        # A_q1 is of shape (Np1 * Np2 * Np3)
        # We tile to get it to form (Np1 * Np2 * Np3, Nq1, Nq2)
        A_q1 = af.tile(self._A_q1, 1, self.f.shape[1], self.f.shape[2])

    if (self._A_q2.elements() == self.N_p1 * self.N_p2 * self.N_p3):
        # _A_q2 is of shape (Np1 * Np2 * Np3)
        # We tile to get it to form (Np1 * Np2 * Np3, Nq1, Nq2)
        A_q2 = af.tile(self._A_q2, 1, self.f.shape[1], self.f.shape[2])

    if (boundary == 'left'):
        f_left = self.boundary_conditions.\
                 f_left(self.f, self.q1_center, self.q2_center,
                        self.p1, self.p2, self.p3,
                        self.physical_system.params
                       )

        # Only changing inflowing characteristics:
        f_left = af.select(A_q1 > 0, f_left, self.f)

        self.f[:, :N_g] = f_left[:, :N_g]

    elif (boundary == 'right'):
        f_right = self.boundary_conditions.\
                  f_right(self.f, self.q1_center, self.q2_center,
                          self.p1, self.p2, self.p3,
                          self.physical_system.params
                         )

        # Only changing inflowing characteristics:
        f_right = af.select(A_q1 < 0, f_right, self.f)

        self.f[:, -N_g:] = f_right[:, -N_g:]

    elif (boundary == 'bottom'):
        f_bottom = self.boundary_conditions.\
                   f_bottom(self.f, self.q1_center, self.q2_center,
                            self.p1, self.p2, self.p3,
                            self.physical_system.params
                           )

        # Only changing inflowing characteristics:
        f_bottom = af.select(A_q2 > 0, f_bottom, self.f)

        self.f[:, :, :N_g] = f_bottom[:, :, :N_g]

    elif (boundary == 'top'):
        f_top = self.boundary_conditions.\
                f_top(self.f, self.q1_center, self.q2_center,
                      self.p1, self.p2, self.p3,
                      self.physical_system.params
                     )

        # Only changing inflowing characteristics:
        f_top = af.select(A_q2 < 0, f_top, self.f)

        self.f[:, :, -N_g:] = f_top[:, :, -N_g:]

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

    return
示例#31
0
def apply_shearing_box_bcs_fields(self, boundary, on_fdtd_grid):
    """
    Applies the shearing box 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
    q = self.physical_system.params.q
    omega = self.physical_system.params.omega

    L_q1 = self.q1_end - self.q1_start
    L_q2 = self.q2_end - self.q2_start

    if (boundary == 'left'):
        sheared_coordinates = self.q2_center[:, :, :
                                             N_g_q] - q * omega * L_q1 * self.time_elapsed

        # Applying periodic boundary conditions to the points which are out of domain:
        while (af.sum(sheared_coordinates > self.q2_end) != 0):
            sheared_coordinates = af.select(sheared_coordinates > self.q2_end,
                                            sheared_coordinates - L_q2,
                                            sheared_coordinates)

        while (af.sum(sheared_coordinates < self.q2_start) != 0):
            sheared_coordinates = af.select(
                sheared_coordinates < self.q2_start,
                sheared_coordinates + L_q2, sheared_coordinates)
        if (on_fdtd_grid == True):
            # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
            # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)
            self.yee_grid_EM_fields[:, :, :N_g_q] = \
                af.reorder(af.approx2(af.reorder(self.yee_grid_EM_fields[:, :, :N_g_q], 2, 3, 0, 1),
                                      af.reorder(self.q1_center[:, :, :N_g_q], 2, 3, 0, 1),
                                      af.reorder(sheared_coordinates, 2, 3, 0, 1),
                                      af.INTERP.BICUBIC_SPLINE,
                                      xp = af.reorder(self.q1_center[:, :, :N_g_q], 2, 3, 0, 1),
                                      yp = af.reorder(self.q2_center[:, :, :N_g_q], 2, 3, 0, 1)
                                     ),
                           2, 3, 0, 1
                          )

        else:
            # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
            # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)
            self.cell_centered_EM_fields[:, :, :N_g_q] = \
                af.reorder(af.approx2(af.reorder(self.cell_centered_EM_fields[:, :, :N_g_q], 2, 3, 0, 1),
                                      af.reorder(self.q1_center[:, :, :N_g_q], 2, 3, 0, 1),
                                      af.reorder(sheared_coordinates, 2, 3, 0, 1),
                                      af.INTERP.BICUBIC_SPLINE,
                                      xp = af.reorder(self.q1_center[:, :, :N_g_q], 2, 3, 0, 1),
                                      yp = af.reorder(self.q2_center[:, :, :N_g_q], 2, 3, 0, 1)
                                     ),
                           2, 3, 0, 1
                          )

    elif (boundary == 'right'):
        sheared_coordinates = self.q2_center[:, :,
                                             -N_g_q:] + q * omega * L_q1 * self.time_elapsed

        # Applying periodic boundary conditions to the points which are out of domain:
        while (af.sum(sheared_coordinates > self.q2_end) != 0):
            sheared_coordinates = af.select(sheared_coordinates > self.q2_end,
                                            sheared_coordinates - L_q2,
                                            sheared_coordinates)

        while (af.sum(sheared_coordinates < self.q2_start) != 0):
            sheared_coordinates = af.select(
                sheared_coordinates < self.q2_start,
                sheared_coordinates + L_q2, sheared_coordinates)

        if (on_fdtd_grid == True):
            # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
            # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)
            self.yee_grid_EM_fields[:, :, -N_g_q:] = \
                af.reorder(af.approx2(af.reorder(self.yee_grid_EM_fields[:, :, -N_g_q:], 2, 3, 0, 1),
                                      af.reorder(self.q1_center[:, :, -N_g_q:], 2, 3, 0, 1),
                                      af.reorder(sheared_coordinates, 2, 3, 0, 1),
                                      af.INTERP.BICUBIC_SPLINE,
                                      xp = af.reorder(self.q1_center[:, :, -N_g_q:], 2, 3, 0, 1),
                                      yp = af.reorder(self.q2_center[:, :, -N_g_q:], 2, 3, 0, 1)
                                     ),
                           2, 3, 0, 1
                          )

        else:
            # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
            # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)
            self.cell_centered_EM_fields[:, :, -N_g_q:] = \
                af.reorder(af.approx2(af.reorder(self.cell_centered_EM_fields[:, :, -N_g_q:],2, 3, 0, 1),
                                      af.reorder(self.q1_center[:, :, -N_g_q:], 2, 3, 0, 1),
                                      af.reorder(sheared_coordinates, 2, 3, 0, 1),
                                      af.INTERP.BICUBIC_SPLINE,
                                      xp = af.reorder(self.q1_center[:, :, -N_g_q:], 2, 3, 0, 1),
                                      yp = af.reorder(self.q2_center[:, :, -N_g_q:], 2, 3, 0, 1)
                                     ),
                           2, 3, 0, 1
                          )

    elif (boundary == 'bottom'):

        sheared_coordinates = self.q1_center[:, :, :, :
                                             N_g_q] - q * omega * L_q2 * self.time_elapsed

        # Applying periodic boundary conditions to the points which are out of domain:
        while (af.sum(sheared_coordinates > self.q1_end) != 0):
            sheared_coordinates = af.select(sheared_coordinates > self.q1_end,
                                            sheared_coordinates - L_q1,
                                            sheared_coordinates)

        while (af.sum(sheared_coordinates < self.q1_start) != 0):
            sheared_coordinates = af.select(
                sheared_coordinates < self.q1_start,
                sheared_coordinates + L_q1, sheared_coordinates)

        if (on_fdtd_grid == True):
            # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
            # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)
            self.yee_grid_EM_fields[:, :, :, :N_g_q] = \
                af.reorder(af.approx2(af.reorder(self.yee_grid_EM_fields[:, :, :, :N_g_q], 2, 3, 0, 1),
                                      af.reorder(sheared_coordinates, 2, 3, 0, 1),
                                      af.reorder(self.q2_center[:, :, :, :N_g_q], 2, 3, 0, 1),
                                      af.INTERP.BICUBIC_SPLINE,
                                      xp = af.reorder(self.q1_center[:, :, :, :N_g_q], 2, 3, 0, 1),
                                      yp = af.reorder(self.q2_center[:, :, :, :N_g_q], 2, 3, 0, 1)
                                     ),
                           2, 3, 0, 1
                          )

        else:
            # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
            # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)
            self.cell_centered_EM_fields[:, :, :, :N_g_q] = \
                af.reorder(af.approx2(af.reorder(self.cell_centered_EM_fields[:, :, :, :N_g_q], 2, 3, 0, 1),
                                      af.reorder(sheared_coordinates, 2, 3, 0, 1),
                                      af.reorder(self.q2_center[:, :, :, :N_g_q], 2, 3, 0, 1),
                                      af.INTERP.BICUBIC_SPLINE,
                                      xp = af.reorder(self.q1_center[:, :, :, :N_g_q], 2, 3, 0, 1),
                                      yp = af.reorder(self.q2_center[:, :, :, :N_g_q], 2, 3, 0, 1)
                                     ),
                           2, 3, 0, 1
                          )

    elif (boundary == 'top'):

        sheared_coordinates = self.q1_center[:, :, :,
                                             -N_g_q:] + q * omega * L_q2 * self.time_elapsed

        # Applying periodic boundary conditions to the points which are out of domain:
        while (af.sum(sheared_coordinates > self.q1_end) != 0):
            sheared_coordinates = af.select(sheared_coordinates > self.q1_end,
                                            sheared_coordinates - L_q1,
                                            sheared_coordinates)

        while (af.sum(sheared_coordinates < self.q1_start) != 0):
            sheared_coordinates = af.select(
                sheared_coordinates < self.q1_start,
                sheared_coordinates + L_q1, sheared_coordinates)

        if (on_fdtd_grid == True):
            # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
            # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)
            self.yee_grid_EM_fields[:, :, :, -N_g_q:] = \
                af.reorder(af.approx2(af.reorder(self.yee_grid_EM_fields[:, :, :, -N_g_q:], 2, 3, 0, 1),
                                      af.reorder(sheared_coordinates, 2, 3, 0, 1),
                                      af.reorder(self.q2_center[:, :, :, -N_g_q:], 2, 3, 0, 1),
                                      af.INTERP.BICUBIC_SPLINE,
                                      xp = af.reorder(self.q1_center[:, :, :, -N_g_q:], 2, 3, 0, 1),
                                      yp = af.reorder(self.q2_center[:, :, :, -N_g_q:], 2, 3, 0, 1)
                                     ),
                           2, 3, 0, 1
                          )

        else:
            # Reordering from (N_p, N_s, N_q1, N_q2) --> (N_q1, N_q2, N_p, N_s)
            # and reordering back from (N_q1, N_q2, N_p, N_s) --> (N_p, N_s, N_q1, N_q2)
            self.cell_centered_EM_fields[:, :, :, -N_g_q:] = \
                af.reorder(af.approx2(af.reorder(self.cell_centered_EM_fields[:, :, :, -N_g_q:], 2, 3, 0, 1),
                                      af.reorder(sheared_coordinates, 2, 3, 0, 1),
                                      af.reorder(self.q2_center[:, :, :, -N_g_q:], 2, 3, 0, 1),
                                      af.INTERP.BICUBIC_SPLINE,
                                      xp = af.reorder(self.q1_center[:, :, :, -N_g_q:], 2, 3, 0, 1),
                                      yp = af.reorder(self.q2_center[:, :, :, -N_g_q:], 2, 3, 0, 1)
                                     ),
                           2, 3, 0, 1
                          )

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

    return