-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add chromatic plasma lens model (#514)
* Examples for 3D space charge benchmarking - Modified the initial beam size in the IOTA lens benchmark example. - Added 2 benchmarks of 3D space charge for initial testing. - Add documentation for 2 benchmarks with space charge. - Add a benchmark example with space charge and periodic s-dependent focusing. - Added an s-dependent example using a Kurth beam without space charge. - Modified tolerance for IOTA lens benchmark example. Reduced tolerance to account for smaller initial beam size and improved preservation of invariants of motion. - Modified tolerances of space charge examples to allow CI tests to pass when space charge is not active. - Modified tolerance for space charge examples. These should fail unless space charge is turned on. * Update input_kurth_10nC.in Selected numerical values for amr.n_cell, lattice.nslice, and geometry.prob_relative. * Add chromatic plasma lens model. * Delete examples/kurth/input_kurth_10nC.in This is not part of this PR. * Add Python and element docs. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove unused variable, add README. * Add draft of example input files. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add test and modify input field strength units to T/m. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix duplicate test name (apochromat). * Add draft of anlysis script. * Update analysis_apochromatic_pl.py Update prediction for relative emittance growth. * Update analysis_apochromatic_pl.py Modify tolerance evaluation for relative emittance growth. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Formatting, Includes, Copy-Paste Leftovers * Modify input parameter units to allow two options. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Correct some text in comments. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Axel Huebl <[email protected]>
- Loading branch information
1 parent
6e21c86
commit 4a8357d
Showing
11 changed files
with
702 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#!/usr/bin/env python3 | ||
# | ||
# Copyright 2022-2023 ImpactX contributors | ||
# Authors: Axel Huebl, Chad Mitchell | ||
# License: BSD-3-Clause-LBNL | ||
# | ||
|
||
import numpy as np | ||
import openpmd_api as io | ||
from scipy.stats import moment | ||
|
||
|
||
def get_moments(beam): | ||
"""Calculate standard deviations of beam position & momenta | ||
and emittance values | ||
Returns | ||
------- | ||
sigx, sigy, sigt, emittance_x, emittance_y, emittance_t | ||
""" | ||
sigx = moment(beam["position_x"], moment=2) ** 0.5 # variance -> std dev. | ||
sigpx = moment(beam["divergence_x"], moment=2) ** 0.5 | ||
sigy = moment(beam["position_y"], moment=2) ** 0.5 | ||
sigpy = moment(beam["divergence_y"], moment=2) ** 0.5 | ||
sigt = moment(beam["position_t"], moment=2) ** 0.5 | ||
sigpt = moment(beam["momentum_t"], moment=2) ** 0.5 | ||
|
||
epstrms = beam.cov(ddof=0) | ||
emittance_x = (sigx**2 * sigpx**2 - epstrms["position_x"]["momentum_x"] ** 2) ** 0.5 | ||
emittance_y = (sigy**2 * sigpy**2 - epstrms["position_y"]["momentum_y"] ** 2) ** 0.5 | ||
emittance_t = (sigt**2 * sigpt**2 - epstrms["position_t"]["momentum_t"] ** 2) ** 0.5 | ||
|
||
return (sigx, sigy, sigt, emittance_x, emittance_y, emittance_t) | ||
|
||
|
||
# initial/final beam | ||
series = io.Series("diags/openPMD/monitor.h5", io.Access.read_only) | ||
last_step = list(series.iterations)[-1] | ||
initial = series.iterations[1].particles["beam"].to_df() | ||
final = series.iterations[last_step].particles["beam"].to_df() | ||
|
||
# compare number of particles | ||
num_particles = 100000 | ||
assert num_particles == len(initial) | ||
assert num_particles == len(final) | ||
|
||
scale = ( | ||
(1.0 - initial.momentum_t) ** 2 | ||
+ (initial.momentum_x) ** 2 | ||
+ (initial.momentum_y) ** 2 | ||
) | ||
xp = initial.momentum_x / np.sqrt(scale) | ||
initial["divergence_x"] = xp | ||
yp = initial.momentum_y / np.sqrt(scale) | ||
initial["divergence_y"] = yp | ||
|
||
print("Initial Beam:") | ||
sigx, sigy, sigt, emittance_x, emittance_y, emittance_t = get_moments(initial) | ||
print(f" sigx={sigx:e} sigy={sigy:e} sigt={sigt:e}") | ||
print( | ||
f" emittance_x={emittance_x:e} emittance_y={emittance_y:e} emittance_t={emittance_t:e}" | ||
) | ||
|
||
atol = 0.0 # ignored | ||
rtol = 3.0 * num_particles**-0.5 # from random sampling of a smooth distribution | ||
print(f" rtol={rtol} (ignored: atol~={atol})") | ||
|
||
assert np.allclose( | ||
[sigx, sigy, sigt, emittance_x, emittance_y, emittance_t], | ||
[ | ||
1.288697604e-6, | ||
1.288697604e-6, | ||
1.0e-6, | ||
5.10997388810014764e-12, | ||
5.10997388810014764e-12, | ||
1.0e-8, | ||
], | ||
rtol=rtol, | ||
atol=atol, | ||
) | ||
|
||
|
||
scale = ( | ||
(1.0 - final.momentum_t) ** 2 + (final.momentum_x) ** 2 + (final.momentum_y) ** 2 | ||
) | ||
xp = final.momentum_x / np.sqrt(scale) | ||
final["divergence_x"] = xp | ||
yp = final.momentum_y / np.sqrt(scale) | ||
final["divergence_y"] = yp | ||
|
||
print("") | ||
print("Final Beam:") | ||
sigx, sigy, sigt, emittance_xf, emittance_yf, emittance_tf = get_moments(final) | ||
demittance_x = 100 * abs(emittance_xf - emittance_x) / emittance_x | ||
demittance_y = 100 * abs(emittance_yf - emittance_y) / emittance_y | ||
demittance_t = 100 * abs(emittance_tf - emittance_t) / emittance_t | ||
|
||
print(f" sigx={sigx:e} sigy={sigy:e} sigt={sigt:e}") | ||
print( | ||
f" emittance change x (%)={demittance_x:e} emittance change y (%)={demittance_y:e} emittance change t (%)={demittance_t:e}" | ||
) | ||
|
||
atol = 0.0 # ignored | ||
rtol = 19.0 * num_particles**-0.5 # from random sampling of a smooth distribution | ||
print(f" rtol={rtol} (ignored: atol~={atol})") | ||
|
||
assert np.allclose( | ||
[sigx, sigy, sigt], | ||
[ | ||
1.283476e-06, | ||
1.291507e-06, | ||
1.0e-6, | ||
], | ||
rtol=rtol, | ||
atol=atol, | ||
) | ||
|
||
atol = 2.0e-3 # from random sampling of a smooth distribution | ||
print(f" atol={atol} %") | ||
|
||
assert np.allclose( | ||
[demittance_x, demittance_y, demittance_t], | ||
[ | ||
0.0, | ||
0.0, | ||
0.0, | ||
], | ||
atol=atol, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
############################################################################### | ||
# Particle Beam(s) | ||
############################################################################### | ||
beam.npart = 100000 | ||
beam.units = static | ||
beam.kin_energy = 100.0e3 # 100 GeV nominal energy | ||
beam.charge = 1.0e-9 | ||
beam.particle = electron | ||
beam.distribution = gaussian | ||
beam.sigmaX = 1.288697604e-6 | ||
beam.sigmaY = 1.288697604e-6 | ||
beam.sigmaT = 1.0e-6 | ||
beam.sigmaPx = 3.965223396e-6 | ||
beam.sigmaPy = 3.965223396e-6 | ||
beam.sigmaPt = 0.01 #1% energy spread | ||
beam.muxpx = 0.0 | ||
beam.muypy = 0.0 | ||
beam.mutpt = 0.0 | ||
|
||
|
||
############################################################################### | ||
# Beamline: lattice elements and segments | ||
############################################################################### | ||
lattice.elements = monitor dr1 q1 dr2 q2 dr2 q3 dr2 q4 dr2 q5 dr2 q6 dr2 q7 dr1 monitor | ||
lattice.nslice = 1 | ||
|
||
monitor.type = beam_monitor | ||
monitor.backend = h5 | ||
|
||
dr1.type = drift_chromatic | ||
dr1.ds = 1.0 | ||
|
||
dr2.type = drift_chromatic | ||
dr2.ds = 2.0 | ||
|
||
q1.type = plasma_lens_chromatic | ||
q1.ds = 0.331817852986604588 | ||
q1.k = 996.147787384348956 | ||
q1.units = 1 | ||
#q1.k = 2.98636067687944129 | ||
|
||
q2.type = plasma_lens_chromatic | ||
q2.ds = 0.176038957633108457 | ||
q2.k = 528.485181135649785 | ||
q2.units = 1 | ||
#q2.k = 1.584350618697976110 | ||
|
||
q3.type = plasma_lens_chromatic | ||
q3.ds = 1.041842576046930486 | ||
q3.k = 3127.707468391874166 | ||
q3.units = 1 | ||
#q3.k = 9.37658318442237437 | ||
|
||
q4.type = plasma_lens_chromatic | ||
q4.ds = 0.334367090894399520 | ||
q4.k = 501.900417308233112 | ||
q4.units = 1 | ||
#q4.k = 1.50465190902479784 | ||
|
||
q5.type = plasma_lens_chromatic | ||
q5.ds = 1.041842576046930486 | ||
q5.k = 3127.707468391874166 | ||
q5.units = 1 | ||
#q5.k = 9.37658318442237437 | ||
|
||
q6.type = plasma_lens_chromatic | ||
q6.ds = 0.176038957633108457 | ||
q6.k = 528.485181135649785 | ||
q6.units = 1 | ||
#q6.k = 1.584350618697976110 | ||
|
||
q7.type = plasma_lens_chromatic | ||
q7.ds = 0.331817852986604588 | ||
q7.k = 996.147787384348956 | ||
q7.units = 1 | ||
#q7.k = 2.98636067687944129 | ||
|
||
|
||
############################################################################### | ||
# Algorithms | ||
############################################################################### | ||
algo.particle_shape = 2 | ||
algo.space_charge = false | ||
|
||
|
||
############################################################################### | ||
# Diagnostics | ||
############################################################################### | ||
diag.slice_step_diagnostics = true |
Oops, something went wrong.