-
Notifications
You must be signed in to change notification settings - Fork 29
2.5D Gaussian Solver #1166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
2.5D Gaussian Solver #1166
Changes from 33 commits
8739136
5e185f2
e019105
c35918d
e953591
ef44a50
42e59e7
cdd97d9
d1bee59
75d25a9
c30c8a4
823a199
8cb841f
b63339a
b9024b9
a01d416
ae8b780
b7c297a
bbc6cb7
33b30be
b865c75
af76457
7ba4b2c
2e53ae9
c5f10fb
d13103a
3534984
3182852
3129814
d552588
3875a9c
6b5caef
b9bfb5c
5dca30c
d49eca4
fb0e9bb
12c2e9c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Copyright 2022-2023 ImpactX contributors | ||
| # Authors: Axel Huebl, Ji Qiang | ||
| # 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["momentum_x"], moment=2) ** 0.5 | ||
| sigy = moment(beam["position_y"], moment=2) ** 0.5 | ||
| sigpy = moment(beam["momentum_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() | ||
| beam_final = series.iterations[last_step].particles["beam"] | ||
| final = beam_final.to_df() | ||
|
|
||
| # compare number of particles | ||
| num_particles = 10000 | ||
| assert num_particles == len(initial) | ||
| assert num_particles == len(final) | ||
|
|
||
| print("Initial Beam:") | ||
| sig_xi, sig_yi, sig_ti, emittance_xi, emittance_yi, emittance_ti = get_moments(initial) | ||
| print(f" sigx={sig_xi:e} sigy={sig_yi:e} sigt={sig_ti:e}") | ||
| print( | ||
| f" emittance_x={emittance_xi:e} emittance_y={emittance_yi:e} emittance_t={emittance_ti:e}" | ||
| ) | ||
|
|
||
| atol = 0.0 # ignored | ||
| rtol = 2.2 * num_particles**-0.5 # from random sampling of a smooth distribution | ||
cemitch99 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| print(f" rtol={rtol} (ignored: atol~={atol})") | ||
|
|
||
| assert np.allclose( | ||
| [sig_xi, sig_yi, sig_ti, emittance_xi, emittance_yi, emittance_ti], | ||
| [7.51e-05, 7.51e-05, 9.99e-4, 1.98e-09, 1.98e-09, 1.97e-06], | ||
| rtol=rtol, | ||
| atol=atol, | ||
| ) | ||
|
|
||
|
|
||
| print("") | ||
| print("Final Beam:") | ||
| sig_xf, sig_yf, sig_tf, emittance_xf, emittance_yf, emittance_tf = get_moments(final) | ||
| print(f" sigx={sig_xf:e} sigy={sig_yf:e} sigt={sig_tf:e}") | ||
| print( | ||
| f" emittance_x={emittance_xf:e} emittance_y={emittance_yf:e} emittance_t={emittance_tf:e}" | ||
| ) | ||
|
|
||
| atol = 0.0 # ignored | ||
| rtol = 2.2 * num_particles**-0.5 # from random sampling of a smooth distribution | ||
cemitch99 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| print(f" rtol={rtol} (ignored: atol~={atol})") | ||
|
|
||
| assert np.allclose( | ||
| [sig_xf, sig_yf, sig_tf, emittance_xf, emittance_yf, emittance_tf], | ||
| [ | ||
| 9.22e-05, | ||
| 8.55e-05, | ||
| 0.000996, | ||
| 2.04e-09, | ||
| 2.01e-09, | ||
| 1.97e-06, | ||
|
Comment on lines
+82
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @qianglbl Let's double check these values are correct/converged. |
||
| ], | ||
| rtol=rtol, | ||
| atol=atol, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -46,19 +46,19 @@ def get_moments(beam): | |||||
| assert num_particles == len(final) | ||||||
|
|
||||||
| print("Initial Beam:") | ||||||
| sig_xi, sig_yi, sig_ti, emittance_xi, emittance_yi, emittance_ti = get_moments(initial) | ||||||
| sig_xi, sig_yi, sig_ti, emittance_xi, emittance_yi, emittance_ti = get_moments(final) | ||||||
|
||||||
| sig_xi, sig_yi, sig_ti, emittance_xi, emittance_yi, emittance_ti = get_moments(final) | |
| sig_xi, sig_yi, sig_ti, emittance_xi, emittance_yi, emittance_ti = get_moments(initial) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial and final moments are switched here.
cemitch99 marked this conversation as resolved.
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| ############################################################################### | ||
| # Particle Beam(s) | ||
| ############################################################################### | ||
| beam.npart = 10000 | ||
| beam.units = static | ||
| beam.kin_energy = 1.0e2 | ||
| beam.charge = 1.0e-9 | ||
| beam.particle = electron | ||
| beam.distribution = gaussian | ||
| beam.lambdaX = 3.9984884770e-5 | ||
| beam.lambdaY = beam.lambdaX | ||
| beam.lambdaT = 1.0e-3 | ||
| beam.lambdaPx = 2.6623538760e-5 | ||
| beam.lambdaPy = beam.lambdaPx | ||
| beam.lambdaPt = 2.0e-3 | ||
| beam.muxpx = -0.846574929020762 | ||
| beam.muypy = -beam.muxpx | ||
| beam.mutpt = 0.0 | ||
|
|
||
|
|
||
| ############################################################################### | ||
| # Beamline: lattice elements and segments | ||
| ############################################################################### | ||
| lattice.elements = monitor drift1 monitor quad1 monitor drift2 monitor quad2 monitor drift3 monitor | ||
| lattice.nslice = 25 | ||
|
|
||
| monitor.type = beam_monitor | ||
| monitor.backend = h5 | ||
|
|
||
| drift1.type = drift | ||
| drift1.ds = 0.25 | ||
|
|
||
| quad1.type = quad | ||
| quad1.ds = 1.0 | ||
| quad1.k = 1.0 | ||
|
|
||
| drift2.type = drift | ||
| drift2.ds = 0.5 | ||
|
|
||
| quad2.type = quad | ||
| quad2.ds = 1.0 | ||
| quad2.k = -1.0 | ||
|
|
||
| drift3.type = drift | ||
| drift3.ds = 0.25 | ||
|
|
||
|
|
||
| ############################################################################### | ||
| # Algorithms | ||
| ############################################################################### | ||
| algo.particle_shape = 2 | ||
| algo.space_charge = Gauss2p5D | ||
| algo.space_charge.gauss_nint = 101 | ||
| algo.space_charge.gauss_charge_z_bins = 129 | ||
| algo.space_charge.gauss_taylor_delta = 0.01 | ||
|
|
||
| ############################################################################### | ||
| # Diagnostics | ||
| ############################################################################### | ||
| diag.slice_step_diagnostics = true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Copyright 2022-2023 ImpactX contributors | ||
| # Authors: Axel Huebl, Chad Mitchell, Ji Qiang | ||
| # License: BSD-3-Clause-LBNL | ||
| # | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| from impactx import ImpactX, distribution, elements | ||
|
|
||
| sim = ImpactX() | ||
|
|
||
| # set numerical parameters and IO control | ||
| sim.particle_shape = 2 # B-spline order | ||
| sim.space_charge = "Gauss2p5D" | ||
| sim.space_charge_gauss_nint = 101 | ||
| sim.space_charge_gauss_charge_z_bins = 129 | ||
| sim.space_charge_gauss_taylor_delta = 0.01 | ||
| sim.slice_step_diagnostics = True | ||
|
|
||
| # domain decomposition & space charge mesh | ||
| sim.init_grids() | ||
|
|
||
| # load a 2 GeV electron beam with an initial | ||
| # unnormalized rms emittance of 2 nm | ||
| kin_energy_MeV = 100 # reference energy | ||
| bunch_charge_C = 1.0e-9 # used with space charge | ||
| npart = 10000 # number of macro particles | ||
|
|
||
| # reference particle | ||
| ref = sim.particle_container().ref_particle() | ||
| ref.set_charge_qe(-1.0).set_mass_MeV(0.510998950).set_kin_energy_MeV(kin_energy_MeV) | ||
|
|
||
| # particle bunch | ||
| distr = distribution.Gaussian( | ||
| lambdaX=3.9984884770e-5, | ||
| lambdaY=3.9984884770e-5, | ||
| lambdaT=1.0e-3, | ||
| lambdaPx=2.6623538760e-5, | ||
| lambdaPy=2.6623538760e-5, | ||
| lambdaPt=2.0e-3, | ||
| muxpx=-0.846574929020762, | ||
| muypy=0.846574929020762, | ||
| mutpt=0.0, | ||
| ) | ||
| sim.add_particles(bunch_charge_C, distr, npart) | ||
|
|
||
| # add beam diagnostics | ||
| monitor = elements.BeamMonitor("monitor", backend="h5") | ||
|
|
||
| # design the accelerator lattice) | ||
| ns = 25 # number of slices per ds in the element | ||
| fodo = [ | ||
| monitor, | ||
| elements.ChrDrift(name="drift1", ds=0.25, nslice=ns), | ||
| monitor, | ||
| elements.ChrQuad(name="quad1", ds=1.0, k=1.0, nslice=ns), | ||
| monitor, | ||
| elements.ChrDrift(name="drift2", ds=0.5, nslice=ns), | ||
| monitor, | ||
| elements.ChrQuad(name="quad2", ds=1.0, k=-1.0, nslice=ns), | ||
| monitor, | ||
| elements.ChrDrift(name="drift3", ds=0.25, nslice=ns), | ||
| monitor, | ||
| ] | ||
| # assign a fodo segment | ||
| sim.lattice.extend(fodo) | ||
|
|
||
| # run simulation | ||
| sim.track_particles() | ||
|
|
||
| # clean shutdown | ||
| sim.finalize() |
Uh oh!
There was an error while loading. Please reload this page.