Пример #1
0
def main():
    #call the simululator to start the game.
    simulation.simulator(start_screen, WHITE)
    print(game_screen)
    #when the start screen exits, start the game screen by calling the simulator again
    simulation.simulator(game_screen, GREEN)
    #If you wanted to add a 3rd screen you would call the simulator again here.
    print('Your score is', score)
def load_last_model_checkpoint(logs_path,run):
    """
    Loads last model checkpoint of the training
    returns a simulation object
    """
    model_folder = os.path.join(logs_path, 'run_'+str(run), "model_checkpoints/")
    model_path = max(glob.iglob(model_folder+"/*.h5"), key = os.path.getmtime)
    sumo_RL = simulation.simulator()
    sumo_RL.load(model_path)

    return(sumo_RL)
def worker_task(position, args):
    """Tells the worker what to do with grid chunk"""
    # print('Run', position + 1, '-- parameters', args)

    sumo_RL = simulation.simulator(connection_label = position +1, **args)

    # print("training agent", position + 1)
    train_data = sumo_RL.train()
    # print("evaluating agent", position + 1)
    evaluation_results = sumo_RL.evaluate(runs = 5)

    return ({"run" : position + 1,
             "args" : args,
             "eval_delay" : evaluation_results,
             "eval_mean_delay" : evaluation_results["average_delay"],
             "train_data": train_data})
Пример #4
0
 def start_simulation(self):
     self.res_print.delete(0.0, END)
     #print(self.net)
     self.res_print.insert(END, '#--------------------Start Parse the Netlist---------------------#\n')
     sim_parse=MyParser(self.net)
     a,b=sim_parse.parse()
     #print (a,'hi')
     if (a==-1):
         parser_info=sim_parse.showParseResult()
     else:
         parser_info='have error at line '+str(b)
     for lines in parser_info:
         self.res_print.insert(END,lines)
     self.res_print.insert(END, ' ')
     self.res_print.insert(END,'#----------------------Start the Simulation----------------------#\n')
     sim_simulator=simulator(self.net)
     sim_simulator.solve_net()
     self.res_print.insert(END,'#----------------------Successful Simulation----------------------#\n')
Пример #5
0
'''
python setup.py build_ext --inplace
'''

from simulation import simulator
import numpy as np
from simulation_parameters import simulation_parameters
from equilbrium_positions import equilibrium_positions as equil
from matplotlib import pyplot

p = simulation_parameters()
simulation = simulator(p)

starting_positions = np.zeros((p.number_ions, 3))
starting_velocities = np.zeros((p.number_ions, 3))
starting_positions[:, 0] = p.number_ions * [0]
starting_positions[:, 1] = p.number_ions * [0]
starting_positions[:, 2] = equil.get_positions(p.number_ions, p.f_z, p)
center_ion = p.number_ions / 2 +1
heated_ion = 0
starting_positions[heated_ion, 0] +=10e-9
# starting_positions[heated_ion+1, 0] +=10e-9

positions,excitations = simulation.simulation(starting_positions, starting_velocities, random_seeding = 0)
print positions[0,:,0]
velocities = np.diff(positions, axis = 1) / p.timestep
print 'vel'
time_axis = np.arange(positions.shape[1]) * p.timestep * 10**6
print 't'
energy_left = velocities[0, :, 0]**2 * p.mass * .5 / p.hbar / (2 * np.pi * p.f_x)
print 'eleft'
Пример #6
0
'''
python setup.py build_ext --inplace
'''

from simulation import simulator
import numpy as np
from simulation_parameters import simulation_parameters
from equilbrium_positions import equilibrium_positions as equil
from matplotlib import pyplot
import matplotlib
matplotlib.rc('xtick', labelsize=20) 
matplotlib.rc('ytick', labelsize=20) 

p = simulation_parameters()
simulation = simulator(p)

starting_positions = np.zeros((p.number_ions, 3))
starting_velocities = np.zeros((p.number_ions, 3))
starting_positions[:, 0] = p.number_ions * [0]
starting_positions[:, 1] = p.number_ions * [0]
starting_positions[:, 2] = equil.get_positions(p.number_ions, p.f_z, p)
center_ion = p.number_ions / 2 +1
heated_ion = 0
starting_positions[heated_ion, 0] +=10e-9

