Distgen exampleĀ¶
Similar to the simple example, but generating particles with Distgen
InĀ [1]:
Copied!
from distgen import Generator
from distgen import Generator
InĀ [2]:
Copied!
# Nicer plotting
import matplotlib
import matplotlib.pyplot as plt
%config InlineBackend.figure_format = 'retina'
matplotlib.rcParams['figure.figsize'] = (8,4)
# Nicer plotting
import matplotlib
import matplotlib.pyplot as plt
%config InlineBackend.figure_format = 'retina'
matplotlib.rcParams['figure.figsize'] = (8,4)
InĀ [3]:
Copied!
YAML="""
n_particle: 10000
random_type: hammersley
species: electron
start:
type: cathode
MTE:
value: 414
units: meV
total_charge:
value: 250
units: pC
r_dist:
n_sigma_cutoff: 1.5
sigma_xy:
value: 0.4
units: mm
type: radial_gaussian
t_dist:
type: superposition
dists:
d1:
type: gaussian
avg_t:
units: ps
value: -1
sigma_t:
units: ps
value: 1
d2:
type: gaussian
avg_t:
units: ps
value: 1
sigma_t:
units: ps
value: 1
"""
G = Generator(YAML)
YAML="""
n_particle: 10000
random_type: hammersley
species: electron
start:
type: cathode
MTE:
value: 414
units: meV
total_charge:
value: 250
units: pC
r_dist:
n_sigma_cutoff: 1.5
sigma_xy:
value: 0.4
units: mm
type: radial_gaussian
t_dist:
type: superposition
dists:
d1:
type: gaussian
avg_t:
units: ps
value: -1
sigma_t:
units: ps
value: 1
d2:
type: gaussian
avg_t:
units: ps
value: 1
sigma_t:
units: ps
value: 1
"""
G = Generator(YAML)
InĀ [4]:
Copied!
# Tune the two dist separation
G['t_dist:dists:d1:avg_t:value'] = -1
G['t_dist:dists:d2:avg_t:value'] = 1
G.run()
GP = G.particles
GP.plot('t')
GP.plot('pz')
# Tune the two dist separation
G['t_dist:dists:d1:avg_t:value'] = -1
G['t_dist:dists:d2:avg_t:value'] = 1
G.run()
GP = G.particles
GP.plot('t')
GP.plot('pz')
InĀ [5]:
Copied!
from impact import Impact
import matplotlib.pyplot as plt
import os
from impact import Impact
import matplotlib.pyplot as plt
import os
InĀ [6]:
Copied!
ifile = 'templates/lcls_injector/ImpactT.in'
os.path.exists(ifile)
ifile = 'templates/lcls_injector/ImpactT.in'
os.path.exists(ifile)
Out[6]:
True
InĀ [7]:
Copied!
# Make Impact object
I = Impact(ifile, initial_particles = G.particles, verbose=True)
# Make Impact object
I = Impact(ifile, initial_particles = G.particles, verbose=True)
Configured to run in: /var/folders/2f/l5_mybzs30j4qqvyj98w1_nw0000gn/T/tmpcf2u4at8
InĀ [8]:
Copied!
# This will use the initial particles
I.write_initial_particles(update_header=True)
# This will use the initial particles
I.write_initial_particles(update_header=True)
writing 10000 particles to /var/folders/2f/l5_mybzs30j4qqvyj98w1_nw0000gn/T/tmpcf2u4at8/partcl.data Cathode start with cathode_kinetic_energy_ref = 1.0 eV Cathode start: Replaced Np with 10000 according to initial particles Cathode start: Replaced Bkenergy with 1.0 according to initial particles Cathode start: Replaced Temission with 9.145639807439135e-12 according to initial particles Cathode start: Replaced Tini with -4.714953504413114e-12 according to initial particles Setting total charge to 2.4999999999999996e-10 C
InĀ [9]:
Copied!
# Change some things
I.header['Nx'] = 16
I.header['Ny'] = 16
I.header['Nz'] = 16
I.header['Dt'] = 5e-13
# Turn Space Charge off
I.header['Bcurr'] = 0
# Other switches
I.timeout = 1000
# Switches for MPI
I.numprocs = 4
# Change some things
I.header['Nx'] = 16
I.header['Ny'] = 16
I.header['Nz'] = 16
I.header['Dt'] = 5e-13
# Turn Space Charge off
I.header['Bcurr'] = 0
# Other switches
I.timeout = 1000
# Switches for MPI
I.numprocs = 4
Setting Npcol, Nprow = 2, 2 Enabling MPI
InĀ [10]:
Copied!
# Change stop location
I.stop = 1.5
#I.ele['stop_1']['s'] = I.ele['OTR2']['s']+.001
# Change stop location
I.stop = 1.5
#I.ele['stop_1']['s'] = I.ele['OTR2']['s']+.001
Removed element: stop_1 Set stop to s = 1.5
InĀ [11]:
Copied!
I.run()
I.run()
Running Impact-T in /var/folders/2f/l5_mybzs30j4qqvyj98w1_nw0000gn/T/tmpcf2u4at8 mpirun -n 4 /Users/chrisonian/Code/mambaforge/envs/lume-impact-dev/bin/ImpactTexe-mpi writing 10000 particles to /var/folders/2f/l5_mybzs30j4qqvyj98w1_nw0000gn/T/tmpcf2u4at8/partcl.data Cathode start with cathode_kinetic_energy_ref = 1.0 eV Cathode start: Replaced Np with 10000 according to initial particles Cathode start: Replaced Bkenergy with 1.0 according to initial particles Cathode start: Replaced Temission with 9.145639807439135e-12 according to initial particles Cathode start: Replaced Tini with -4.714953504413114e-12 according to initial particles
Loaded fort 18 : Time and energy Loaded fort 24 : RMS X information Loaded fort 25 : RMS Y information Loaded fort 26 : RMS Z information Loaded fort 27 : Max amplitude information Loaded fort 28 : Load balance and loss diagnostics Loaded fort 29 : Cube root of third moments of the beam distribution Loaded fort 30 : Fourth root of the fourth moments of the beam distribution Loaded fort 32 : Covariance matrix of the beam distribution Loaded fort 60 : Slice information of the initial distribution Loaded fort 70 : Slice information of the final distribution Loading particles Loaded fort 40 : initial particle distribution at t = 0 Loaded fort 50 : final particle distribution projected to the centroid location of the bunch Loaded write beam particles YAG02 fort.102 Converting z to t according to cathode_kinetic_energy_ref = 1.0 eV Converted initial_particles to ParticleGroup Converted final_particles to ParticleGroup Converted YAG02 to ParticleGroup
InĀ [12]:
Copied!
I.input.keys()
I.input.keys()
Out[12]:
dict_keys(['original_input', 'input_particle_file', 'header', 'lattice', 'fieldmaps'])
InĀ [13]:
Copied!
I.output.keys()
I.output.keys()
Out[13]:
dict_keys(['run_info', 'stats', 'slice_info', 'particles'])
InĀ [14]:
Copied!
I.output['stats'].keys()
I.output['stats'].keys()
Out[14]:
dict_keys(['t', 'mean_z', 'mean_gamma', 'mean_beta', 'max_r', 'sigma_gamma', 'mean_x', 'sigma_x', 'norm_emit_x', 'mean_y', 'sigma_y', 'norm_emit_y', 'sigma_z', 'norm_emit_z', 'max_amplitude_x', 'max_amplitude_y', 'max_amplitude_z', 'loadbalance_min_n_particle', 'loadbalance_max_n_particle', 'n_particle', 'moment3_x', 'moment3_y', 'moment3_z', 'moment4_x', 'moment4_y', 'moment4_z', 'cov_x__x', 'cov_x__y', 'cov_x__z', 'cov_y__y', 'cov_y__z', 'cov_z__z', 'mean_kinetic_energy', 'cov_x__px', 'cov_y__py', 'cov_z__pz', 'cov_x__py', 'cov_x__pz', 'cov_px__px', 'cov_y__px', 'cov_px__py', 'cov_z__px', 'cov_px__pz', 'cov_y__pz', 'cov_py__py', 'cov_z__py', 'cov_py__pz', 'cov_pz__pz'])
InĀ [15]:
Copied!
I.output['slice_info'].keys()
I.output['slice_info'].keys()
Out[15]:
dict_keys(['initial_particle_slices', 'final_particle_slices'])
ParticlesĀ¶
InĀ [16]:
Copied!
# Particles are automatically parsed in to openpmd-beamphysics ParticleGroup objects
I.output['particles']
# Particles are automatically parsed in to openpmd-beamphysics ParticleGroup objects
I.output['particles']
Out[16]:
{'initial_particles': <ParticleGroup with 10000 particles at 0x144aeb5c0>, 'final_particles': <ParticleGroup with 10000 particles at 0x145cddbe0>, 'YAG02': <ParticleGroup with 10000 particles at 0x145e84da0>}
InĀ [17]:
Copied!
PI = I.output['particles']['initial_particles']
PF = I.output['particles']['final_particles']
PI = I.output['particles']['initial_particles']
PF = I.output['particles']['final_particles']
InĀ [18]:
Copied!
# Original particles
GP.plot('t', 'pz')
# Original particles
GP.plot('t', 'pz')
InĀ [19]:
Copied!
# Readback of initial particles from Impact-T.
PI.plot('t', 'pz')
# Readback of initial particles from Impact-T.
PI.plot('t', 'pz')
InĀ [20]:
Copied!
# The initial time was shifted to account for this
I.header['Tini']
# The initial time was shifted to account for this
I.header['Tini']
Out[20]:
-4.714953504413114e-12
InĀ [21]:
Copied!
# Get the final particles, calculate some statistic
P = I.output['particles']['final_particles']
P['mean_energy']
# Get the final particles, calculate some statistic
P = I.output['particles']['final_particles']
P['mean_energy']
Out[21]:
5996724.8303187685
InĀ [22]:
Copied!
# Show the units
P.units('mean_energy')
# Show the units
P.units('mean_energy')
Out[22]:
pmd_unit('eV', 1.602176634e-19, (2, 1, -2, 0, 0, 0, 0))
InĀ [23]:
Copied!
P.plot('z', 'pz')
P.plot('z', 'pz')
StatsĀ¶
InĀ [24]:
Copied!
# Impact's own calculated statistics can be retieved
len(I.stat('norm_emit_x')), I.stat('norm_emit_x')[-1]
# Impact's own calculated statistics can be retieved
len(I.stat('norm_emit_x')), I.stat('norm_emit_x')[-1]
Out[24]:
(631, 2.5687794e-07)
InĀ [25]:
Copied!
# Compare these.
key1 = 'mean_z'
key2 = 'sigma_x'
units1 = str(I.units(key1))
units2 = str(I.units(key2))
plt.xlabel(key1+f' ({units1})')
plt.ylabel(key2+f' ({units2})')
plt.plot(I.stat(key1), I.stat(key2))
plt.scatter(
[I.particles[name][key1] for name in I.particles],
[I.particles[name][key2] for name in I.particles], color='red')
# Compare these.
key1 = 'mean_z'
key2 = 'sigma_x'
units1 = str(I.units(key1))
units2 = str(I.units(key2))
plt.xlabel(key1+f' ({units1})')
plt.ylabel(key2+f' ({units2})')
plt.plot(I.stat(key1), I.stat(key2))
plt.scatter(
[I.particles[name][key1] for name in I.particles],
[I.particles[name][key2] for name in I.particles], color='red')
Out[25]:
<matplotlib.collections.PathCollection at 0x145bfa960>
Archive, and restart from the middleĀ¶
InĀ [26]:
Copied!
afile = I.archive()
I2 = Impact(verbose=False)
I2.load_archive(afile)
# Patch in these particles
I2.initial_particles = I2.particles['YAG02']
# Turn off cathode start
I2.header['Flagimg'] = 0
I2.configure()
afile = I.archive()
I2 = Impact(verbose=False)
I2.load_archive(afile)
# Patch in these particles
I2.initial_particles = I2.particles['YAG02']
# Turn off cathode start
I2.header['Flagimg'] = 0
I2.configure()
Archiving to file impact_c092aaf3e3063efb1a2ee437177657cc.h5
InĀ [27]:
Copied!
# Run again
I2.use_mpi=True
I2.run()
# Run again
I2.use_mpi=True
I2.run()
InĀ [28]:
Copied!
# Compare these.
key1 = 'mean_z'
key2 = 'sigma_x'
units1 = str(I.units(key1))
units2 = str(I.units(key2))
plt.xlabel(key1+f' ({units1})')
plt.ylabel(key2+f' ({units2})')
plt.plot(I.stat(key1), I.stat(key2), color='black', label='original run')
plt.plot(I2.stat(key1), I2.stat(key2), color='red', label='restart run')
plt.scatter(
[I.particles[name][key1] for name in I.particles],
[I.particles[name][key2] for name in I.particles], color='black')
plt.scatter(
[I2.particles[name][key1] for name in I2.particles],
[I2.particles[name][key2] for name in I2.particles], color='red', marker='x')
plt.legend()
# Compare these.
key1 = 'mean_z'
key2 = 'sigma_x'
units1 = str(I.units(key1))
units2 = str(I.units(key2))
plt.xlabel(key1+f' ({units1})')
plt.ylabel(key2+f' ({units2})')
plt.plot(I.stat(key1), I.stat(key2), color='black', label='original run')
plt.plot(I2.stat(key1), I2.stat(key2), color='red', label='restart run')
plt.scatter(
[I.particles[name][key1] for name in I.particles],
[I.particles[name][key2] for name in I.particles], color='black')
plt.scatter(
[I2.particles[name][key1] for name in I2.particles],
[I2.particles[name][key2] for name in I2.particles], color='red', marker='x')
plt.legend()
Out[28]:
<matplotlib.legend.Legend at 0x145b10bf0>
InĀ [29]:
Copied!
# Cleanup
os.remove(afile)
# Cleanup
os.remove(afile)