Genesis4 Particles¶
This shows examples of the various ways to input particle data into Genesis4.
import logging
import os
from math import pi, sqrt
import matplotlib.pyplot as plt
import numpy as np
from scipy.constants import c
import genesis.version4 as g4
logging.basicConfig()
# logging.getLogger("genesis").setLevel("DEBUG")
%config InlineBackend.figure_format = 'retina'
Lattice¶
Create a simple drift lattice
D1 = g4.Drift(L=1)
lattice = g4.Lattice(elements={"D1": D1, "LAT": g4.Line(elements=[D1])})
profile_gauss
¶
This profile will make a Gaussian distribition. Here we do some calculations to make the correct bunch length for a given bunch charge to provide a peak current.
PEAK_CURRENT = 1000
BUNCH_CHARGE = 100e-12
SIGMA_T = BUNCH_CHARGE / (sqrt(2 * pi) * PEAK_CURRENT)
SIGMA_Z = SIGMA_T * c
SLEN = 6 * SIGMA_Z
S0 = 3 * SIGMA_Z
SIGMA_T, SIGMA_Z, SLEN
(3.989422804014327e-14, 1.1959988684167075e-05, 7.175993210500245e-05)
main = g4.MainInput(
namelists=[
g4.Setup(
rootname="drift_test",
# lattice="LATFILE",
beamline="LAT",
gamma0=1000,
lambda0=1e-07,
delz=0.026,
seed=123456,
npart=128,
),
g4.Time(slen=SLEN),
g4.ProfileGauss(
label="beamcurrent",
c0=PEAK_CURRENT,
s0=S0,
sig=SIGMA_Z,
),
g4.Beam(
gamma=1000,
delgam=1,
current="beamcurrent",
),
g4.Track(zstop=1),
g4.Write(beam="end"),
],
)
G = g4.Genesis4(main, lattice, verbose=True)
output = G.run()
Configured to run in: /tmp/tmpg16mji7l Running Genesis4 in /tmp/tmpg16mji7l /home/runner/miniconda3/envs/lume-genesis-dev/bin/genesis4 -l genesis.lat genesis4.in --------------------------------------------- GENESIS - Version 4.6.6 has started... Compile info: Compiled by conda at 2024-06-10 16:25:29 [UTC] from Git Commit ID: 07004e4cb437003b4b6cf024122db18caee13722 Starting Time: Thu Aug 29 16:18:22 2024 MPI-Comm Size: 1 node Opened input file genesis4.in Parsing lattice file genesis.lat ... Setting up time window of 71.8 microns with 718 sample points... Adding profile with label: beamcurrent Generating input particle distribution... Running Core Simulation... Time-dependent run with 718 slices for a time window of 71.8 microns Initial analysis of electron beam and radiation field... Calculation: 0% done Writing output file... Core Simulation done. End of Track Writing particle distribution to file: end.par.h5 ...
Program is terminating... Ending Time: Thu Aug 29 16:18:23 2024 Total Wall Clock Time: 0.260937 seconds ------------------------------------- Success - execution took 0.30s.
G.input.main.setup.delz
0.026
print(G.output.run.output_log)
--------------------------------------------- GENESIS - Version 4.6.6 has started... Compile info: Compiled by conda at 2024-06-10 16:25:29 [UTC] from Git Commit ID: 07004e4cb437003b4b6cf024122db18caee13722 Starting Time: Thu Aug 29 16:18:22 2024 MPI-Comm Size: 1 node Opened input file genesis4.in Parsing lattice file genesis.lat ... Setting up time window of 71.8 microns with 718 sample points... Adding profile with label: beamcurrent Generating input particle distribution... Running Core Simulation... Time-dependent run with 718 slices for a time window of 71.8 microns Initial analysis of electron beam and radiation field... Calculation: 0% done Writing output file... Core Simulation done. End of Track Writing particle distribution to file: end.par.h5 ... Program is terminating... Ending Time: Thu Aug 29 16:18:23 2024 Total Wall Clock Time: 0.260937 seconds -------------------------------------
output.load_particles()
P1 = output.particles["end"]
P1.drift_to_z()
P1.plot("t", "energy")
P1
<ParticleGroup with 91904 particles at 0x7fabbf642120>
output.particles["end"]
<ParticleGroup with 91904 particles at 0x7fabbf642120>
Check the charge
P1.charge
np.float64(9.973150081144012e-11)
profile_file
¶
LUME-Genesis automatically makes an HDF5 file with ProfileArray
.
NPTS = 100
SLEN = 100e-6
S = np.linspace(0, SLEN, NPTS)
CURRENT = np.linspace(1, 1000.0, NPTS)
plt.plot(S, CURRENT)
[<matplotlib.lines.Line2D at 0x7fab6e050d10>]
main = g4.MainInput(
namelists=[
g4.Setup(
rootname="drift_test",
# lattice=lattice,
beamline="LAT",
gamma0=1000,
lambda0=1e-07,
delz=0.026,
seed=123456,
npart=128,
),
g4.Time(slen=SLEN),
g4.ProfileArray(label="beamcurrent", xdata=S, ydata=CURRENT),
g4.Beam(
gamma=1000,
delgam=1,
current="beamcurrent",
ex=1e-06,
ey=1e-06,
betax=7.910909406464387,
betay=16.881178621346898,
alphax=-0.7393217413918415,
alphay=1.3870723536888105,
),
g4.Track(zstop=1),
g4.Write(beam="end"),
]
)
G = g4.Genesis4(main, lattice, verbose=True)
output = G.run()
Configured to run in: /tmp/tmpb6sza373 Running Genesis4 in /tmp/tmpb6sza373 /home/runner/miniconda3/envs/lume-genesis-dev/bin/genesis4 -l genesis.lat genesis4.in --------------------------------------------- GENESIS - Version 4.6.6 has started... Compile info: Compiled by conda at 2024-06-10 16:25:29 [UTC] from Git Commit ID: 07004e4cb437003b4b6cf024122db18caee13722 Starting Time: Thu Aug 29 16:18:24 2024 MPI-Comm Size: 1 node Opened input file genesis4.in Parsing lattice file genesis.lat ... Setting up time window of 100 microns with 1000 sample points... Adding profile with label: beamcurrent Generating input particle distribution... Running Core Simulation... Time-dependent run with 1000 slices for a time window of 100 microns Initial analysis of electron beam and radiation field... Calculation: 0% done Writing output file... Core Simulation done. End of Track Writing particle distribution to file: end.par.h5 ...
Program is terminating... Ending Time: Thu Aug 29 16:18:25 2024 Total Wall Clock Time: 0.3432 seconds ------------------------------------- Success - execution took 0.38s.
Inspect the input and output¶
print(main.to_genesis())
&setup rootname = drift_test lattice = genesis.lat beamline = LAT gamma0 = 1000.0 lambda0 = 1e-07 delz = 0.026 seed = 123456 npart = 128 &end &time slen = 0.0001 &end &profile_file label = beamcurrent xdata = ProfileArray_0.h5/x ydata = ProfileArray_0.h5/y &end &beam gamma = 1000.0 delgam = 1.0 current = @beamcurrent ex = 1e-06 ey = 1e-06 betax = 7.910909406464387 betay = 16.881178621346898 alphax = -0.7393217413918415 alphay = 1.3870723536888105 &end &track zstop = 1.0 &end &write beam = end &end
print(lattice.to_genesis())
D1: drift = {l=1.0}; LAT: LINE = {D1};
print(output.run.output_log)
--------------------------------------------- GENESIS - Version 4.6.6 has started... Compile info: Compiled by conda at 2024-06-10 16:25:29 [UTC] from Git Commit ID: 07004e4cb437003b4b6cf024122db18caee13722 Starting Time: Thu Aug 29 16:18:24 2024 MPI-Comm Size: 1 node Opened input file genesis4.in Parsing lattice file genesis.lat ... Setting up time window of 100 microns with 1000 sample points... Adding profile with label: beamcurrent Generating input particle distribution... Running Core Simulation... Time-dependent run with 1000 slices for a time window of 100 microns Initial analysis of electron beam and radiation field... Calculation: 0% done Writing output file... Core Simulation done. End of Track Writing particle distribution to file: end.par.h5 ... Program is terminating... Ending Time: Thu Aug 29 16:18:25 2024 Total Wall Clock Time: 0.3432 seconds -------------------------------------
output.meta
OutputMeta( extra={}, beamdumps=OutputMetaDumps(extra={}, filenames={}, intstep=array([], dtype=float64)), fielddumps=OutputMetaDumps(extra={}, filenames={}, intstep=array([], dtype=float64)), host='Undefined', input_file='&setup\n rootname = drift_test\n lattice = genesis.lat\n beamline = LAT\n gamma0 = 1000.0\n lambda0 = 1e-07\n delz = 0.026\n seed... lattice_file='D1: drift = {l=1.0};\nLAT: LINE = {D1};\n', time_stamp='Thu Aug 29 16:18:24 2024\n', user='runner', version=OutputMetaVersion( extra={}, build_info='Compiled by conda at 2024-06-10 16:25:29 [UTC] from Git Commit ID: 07004e4cb437003b4b6cf024122db18caee13722', major=4.0, minor=6.0, revision=6.0, ), cwd='/tmp/tmpb6sza373', mpisize=1.0, )
output.load_particles()
P1 = output.particles["end"]
P1.drift_to_z()
P1.plot("t", "energy")
P1
<ParticleGroup with 128000 particles at 0x7fab6dcbf2c0>
Resample particles for equal weights. This is neccessary when reading from a distribution file.
NSAMPLE = len(P1)
P1r = P1.resample(NSAMPLE)
P1r.plot("t", "energy")
P1r
<ParticleGroup with 128000 particles at 0x7fab6405e960>
Make a more interesting distribution from this:
P1r.pz[0 : len(P1) // 2] *= 1.1
P1r.plot("t", "energy")
ParticleGroup can write to a file for Genesis4.
Please note that LUME-Genesis will write the distribution for you prior to running Genesis4, so this step is not necessary.
DIST_FILE = "genesis4_distribution.h5"
P1r.write_genesis4_distribution(DIST_FILE, verbose=True)
Resampling 128000 weighted particles
Datasets x, xp, y, yp, t, p written to: genesis4_distribution.h5
ParticleGroup¶
Genesis4Input directly supports OpenPMD-beamphysics ParticleGroup
instances.
When using the MainInput.initial_particles
property setter, LUME-Genesis will ensure the namelist is added before the first "Track" or "Write" namelist in the main input.
It will implicitly set the import_distribution
charge and the time.slen
to the calculated time window from the particles, equivalent to the following:
import_distribution.charge = particles.charge
main.time.slen = max(
c_light * np.ptp(particles.t),
np.ptp(particles.z),
)
Additionally, the appropriate input file for Genesis4 will be written automatically when Genesis4 is executed.
main = g4.MainInput(
namelists=[
g4.Setup(
rootname="drift_test",
# lattice=full_path(LATFILE),
beamline="LAT",
gamma0=1000,
lambda0=1e-07,
delz=0.026,
seed=123456,
npart=512,
),
g4.Time(),
g4.Track(zstop=1),
g4.Write(beam="end"),
],
)
G1 = g4.Genesis4(main, lattice, verbose=True, initial_particles=P1r)
output = G1.run()
WARNING:genesis.version4.input.core:Updating time namelist slen: 0.000100 (was 0.000000)
Configured to run in: /tmp/tmpwzn3_c40 Running Genesis4 in /tmp/tmpwzn3_c40 /home/runner/miniconda3/envs/lume-genesis-dev/bin/genesis4 -l genesis.lat genesis4.in
--------------------------------------------- GENESIS - Version 4.6.6 has started... Compile info: Compiled by conda at 2024-06-10 16:25:29 [UTC] from Git Commit ID: 07004e4cb437003b4b6cf024122db18caee13722 Starting Time: Thu Aug 29 16:19:37 2024 MPI-Comm Size: 1 node Opened input file genesis4.in Parsing lattice file genesis.lat ... Setting up time window of 100 microns with 1000 sample points... Importing distribution file... Charge of external distribution: 1.66782e-10 Particles in external distribution: 128000 Analysing external distribution... Analysis of the imported distribution Total Bunch Length (microns): 99.7986 Length for Matching (microns): 99.7986 Energy (MeV): 536.621 Norm. Emittance in x (micron): 1.00802 Norm. Emittance in y (micron): 1.00601 Beta Function in x (m): 10.0683 Beta Function in y (m): 14.9156 Alpha Function in x : -0.936429 Alpha Function in y : 1.20821 Beam center in x (micron): -0.0532024 Beam center in y (micron): -0.190906 Beam center in px : -4.21174e-08 Beam center in py : -3.03125e-08 Sorting external distribution... Global Sorting: Slicelength: 0 - Send backwards for theta < 4.98993e-07 - Send forward for theta > 9.9401e-05 *** Non-matching PArticle Transfar: Rank: 0 Deleted: 0 Forward: 1032 Backward: 13 Generating internal particle distribution...
Running Core Simulation... Time-dependent run with 1000 slices for a time window of 100 microns Initial analysis of electron beam and radiation field... Calculation: 0% done Writing output file... Core Simulation done. End of Track Writing particle distribution to file: end.par.h5 ...
Program is terminating... Ending Time: Thu Aug 29 16:19:38 2024 Total Wall Clock Time: 0.984933 seconds ------------------------------------- Success - execution took 30.81s.
output.run
RunInfo( error_reason='', run_script='/home/runner/miniconda3/envs/lume-genesis-dev/bin/genesis4 -l genesis.lat genesis4.in', run_time=30.80634787400004, )
output.load_particles()
P2 = output.particles["end"]
P2.z
array([4.12939019e-11, 2.27363562e-08, 5.33377701e-08, ..., 9.99380681e-05, 9.99628116e-05, 9.99879424e-05])
P2.drift_to_z()
P2.plot("t", "energy")
P2
<ParticleGroup with 512000 particles at 0x7fab640d5550>
P2.plot("weight", bins=100)
Notice that importdistribution
is filled in:
print(G1.input.to_genesis())
# Main input &setup rootname = drift_test lattice = genesis.lat beamline = LAT gamma0 = 1000.0 lambda0 = 1e-07 delz = 0.026 seed = 123456 npart = 512 &end &time slen = 9.999850899316347e-05 &end &importdistribution file = initial_particles.h5 charge = 1.6678221438112366e-10 &end &track zstop = 1.0 &end &write beam = end &end # Lattice D1: drift = {l=1.0}; LAT: LINE = {D1};
Cleanup¶
G1.input.initial_particles
<ParticleGroup with 128000 particles at 0x7fab6405e960>
os.remove(DIST_FILE)