Esempio n. 1
0
def numerical_loop(real_time, pos, vel, Ie, W_elec, idx, B, E_int, q_dens, Ji,
                   Ve, Te, DT, max_inc, data_iter, ch_flag):
    '''
    Does the number crunching for a short snippet. Logs number of time variable changes in ch_flag as powers of 2
    (-1 = half, 2 = 4 times slower)
    
    Array values are mutable: Don't have to be returned. Only integer values
    '''

    qq = 0
    while qq < data_iter:
        # Check timestep used for this iteration
        vel, qq, DT, max_inc, data_iter, ch_flag = aux.check_timestep(
            qq, DT, pos, vel, B, E_int, q_dens, Ie, W_elec, max_inc, data_iter,
            idx)

        # Add timestep to counter
        real_time += DT

        # Main loop
        pos, vel, Ie, W_elec, q_dens_adv, Ji = particles.advance_particles_and_moments(
            pos, vel, Ie, W_elec, idx, B, E_int, DT)
        q_dens = 0.5 * (q_dens + q_dens_adv)
        B = fields.push_B(B, E_int, DT)
        E_half, Ve, Te = fields.calculate_E(B, Ji, q_dens)
        q_dens = q_dens_adv.copy()

        # Predictor-Corrector: Advance fields to start of next timestep
        E_int, B = fields.predictor_corrector(B, E_int, E_half, pos, vel,
                                              q_dens_adv, Ie, W_elec, idx, DT)

        # Increment loop variable
        qq += 1
    return DT, ch_flag, max_inc, data_iter, real_time
Esempio n. 2
0
def test_push_B_w_varying_background():
    max_inc = 101
    DT = 1.0
    x_offset = 200e-9

    E = np.zeros((const.NX + 3, 3))
    B = np.zeros((const.NX + 3, 3), dtype=float)
    x = np.arange(const.NX + 3)
    #fig, ax = plt.subplots()

    B[:, 0] += x_offset

    qq = 1
    while qq < max_inc:
        # push_B(B, E, DT, qq)
        B = fields.push_B(B, E, DT, qq, half_flag=1)
        print('t = {}s, B = {}nT'.format((qq - 0.5) * DT, B[0, :] * 1e9))
        # =============================================================================
        #         ax.clear()
        #         ax.plot(x, B[:, 0] * 1e9)
        #         ax.plot(x, B[:, 1] * 1e9)
        #         ax.plot(x, B[:, 2] * 1e9)
        #         ax.set_title('Bx at t = {}'.format((qq - 0.5) * DT))
        #         ax.set_ylim(-(const.HM_amplitude + x_offset)*1e9, (const.HM_amplitude + x_offset)*1e9)
        #         ax.set_xlim(0, const.NX + 3)
        #         ax.set_ylabel('Magnetic Field (nT)')
        #         ax.set_xlabel('Cell number')
        #         plt.pause(0.1)
        # =============================================================================

        B = fields.push_B(B, E, DT, qq, half_flag=0)
        print('t = {}s, B = {}nT'.format(qq * DT, B[0, :] * 1e9))
        # =============================================================================
        #         ax.clear()
        #         ax.plot(x, B[:, 0] * 1e9)
        #         ax.plot(x, B[:, 1] * 1e9)
        #         ax.plot(x, B[:, 2] * 1e9)
        #         ax.set_title('Bx at t = {}'.format(qq * DT))
        #         ax.set_ylim(-(const.HM_amplitude + x_offset)*1e9, (const.HM_amplitude + x_offset)*1e9)
        #         ax.set_xlim(0, const.NX + 3)
        #         ax.set_ylabel('Magnetic Field (nT)')
        #         ax.set_xlabel('Cell number')
        #         plt.pause(0.1)
        # =============================================================================

        qq += 1
    return