positions,excitations = simulation.simulation(starting_positions, starting_velocities, random_seeding = 0)
print positions[0,:,0]
velocities = np.diff(positions, axis = 1) / p.timestep
print 'vel'
time_axis = np.arange(positions.shape[1]) * p.timestep * 10**6
print 't'
Пример #7
0
    def run(self):
        # sets the initial values of things
        self.simCancel = False
        tempvalues = []

        # creates a new window for the progress bar and other buttons
        self.progWin = tk.Toplevel(self.root)
        self.progWin.title("SimulationRun")
        self.progWin.protocol('WM_DELETE_WINDOW', self.cancel)

        # creates a style for the progress bar
        style = tk.ttk.Style()
        style.theme_use('default')
        style.configure("black.Horizontal.TProgressbar", background='black')

        # makes lable for the progress meter
        progLabel = tk.Label(self.progWin, text='Simulation Progress:')
        progLabel.grid(column=0, row=0, sticky='w')

        # makes a lable for current progress percent
        curProgLabel = tk.Label(self.progWin, text='0.00%')
        curProgLabel.grid(column=1, row=0, sticky='w')

        timeLabel = tk.Label(self.progWin, text='Estimated Time Remaining:')
        timeLabel.grid(column=0, row=2, sticky='w')

        timeRemain = tk.Label(self.progWin, text='HRS:MIN:SEC')
        timeRemain.grid(column=1, row=2, sticky='w')

        # makes a progress bar set to just under the size of the window
        bar = Progressbar(self.progWin,
                          length=self.root.winfo_screenwidth() / 5,
                          style='black.Horizontal.TProgressbar')
        bar.grid(column=0, columnspan=4, row=1, padx=10, pady=5)

        # Creates buttons for cancal and analyse
        bCancel = tk.Button(self.progWin, text='Cancel', command=self.cancel)
        bCancel.grid(column=1, row=3, pady=5)
        bAnalyse = tk.Button(self.progWin,
                             text='Analyze',
                             command=lambda: self.analyse(tempvalues))
        bAnalyse['state'] = 'disable'
        bAnalyse.grid(column=0, row=3, pady=5)

        # updates window
        self.progWin.update()

        #gets sim number
        self.simNumber = self.numSim.get()

        # gets sim length
        simLen = self.simLength.get()

        # gets car ratios
        ratioNC = int(self.sbNorm.get())
        ratioBB = int(self.sbBBCar.get())
        ratioAC = int(self.sbAuton.get())

        # validity checks for different data fields
        if (not self.boolNormCar.get() or ratioNC < 0):
            ratioNC = 0

        if (not self.boolBBCar.get() or ratioBB < 0):
            ratioBB = 0

        if (not self.boolAutoCar.get() or ratioAC < 0):
            ratioAC = 0

        if (self.boolGraphics.get()):
            self.simNumber = 1

        # counter for tests
        simiters = 0.0
        # runs the tests
        for i in range(self.simNumber):
            # checks if the sim should still run
            if (self.simCancel == True):
                self.progWin.quit()
                messagebox.showwarning('Sim Canceled',
                                       'Simulation has been interrupted.')
                return

            self.sim = s.simulator(self.root, self.lanes.get(),
                                   self.boolDebug.get(), self.speedLim.get(),
                                   self.boolGraphics.get(), simLen, 8,
                                   self.carsPerMin.get(), ratioNC, ratioBB,
                                   ratioAC, False)
            t0 = time.time()
            self.sim.start()
            t1 = time.time()
            deltaT = t1 - t0
            estTime = round((self.simNumber - simiters) * deltaT, 2)

            sec = round(estTime % 60)
            min = int((estTime - sec) / 60) % 60
            hr = int(estTime / 60 / 60)
            timeStr = ''

            if (hr > 0):
                timeStr += str(hr) + " Hours "

            if (min > 0):
                timeStr += str(min) + " Minutes "

            timeStr += str(sec) + " Seconds"

            timeRemain['text'] = str(timeStr)

            self.sim.collect_results()
            tempvalues.append(self.sim.RESULTS)
            simiters += 1.0
            bar['value'] = round(simiters / float(self.simNumber) * 100.0, 2)

            if (round(simiters / float(self.simNumber) * 100.0, 2) == 100):
                timeRemain['text'] = 'Done'
            curProgLabel['text'] = str(bar['value']) + "%"
            self.progWin.update()

        self.results = tempvalues
        bCancel['state'] = 'disable'
        bAnalyse['state'] = 'normal'
