예제 #1
0
def boris_algorithm(v0, Bp, Ep, dt, idx):
    '''Updates the velocities of the particles in the simulation using a Boris particle pusher, as detailed
    in Birdsall & Langdon (1985),  59-63.

    INPUT:
        v0   -- Original particle velocity
        B    -- Magnetic field value at particle  position
        E    -- Electric field value at particle position
        dt   -- Simulation time cadence
        idx  -- Particle species identifier

    OUTPUT:
        v0   -- Updated particle velocity (overwrites input value on return)
        
    DOES SINGLE PARTICLE (NEW FUNCTION)
    '''
    T = (charge[idx] * Bp / mass[idx]) * dt / 2.  # Boris variable
    S = 2. * T / (1. + T[0]**2 + T[1]**2 + T[2]**2)  # Boris variable

    v_minus = v0 + charge[idx] * Ep * dt / (2. * mass[idx])
    v_prime = v_minus + cross_product_single(v_minus, T)
    v_plus = v_minus + cross_product_single(v_prime, S)

    v0 = v_plus + charge[idx] * Ep * dt / (2. * mass[idx])
    return v0
예제 #2
0
def two_part_velocity_update(part, B, E, dt):
    ''' Backup velocity update from Matthews (1994), just in case Boris isn't compatible with it.
    
    Advances velocity full timestep by first approximating half timestep.
    '''
    W_magnetic = assign_weighting(part[0, :], part[1, :],
                                  0)  # Magnetic field weighting

    for jj in range(Nj):
        for nn in range(idx_bounds[jj, 0], idx_bounds[jj, 1]):
            I = int(part[1, nn])  # Nearest (leftmost) node, I
            Ib = int(part[0, nn] / dx)  # Nearest (leftmost) magnetic node
            We = part[2, nn]  # E-field weighting
            Wb = W_magnetic[nn]  # B-field weighting
            idx = jj  # Particle species identifier

            Ep = E[I, 0:3] * (
                1 - We) + E[I + 1, 0:3] * We  # E-field at particle location
            Bp = B[Ib, 0:3] * (
                1 - Wb) + B[Ib + 1, 0:3] * Wb  # B-field at particle location

            fac = 0.5 * dt * charge[idx] / mass[idx]
            v_half = part[3:6] + fac * (Ep +
                                        cross_product_single(part[3:6], Bp))

            part[3:6] += 2 * fac * (Ep + cross_product_single(v_half, Bp))

    return part
예제 #3
0
def velocity_update(vel, Ie, W_elec, Ib, W_mag, idx, B, E, dt):
    '''
    Interpolates the fields to the particle positions using TSC weighting, then
    updates velocities using a Boris particle pusher.
    Based on Birdsall & Langdon (1985), pp. 59-63.

    INPUT:
        part -- Particle array containing velocities to be updated
        B    -- Magnetic field on simulation grid
        EIb, W_mag = assign_weighting_TSC(pos, E_nodes=False)    -- Electric field on simulation grid
        dt   -- Simulation time cadence
        W    -- Weighting factor of particles to rightmost node

    OUTPUT:
        vel  -- Returns particle array with updated velocities
    '''
    Ep = E[Ie    , 0:3] * W_elec[0]                 \
       + E[Ie + 1, 0:3] * W_elec[1]                 \
       + E[Ie + 2, 0:3] * W_elec[2]                 # E-field at particle location

    Bp = B[Ib    , 0:3] * W_mag[0]                  \
       + B[Ib + 1, 0:3] * W_mag[1]                  \
       + B[Ib + 2, 0:3] * W_mag[2]                  # B-field at particle location

    T = (charge[idx] * Bp / mass[idx]) * dt / 2.  # Boris variable
    S = 2. * T / (1. + T[0]**2 + T[1]**2 + T[2]**2)  # Boris variable

    v_minus = vel + charge[idx] * Ep * dt / (2. * mass[idx])
    v_prime = v_minus + aux.cross_product_single(v_minus, T)
    v_plus = v_minus + aux.cross_product_single(v_prime, S)

    vel = v_plus + charge[idx] * Ep * dt / (2. * mass[idx])
    return vel
예제 #4
0
def two_step_algorithm(v0, Bp, Ep, dt, idx):
    fac = 0.5 * dt * charge[idx] / mass[idx]
    v_half = v0 + fac * (Ep + aux.cross_product_single(v0, Bp))
    v0 += 2 * fac * (Ep + aux.cross_product_single(v_half, Bp))
    return v0