Esempio n. 3
0
def main_loop(pos, vel, idx, Ie, W_elec, Ib, W_mag, Ep, Bp, v_prime, S, T,temp_N,                      \
              B, E_int, E_half, q_dens, q_dens_adv, Ji, ni, nu, mp_flux,       \
              Ve, Te, Te0, temp3De, temp3Db, temp1D, old_particles, old_fields,\
              B_damping_array, E_damping_array, qq, DT, max_inc, part_save_iter, field_save_iter):
    '''
    Main loop separated from __main__ function, since this is the actual computation bit.
    Could probably be optimized further, but I wanted to njit() it.
    The only reason everything's not njit() is because of the output functions.
    
    Future: Come up with some way to loop until next save point
    
    Thoughts: declare a variable steps_to_go. Output all time variables at return
    to resync everything, and calculate steps to next stop.
    If no saves, steps_to_go = max_inc
    '''
    # Check timestep
    qq, DT, max_inc, part_save_iter, field_save_iter, damping_array \
    = check_timestep(pos, vel, B, E_int, q_dens, Ie, W_elec, Ib, W_mag, temp3De, Ep, Bp, v_prime, S, T,temp_N,\
                     qq, DT, max_inc, part_save_iter, field_save_iter, idx, B_damping_array)

    # =============================================================================
    #     # Check number of spare particles every 25 steps
    #     if qq%25 == 0 and particle_open == 1:
    #         num_spare = (idx < 0).sum()
    #         if num_spare < inject_rate.sum() * DT * 5.0:
    #             # Change this to dynamically expand particle arrays later on (adding more particles)
    #             print('WARNING :: Less than 5 time increments of spare particles remaining. Widening arrays...')
    #             pos, vel, idx, Ie, W_elec, Ib, W_mag, Ep, Bp, v_prime, S, T, temp_N, old_particles = \
    #             increase_particle_array_size(pos, vel, idx, Ie, W_elec, Ib, W_mag, Ep, Bp, v_prime,
    #                                          S, T, temp_N, old_particles)
    # =============================================================================

    # Move particles, collect moments
    particles.advance_particles_and_moments(pos, vel, Ie, W_elec, Ib, W_mag, idx, Ep, Bp, v_prime, S, T,temp_N,\
                                            B, E_int, DT, q_dens_adv, Ji, ni, nu, mp_flux)

    # Average N, N + 1 densities (q_dens at N + 1/2)
    q_dens *= 0.5
    q_dens += 0.5 * q_dens_adv

    # Push B from N to N + 1/2
    fields.push_B(B, E_int, temp3Db, DT, qq, B_damping_array, half_flag=1)

    # Calculate E at N + 1/2
    fields.calculate_E(B, Ji, q_dens, E_half, Ve, Te, Te0, temp3De, temp3Db,
                       temp1D, E_damping_array)

    ###################################
    ### PREDICTOR CORRECTOR SECTION ###
    ###################################

    # Store old values
    mp_flux_old = mp_flux.copy()
    old_particles[0, :] = pos
    old_particles[1:4, :] = vel
    old_particles[4, :] = Ie
    old_particles[5:8, :] = W_elec
    old_particles[8, :] = idx

    old_fields[:, 0:3] = B
    old_fields[:NC, 3:6] = Ji
    old_fields[:NC, 6:9] = Ve
    old_fields[:NC, 9] = Te

    # Predict fields
    E_int *= -1.0
    E_int += 2.0 * E_half

    fields.push_B(B, E_int, temp3Db, DT, qq, B_damping_array, half_flag=0)

    # Advance particles to obtain source terms at N + 3/2
    particles.advance_particles_and_moments(pos, vel, Ie, W_elec, Ib, W_mag, idx, Ep, Bp, v_prime, S, T,temp_N,\
                                            B, E_int, DT, q_dens, Ji, ni, nu, mp_flux, pc=1)

    q_dens *= 0.5
    q_dens += 0.5 * q_dens_adv

    # Compute predicted fields at N + 3/2
    fields.push_B(B, E_int, temp3Db, DT, qq + 1, B_damping_array, half_flag=1)
    fields.calculate_E(B, Ji, q_dens, E_int, Ve, Te, Te0, temp3De, temp3Db,
                       temp1D, E_damping_array)

    # Determine corrected fields at N + 1
    E_int *= 0.5
    E_int += 0.5 * E_half

    # Restore old values: [:] allows reference to same memory (instead of creating new, local instance)
    pos[:] = old_particles[0, :]
    vel[:] = old_particles[1:4, :]
    Ie[:] = old_particles[4, :]
    W_elec[:] = old_particles[5:8, :]
    idx[:] = old_particles[8, :]

    B[:] = old_fields[:, 0:3]
    Ji[:] = old_fields[:NC, 3:6]
    Ve[:] = old_fields[:NC, 6:9]
    Te[:] = old_fields[:NC, 9]

    fields.push_B(B, E_int, temp3Db, DT, qq, B_damping_array,
                  half_flag=0)  # Advance the original B

    q_dens[:] = q_dens_adv
    mp_flux = mp_flux_old.copy()

    return qq, DT, max_inc, part_save_iter, field_save_iter