Пример #8
0

total_to_average = 500
for i in range(total_to_average):
    print 'ITERATION', i
    #starting at equilibrium positions
    p = simulation_parameters()
    starting_positions = np.zeros((p.number_ions, 3))
    starting_positions[:, 0] = p.number_ions * [0]
    starting_positions[:, 1] = p.number_ions * [0]
    starting_positions[:, 2] = equil.get_positions(p.number_ions, p.f_z, p)
    starting_velocities = np.zeros((p.number_ions, 3))
    #first do doppler cooling to randomize starting positions
    p.laser_detuning = -.5 * p.transition_gamma
    p.simulation_duration = 200e-6
    doppler_cooling_simulator = simulator(p)
    doppler_positions, doppler_excitations = doppler_cooling_simulator.simulation(starting_positions, starting_velocities, random_seeding = i)
    #now do laser heating with pulsing heating
    p.laser_detuning = 0 * p.transition_gamma
    p.saturation = 2.0
    p.simulation_duration = 200e-6
    p.laser_direction = np.array([1.0, 0.0, 0.0])
    p.pulsed_laser = True
    starting_positions = doppler_positions[:,-1,:]
    starting_velocities =  doppler_positions[:,-1,:] -  doppler_positions[:,-2,:]
    heating_simulator = simulator(p)
    heating_positions, heating_excitations = heating_simulator.simulation(starting_positions, starting_velocities, random_seeding = i)
    #now we do laser heating with blue heating
    p.laser_detuning = 0.5 * p.transition_gamma
    p.saturation = 1.0
    p.simulation_duration = 200e-6
Пример #9
0
doppler_average = np.zeros(599)
heating_average = np.zeros(599)
total_to_average = 10
for i in range(total_to_average):
    print 'ITERATION', i
    #starting at equilibrium positions
    p = simulation_parameters()
    starting_positions = np.zeros((p.number_ions, 3))
    starting_positions[:, 0] = p.number_ions * [0]
    starting_positions[:, 1] = p.number_ions * [0]
    starting_positions[:, 2] = equil.get_positions(p.number_ions, p.f_z, p)
    starting_velocities = np.zeros((p.number_ions, 3))
    #first do doppler cooling to randomize starting positions
    p.laser_detuning = -.5 * p.transition_gamma
    p.simulation_duration = 200e-6
    doppler_cooling_simulator = simulator(p)
    doppler_positions, doppler_excitations = doppler_cooling_simulator.simulation(starting_positions, starting_velocities, random_seeding = i)
    #now do laser heating
    p.laser_detuning = +0.5 * p.transition_gamma
    p.saturation = 1.0
    p.simulation_duration = 200e-6
    p.laser_direction = np.array([1.0, 0.0, 0.0])
    starting_positions = doppler_positions[:,-1,:]
    starting_velocities =  doppler_positions[:,-1,:] -  doppler_positions[:,-2,:]
    heating_simulator = simulator(p)
    heating_positions, heating_excitations = heating_simulator.simulation(starting_positions, starting_velocities, random_seeding = i)
    
    
    doppler_velocities = np.diff(doppler_positions, axis = 1) / p.timestep
    heat_velocities = np.diff(heating_positions, axis = 1) / p.timestep
    