Esempio n. 4
0
def main_loop(pos, vel, idx, Ie, W_elec, Ib, W_mag,                      \
              B, E_int, E_half, q_dens, q_dens_adv, Ji, ni, nu,          \
              Ve, Te, temp3D, temp3D2, temp1D, old_particles, old_fields,\
              qq, DT, max_inc, part_save_iter, field_save_iter):
    '''
    Main loop separated from __main__ function, since this is the actual computation bit.
    Could probably be optimized further, but I wanted to njit() it.
    The only reason everything's not njit() is because of the output functions.
    
    Future: Come up with some way to loop until next save point
    
    Thoughts: declare a variable steps_to_go. Output all time variables at return
    to resync everything, and calculate steps to next stop.
    If no saves, steps_to_go = max_inc
    '''
    # Check timestep
    qq, DT, max_inc, part_save_iter, field_save_iter \
    = check_timestep(pos, vel, B, E_int, q_dens, Ie, W_elec, Ib, W_mag, temp3D, \
                     qq, DT, max_inc, part_save_iter, field_save_iter, idx)

    # Move particles, collect moments
    particles.advance_particles_and_moments(pos, vel, Ie, W_elec, Ib, W_mag, idx, \
                                            B, E_int, DT, q_dens_adv, Ji, ni, nu, temp1D)

    # Average N, N + 1 densities (q_dens at N + 1/2)
    q_dens *= 0.5
    q_dens += 0.5 * q_dens_adv

    # Push B from N to N + 1/2
    fields.push_B(B, E_int, temp3D, DT, qq, half_flag=1)

    # Calculate E at N + 1/2
    fields.calculate_E(B, Ji, q_dens, E_half, Ve, Te, temp3D, temp3D2, temp1D)

    ###################################
    ### PREDICTOR CORRECTOR SECTION ###
    ###################################

    # Store old values
    old_particles[0, :] = pos
    old_particles[1:4, :] = vel
    old_particles[4, :] = Ie
    old_particles[5:8, :] = W_elec

    old_fields[:, 0:3] = B
    old_fields[:, 3:6] = Ji
    old_fields[:, 6:9] = Ve
    old_fields[:, 9] = Te

    # Predict fields
    E_int *= -1.0
    E_int += 2.0 * E_half

    fields.push_B(B, E_int, temp3D, DT, qq, half_flag=0)

    # Advance particles to obtain source terms at N + 3/2
    particles.advance_particles_and_moments(pos, vel, Ie, W_elec, Ib, W_mag, idx, \
                                            B, E_int, DT, q_dens, Ji, ni, nu, temp1D, pc=1)

    q_dens *= 0.5
    q_dens += 0.5 * q_dens_adv

    # Compute predicted fields at N + 3/2
    fields.push_B(B, E_int, temp3D, DT, qq + 1, half_flag=1)
    fields.calculate_E(B, Ji, q_dens, E_int, Ve, Te, temp3D, temp3D2, temp1D)

    # Determine corrected fields at N + 1
    E_int *= 0.5
    E_int += 0.5 * E_half

    # Restore old values: [:] allows reference to same memory (instead of creating new, local instance)
    pos[:] = old_particles[0, :]
    vel[:] = old_particles[1:4, :]
    Ie[:] = old_particles[4, :]
    W_elec[:] = old_particles[5:8, :]
    B[:] = old_fields[:, 0:3]
    Ji[:] = old_fields[:, 3:6]
    Ve[:] = old_fields[:, 6:9]
    Te[:] = old_fields[:, 9]

    fields.push_B(B, E_int, temp3D, DT, qq,
                  half_flag=0)  # Advance the original B

    q_dens[:] = q_dens_adv

    return qq, DT, max_inc, part_save_iter, field_save_iter
Esempio n. 5
0
        # Check timestep
        vel, qq, DT, max_inc, data_iter, ch_flag \
        = aux.check_timestep(qq, DT, pos, vel, B, E_int, q_dens, Ie, W_elec, max_inc, data_iter, idx)

        if ch_flag == 1:
            print 'Timestep halved. Syncing particle velocity with DT = {}'.format(
                DT)
        elif ch_flag == 2:
            print 'Timestep Doubled. Syncing particle velocity with DT = {}'.format(
                DT)

        # Main loop
        pos, vel, Ie, W_elec, q_dens_adv, Ji = particles.advance_particles_and_moments(
            pos, vel, Ie, W_elec, idx, B, E_int, DT)
        q_dens = 0.5 * (q_dens + q_dens_adv)
        B = fields.push_B(B, E_int, DT)
        E_half, Ve, Te = fields.calculate_E(B, Ji, q_dens)
        q_dens = q_dens_adv.copy()

        # Predictor-Corrector: Advance fields to start of next timestep
        E_int, B = fields.predictor_corrector(B, E_int, E_half, pos, vel,
                                              q_dens_adv, Ie, W_elec, idx, DT)

        if generate_data == 1:
            if qq % data_iter == 0:
                save.save_data(DT, data_iter, qq, pos, vel, Ji, E_int, B, Ve,
                               Te, q_dens)

        if (qq + 1) % 25 == 0:
            print 'Timestep {} of {} complete'.format(qq + 1, max_inc)
Esempio n. 6
0
                             qq, DT, max_inc, part_save_iter, field_save_iter, idx, B_damping_array)

            # Move particles, collect moments, delete or inject new particles
            particles.advance_particles_and_moments(pos, vel, Ie, W_elec, Ib, W_mag, idx, Ep, Bp, v_prime, S, T,temp_N,\
                                                    B, E_int, DT, q_dens_adv, Ji, ni, nu, flux_rem)

            # Average N, N + 1 densities (q_dens at N + 1/2)
            q_dens *= 0.5
            q_dens += 0.5 * q_dens_adv

            if disable_waves == False:
                # Push B from N to N + 1/2
                fields.push_B(B,
                              E_int,
                              temp3Db,
                              DT,
                              qq,
                              B_damping_array,
                              half_flag=1)

                # Calculate E at N + 1/2
                fields.calculate_E(B, Ji, q_dens, E_half, Ve, Te, Te0, temp3De,
                                   temp3Db, temp1D, E_damping_array)

                ###################################
                ### PREDICTOR CORRECTOR SECTION ###
                ###################################

                # Store old values
                old_particles[0:3, :] = pos
                old_particles[3:6, :] = vel