Пример #10
0
def dynamics_simulation(configuration):
    '''
    The function requires a parameter configuration, which is a list or numpy array

        configuration = [trap_configuration, operation1, operation2, operation3...]

    trap_configuration consists of frequencies setting, ion settings

        trap_configuration = [number_ions, frequency_drive, frequency_x, frequency_y, frequency_z, damping, mass, transition_gamma, wavelength, use_harmonic_approximation, starting_positions, starting_positions]

        e.g. trap_configuration = [1, 30.0*10**6, 4.0 * 10**6, 3.0 * 10**6, 0.2 * 10**6, 0, 40, 1 / (7.1 * 10**-9), 397*10**-9, False, [[0,0, z1],[0,0,z2]], [[0,0,0],[0,0,0]]]

        z1, z2 are equilibrium positions obtained by equilbrium_positions.py, and you can assign a configuration without starting_positions and starting_velocity, which can be generated by the program, see below as an example.

        trap_configuration = [2, 30.0*10**6, 4.0 * 10**6, 3.0 * 10**6, 0.2 * 10**6, 0, 40, 1 / (7.1 * 10**-9), False]

        In details, the example is actually the default settings for the simulation, testing 40Ca.

        You should note that number_ions should be an integer, frequencies should all be double in Hz, damping is a dimensionless quantity, transition_gamma is 1/tau, use_harmonic_approximation should be assigned True if you want to deal with the simulation in pseudo potential approximation

        If you just want to run this simulation with those default settings, please assign trap_configuration = 0

        You can also change the number of default ion with a non-zero integer to tran_configuration

    operation indicates a duration with some laser interactions or not

        operation = [simulation_duration, cooling_laser, heating_laser,iteration_times, timesteps]

        laser = [saturation, laser_detuning, laser_direction, laser_center, laser_waist, laser_pulsed]

        In operation, four parameters are required
            simulation_duration = (double) time, unit in seconds
            iteration_times = (int) n, it is used to run the same simulation multiple times and average the results

        cooling_laser and heating_laser share the same data structure as laser above.

            saturation = 2Omega^2/Gamma^2

            laser_detuning = (double) detuning, is a factor compared to Gamma, for example if you want to set laser_detuning = 0.5 * Gamma, you actually just need to set laser_detuning = -0.5, but do notice that laser_detuning can be positive for heating, and you must not assign wrong values to lasers, cooling requires detuning to be negative, but positive for heating

            laser_direction = [x,y,z], not necessary to make it normalized

            laser_center = [x,y,z], a point in space

            laser_waist = (double) waist, in meters

            laser_pulsed = True/False, indicating pulsed laser or not
        **************************************************************************
        P.S. if any kind of laser is not applied, please assign laser to be 0, heating_laser = 0 for example, operation = [simulation_duration, iteration_times, cooling_laser, 0]
        !!! Numpy array is prefered for array
        **************************************************************************

        timesteps is not necessary, the default would be 100, which means timestep in the parameters 1/f_drive/100, but you can try it for some different numbers,
        for example, timesteps = 5, cause simulation timestep = 1/f_drive/5

    If you want to applay different laser or anything, please add more operations, but the least number of operations is 1, even you don't apply any laser, just testing its dynamics caused by the quadropole potential and Coulomb interation.

    Returns a list consisting [positions, excitations, time_steps]

        positions = np.array([positions_1,positions_2......])
        excitations = np.array([excitations_1,excitations_2......])
        time_steps = np.array([timesteps_1,timesteps_2......])
    '''
    parameters = simulation_parameters()
    if configuration[0] == 0:
        starting_positions = np.zeros((parameters.number_ions, 3))
        starting_positions[:, 0] = parameters.number_ions * [0]  # x
        starting_positions[:, 1] = parameters.number_ions * [0]  # y
        starting_positions[:,
                           2] = equil.get_positions(parameters.number_ions,
                                                    parameters.f_z, parameters)
        starting_positions += (np.random.random(
            (parameters.number_ions, 3)) - .5) * 1e-5
        starting_velocities = np.zeros((parameters.number_ions, 3))
    elif type(configuration[0]) == type(1) and configuration[0] > 0:
        parameters.number_ions = configuration[0]
        starting_positions = np.zeros((parameters.number_ions, 3))
        starting_positions[:, 0] = parameters.number_ions * [0]  # x
        starting_positions[:, 1] = parameters.number_ions * [0]  # y
        starting_positions[:,
                           2] = equil.get_positions(parameters.number_ions,
                                                    parameters.f_z, parameters)
        starting_positions += (np.random.random(
            (parameters.number_ions, 3)) - .5) * 1e-5
        starting_velocities = np.zeros((parameters.number_ions, 3))
    elif len(configuration[0]) == 10:
        parameters.number_ions = configuration[0][0]
        parameters.f_drive = configuration[0][1]
        parameters.f_x = configuration[0][2]
        parameters.f_y = configuration[0][3]
        parameters.f_z = configuration[0][4]
        parameters.damping = configuration[0][5]
        parameters.mass = configuration[0][6] * parameters.atomic_unit
        parameters.transition_gamma = configuration[0][7]
        parameters.wavelength = configuration[0][8]
        parameters.transition_k_mag = 2 * np.pi / parameters.wavelength
        parameters.use_harmonic_approximation = configuration[0][9]
        starting_positions = np.zeros((parameters.number_ions, 3))
        starting_positions[:, 0] = parameters.number_ions * [0]  # x
        starting_positions[:, 1] = parameters.number_ions * [0]  # y
        starting_positions[:,
                           2] = equil.get_positions(parameters.number_ions,
                                                    parameters.f_z, parameters)
        starting_positions += (np.random.random(
            (parameters.number_ions, 3)) - .5) * 1e-5
        starting_velocities = np.zeros((parameters.number_ions, 3))
    elif len(configuration[0]) == 12:
        parameters.number_ions = configuration[0][0]
        parameters.f_drive = configuration[0][1]
        parameters.f_x = configuration[0][2]
        parameters.f_y = configuration[0][3]
        parameters.f_z = configuration[0][4]
        parameters.damping = configuration[0][5]
        parameters.mass = configuration[0][6] * parameters.atomic_unit
        parameters.transition_gamma = configuration[0][7]
        parameters.wavelength = configuration[0][8]
        parameters.transition_k_mag = 2 * np.pi / parameters.wavelength
        parameters.use_harmonic_approximation = configuration[0][9]
        starting_positions = np.array(configuration[0][10])
        starting_velocities = np.array(configuration[0][11])
    else:
        raise Exception("Wrong input for trap settings")
    starting_time = 0
    starting_excitations = np.zeros(parameters.number_ions, dtype=np.uint8)
    excitations = []
    positions = []
    time = []
    order = 0
    for operation in configuration[1:]:
        order += 1
        print "!!!Operation", order, "starts!"
        parameters.simulation_duration = operation[0]
        iteration_times = 1
        if len(operation) == 5:
            iteration_times = operation[3]
            parameters.time_steps = (1 / parameters.f_drive) / operation[4]
        if len(operation) == 4:
            iteration_times = operation[3]
        chunksize = int(parameters.total_steps * 3e-3)
        # initialize cooling laser
        if not operation[1] == 0:
            parameters.cooling_on = True
            parameters.cooling_saturation = float(operation[1][0])
            parameters.cooling_laser_detuning = operation[1][
                1] * parameters.transition_gamma
            parameters.cooling_laser_direction = np.array(
                operation[1][2]).astype(float)
            parameters.cooling_laser_direction = parameters.cooling_laser_direction / \
                np.sqrt(np.sum(parameters.cooling_laser_direction**2)
                        )  # normalized
            parameters.cooling_laser_center = np.array(
                operation[1][3]).astype(float)
            parameters.cooling_laser_waist = float(operation[1][4])
            parameters.cooling_laser_pulsed = operation[1][5]
        # initialize heating laser
        if not operation[2] == 0:
            parameters.heating_on = True
            parameters.heating_saturation = float(operation[2][0])
            parameters.heating_laser_detuning = operation[2][
                1] * parameters.transition_gamma
            parameters.heating_laser_direction = np.array(
                operation[2][2]).astype(float)
            parameters.heating_laser_direction = parameters.heating_laser_direction / \
                np.sqrt(np.sum(parameters.heating_laser_direction**2)
                        )  # normalized
            parameters.heating_laser_center = np.array(
                operation[2][3]).astype(float)
            parameters.heating_laser_waist = float(operation[2][4])
            parameters.heating_laser_pulsed = operation[2][5]
        positions_i = np.zeros(
            (parameters.number_ions, parameters.total_steps, 3))
        excitations_i = np.zeros(
            (parameters.total_steps, parameters.number_ions), dtype=np.uint8)
        for i in range(iteration_times):
            print 'ITERATION', i + 1
            simulator_i = simulator(parameters)
            positions_operation_i, excitations_operation_i = simulator_i.simulation(
                starting_positions,
                starting_velocities,
                starting_excitations,
                random_seeding=i)
            positions_i += positions_operation_i
            excitations_i += excitations_operation_i
        print "!!!Operation", order, "ends"
        positions_i /= iteration_times
        excitations_i = np.round(excitations_i / iteration_times)
        timesteps = np.arange(parameters.total_steps) * \
            parameters.timestep * 10**6 + starting_time
        # update the starting time, positions and excitations for next
        # operation
        starting_time = timesteps[-1]
        starting_velocities = (positions_i[:, -1, :] -
                               positions_i[:, -2, :]) / parameters.timestep
        starting_positions = positions_i[:, -1, :]
        starting_excitations = excitations_i[-1, :]
        positions.append(positions_i)
        excitations.append(excitations_i)
        time.append(timesteps)
        positions_chunk = positions_i[:, :(parameters.total_steps //
                                           chunksize) * chunksize, :].reshape(
                                               (parameters.number_ions, -1,
                                                chunksize, 3))
        timesteps_chunk = timesteps[:(parameters.total_steps // chunksize) *
                                    chunksize].reshape((-1, chunksize))
        positions_center = positions_chunk.mean(axis=2) * 10**6
        timesteps_center = timesteps_chunk.mean(axis=1)
        # positions_center = positions_i * 10**6
        # timesteps_center = timesteps
        for num in range(parameters.number_ions):
            pyplot.figure((order - 1) * parameters.number_ions + num + 1)
            pyplot.title("Trajectory of ion {} in operation {}".format(
                num + 1, order),
                         fontsize=12)
            pyplot.xlabel(r'Time($\mu s$)', fontsize=10)
            pyplot.ylabel(r'Positions($\mu m$)', fontsize=10)
            pyplot.tick_params(axis='both', labelsize=6)
            pyplot.plot(timesteps_center,
                        positions_center[num, :, 0],
                        'blue',
                        label='x')
            pyplot.plot(timesteps_center,
                        positions_center[num, :, 1],
                        'red',
                        label='y')
            pyplot.plot(timesteps_center,
                        positions_center[num, :, 2],
                        'black',
                        label='z')
            pyplot.grid(True, which='both')
            pyplot.legend()
            filename = "ion " + str(num + 1) + \
                " in operation " + str(order) + ".png"
            pyplot.savefig(filename, dpi=100)
    pyplot.show()
    positions = np.array(positions)
    excitations = np.array(excitations)
    time = np.array(time)
    return [positions, excitations, time]
Пример #11
0
    path = "./experiments/sim_" + str(exp)
    filename = path + "/" + str(exp) + 'checkpoint.pickle'

    if args.checkpoint == "True" and os.path.exists(filename):
        with open(filename, 'rb') as handle:
            regret, r2, logloss, x, y, i = pickle.load(handle)

    else:
        regret, r2, logloss, x, y, i = [], [], [], x_start, y_start, 0

    if args.deep_gt == "True":
        gt_model = gtNN(0.2)
        gt_model.load_state_dict(torch.load("./data/gt_weights_2.pt"))
    else:
        gt_model = gtLR(w_gt)

    _ = simulator().run(model, gt_model, x_sim, x, y, x_test, y_test,
                        args.len_sim, args.n_ads_sel, args.freq,
                        args.n_new_ads, 10, args.exp, regret, r2, logloss, i)

    clicks, regret, r2_score = _

    path = "./experiments/sim_" + str(exp)
    try:
        os.mkdir(path)
    except Exception:
        None

    with open(path + "/" + str(exp) + '.pickle', 'wb') as handle:
        pickle.dump(_, handle, protocol=pickle.HIGHEST_PROTOCOL)
Пример #12
0
heating_average_right = np.zeros((p.total_steps - 1) // chunksize)
total_to_average = 20
for i in range(total_to_average):
    print 'ITERATION', i
    # starting at equilibrium positions
    p = simulation_parameters()
    starting_positions = np.zeros((p.number_ions, 3))
    starting_positions[:, 0] = p.number_ions * [0]  # x
    starting_positions[:, 1] = p.number_ions * [0]  # y
    starting_positions[:, 2] = equil.get_positions(
        p.number_ions, p.f_z, p)  # z
    starting_velocities = np.zeros((p.number_ions, 3))
    # first do doppler cooling to randomize starting positions
    p.laser_detuning = -.5 * p.transition_gamma
    p.simulation_duration = duration_doppler_cooling
    doppler_cooling_simulator = simulator(p)
    doppler_positions, doppler_excitations = doppler_cooling_simulator.simulation(
        starting_positions, starting_velocities, random_seeding=i)
#     print doppler_positions[0, :, 0].mean()

    # now do laser heating
    p.laser_detuning = +0.5 * p.transition_gamma
    p.pulsed_laser = False
    p.saturation = 1.0
    p.simulation_duration = duration_heating
    # only heat leftmost ion, radially
    p.laser_direction = np.array([1.0, 0.0, 0.0])
    left_ion_z = equil.get_positions(p.number_ions, p.f_z, p)[0]
    p.laser_center = np.array([0.0, 0.0, left_ion_z])
    p.laser_waist = 1e-6