Esempio n. 7
0
def main_loop(pos, vel, idx, Ie, W_elec, Ib, W_mag, Ep, Bp, v_prime, S, T,temp_N,                      \
              B, E_int, E_half, q_dens, q_dens_adv, Ji, ni, nu,          \
              Ve, Te, Te0, temp3De, temp3Db, temp1D, old_particles, old_fields,\
              B_damping_array, E_damping_array, qq, DT, max_inc, part_save_iter, field_save_iter):
    '''
    Main loop separated from __main__ function, since this is the actual computation bit.
    Could probably be optimized further, but I wanted to njit() it.
    The only reason everything's not njit() is because of the output functions.
    
    Future: Come up with some way to loop until next save point
    
    Thoughts: declare a variable steps_to_go. Output all time variables at return
    to resync everything, and calculate steps to next stop.
    If no saves, steps_to_go = max_inc
    '''
    NC = const.NC
    # Check timestep
    #print('MAIN   Checking timestep')
    qq, DT, max_inc, part_save_iter, field_save_iter, B_damping_array, E_damping_array   \
    = check_timestep(pos, vel, B, E_int, q_dens, Ie, W_elec, Ib, W_mag, temp3De, Ep, Bp, \
                     v_prime, S, T,temp_N, qq, DT, max_inc, part_save_iter, \
                     field_save_iter, idx, B_damping_array, E_damping_array)

    # Move particles, collect moments
    #print('MAIN   Advancing particles/moments')
    particles.advance_particles_and_moments(pos, vel, Ie, W_elec, Ib, W_mag, idx, Ep, Bp, v_prime, S, T,temp_N,\
                                            B, E_int, DT, q_dens_adv, Ji, ni, nu)

    # Average N, N + 1 densities (q_dens at N + 1/2)
    #print('MAIN   Averaging density')
    q_dens *= 0.5
    q_dens += 0.5 * q_dens_adv

    if const.disable_waves == 0:
        # Push B from N to N + 1/2
        fields.push_B(B, E_int, temp3Db, DT, qq, B_damping_array, half_flag=1)

        # Calculate E at N + 1/2
        fields.calculate_E(B,
                           Ji,
                           q_dens,
                           E_half,
                           Ve,
                           Te,
                           Te0,
                           temp3De,
                           temp3Db,
                           temp1D,
                           E_damping_array,
                           qq,
                           DT,
                           half_flag=1)

        ###################################
        ### PREDICTOR CORRECTOR SECTION ###
        ###################################

        # Store old values
        old_particles[0:3, :] = pos
        old_particles[3:6, :] = vel
        old_particles[6, :] = Ie
        old_particles[7:10, :] = W_elec
        old_particles[10, :] = idx

        old_fields[:, 0:3] = B
        old_fields[:NC, 3:6] = Ji
        old_fields[:NC, 6:9] = Ve
        old_fields[:NC, 9] = Te

        # Predict fields
        E_int *= -1.0
        E_int += 2.0 * E_half

        fields.push_B(B, E_int, temp3Db, DT, qq, B_damping_array, half_flag=0)

        # Advance particles to obtain source terms at N + 3/2
        particles.advance_particles_and_moments(pos, vel, Ie, W_elec, Ib, W_mag, idx, Ep, Bp, v_prime, S, T,temp_N,\
                                                B, E_int, DT, q_dens, Ji, ni, nu, pc=1)

        # Average N + 1, N + 2 densities (q_dens at N + 3/2)
        q_dens *= 0.5
        q_dens += 0.5 * q_dens_adv

        # Compute predicted fields at N + 3/2
        fields.push_B(B,
                      E_int,
                      temp3Db,
                      DT,
                      qq + 1,
                      B_damping_array,
                      half_flag=1)
        fields.calculate_E(B,
                           Ji,
                           q_dens,
                           E_int,
                           Ve,
                           Te,
                           Te0,
                           temp3De,
                           temp3Db,
                           temp1D,
                           E_damping_array,
                           qq + 1,
                           DT,
                           half_flag=1)

        # Determine corrected fields at N + 1
        E_int *= 0.5
        E_int += 0.5 * E_half

        # Restore old values: [:] allows reference to same memory (instead of creating new, local instance)
        pos[:] = old_particles[0:3, :]
        vel[:] = old_particles[3:6, :]
        Ie[:] = old_particles[6, :]
        W_elec[:] = old_particles[7:10, :]
        idx[:] = old_particles[10, :]

        B[:] = old_fields[:, 0:3]
        Ji[:] = old_fields[:NC, 3:6]
        Ve[:] = old_fields[:NC, 6:9]
        Te[:] = old_fields[:NC, 9]

        fields.push_B(B, E_int, temp3Db, DT, qq, B_damping_array,
                      half_flag=0)  # Advance the original B

        q_dens[:] = q_dens_adv

    return qq, DT, max_inc, part_save_iter, field_save_iter