-
Notifications
You must be signed in to change notification settings - Fork 29
ChrPlasmaLens element: Support k<0, and fix uninitialized-variable bug in tracking of reference particle #1030
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
Merged
Merged
Changes from 51 commits
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
2be89b0
Compiles?
kyrsjo de1830f
Fixed the math, no we can defocus with k<0!
kyrsjo 1267d4a
Initial add of defocusing ChrPlasmaLens
kyrsjo 61bfa90
Fix use of uninitialized variable for reference particle tracking in …
kyrsjo d39ef33
Remove forgotten debugging comment
kyrsjo b7e83f5
Splelling
kyrsjo 2ab5502
Fix tabs/spaces
kyrsjo 98abdfd
Fix uninitialized variable giving bad results for envelope tracking w…
kyrsjo 71140f9
Handle m_g=0 correctly in ChrPlasmaLens
kyrsjo 71a25b3
Use right litteral type in comparisons
kyrsjo 160d29f
Fix indentation
kyrsjo 72426ee
litteral types for assignments
kyrsjo 7702878
Merge branch 'development' into APL-negK
kyrsjo 6c683df
Rollback the changes in ConstF to what it looks in development branch…
kyrsjo af58e67
Merge branch 'development' into APL-negK
kyrsjo c9b76e5
Fix apochromatic_pl test as suggested by @cemitch99
kyrsjo b549e52
Merge branch 'development' into APL-negK
kyrsjo e2f4a72
Chromatic effect in drift as well, as in ChrQuad and in ChrDrift
kyrsjo b0c97ca
Merge branch 'development' into APL-negK
kyrsjo f80b2e8
Fix time propagation for g=0 in ChrPlasmaLens
kyrsjo 084bfe6
Fix time dependency for negative focusing
kyrsjo c28173f
Merge branch 'development' into APL-negK
kyrsjo 9594af2
Merge branch 'development' into APL-negK
kyrsjo 4183317
Start adding tests for APLs
kyrsjo 76770e1
Activate the APL test
kyrsjo 9f27a0a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] eac18d4
Refactoring
kyrsjo e0a4128
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 8d857c9
Improve ChrPlasmaLens tests and add plot
kyrsjo 9c63ba5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 2add452
Test the ChrPlasmaLens, not drift
kyrsjo 6c032c5
Coding conventions
kyrsjo 435c8f2
Cleanup
kyrsjo 53fe154
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 8ba3b0d
Add focusing test to ChrPlasmaLens
kyrsjo f805026
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] b8ce24f
Add defocusing test
kyrsjo bb5f6d2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] 206efcf
Cleanup and add to CMakeLists
kyrsjo bb670a1
Fix analytical estimate, generalize run script for test
kyrsjo ebd3d03
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] d1cff56
Fix error in CMakeLists
kyrsjo 42cce64
Rename run_APL_ChrPlasmaLens.py -> run_APL.py
kyrsjo 7f06ab2
Swap reference values to analytical values
kyrsjo 4a70434
Catch error
kyrsjo 52a252f
Add README.rst for active_plasma_lens_test
kyrsjo efca31b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] a64508a
Hopefully fixing REST syntax
kyrsjo 199cef0
Merge branch 'development' into APL-negK
kyrsjo fba821b
Merge branch 'development' into APL-negK
kyrsjo 4866ef8
Merge branch 'development' into APL-negK
cemitch99 2089acf
Update examples/active_plasma_lens/plot_APL_ChrPlasmaLens_analytical.py
cemitch99 083d8dd
Link README to examples documentation.
cemitch99 fb81266
Update docs/source/usage/examples.rst
cemitch99 aa5d51a
Apply suggestions from code review
cemitch99 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,45 @@ | ||
| .. _examples-active_plasma_lens: | ||
|
|
||
| Active Plasma Lens | ||
| ================== | ||
|
|
||
| These examples demonstrates the of the effect of an Active Plasma Lens (APL) on the beam. | ||
| The lattice contains this element and nothing else. | ||
| The length of the element is 20 mm, and it can be run in no-field, focusing, and defocusing mode. | ||
|
|
||
| We use a 200 MeV electron beam with an initial normalized rms emittance of 10 um. | ||
| The beam is set to have :math:`\alpha = 0` in the middle of the lens in the case of no field. | ||
| The beam size in the middle of the lens is set to 10 µm for the no-field examples (in order to have a strongly parabolic :math:`\beta`-function within the lens), and 100 µm for the focusing and defocusing examples. | ||
| A :math:`\sigma_{pt} = 10^{-3}` is also assumed. | ||
| Before the simulations, this beam is back-propagate to the lens entry asuming no field. | ||
cemitch99 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Run | ||
| --- | ||
|
|
||
| This example can be run as | ||
| * ``python3 run_APL_ChrPlasmaLens_zero.py`` (no field, ``ChrPlasmaLens``, tracking) | ||
| * ``python3 run_APL_ChrPlasmaLens_focusing.py`` (focusing field, ``ChrPlasmaLens``, tracking) | ||
| * ``python3 run_APL_ChrPlasmaLens_defocusing.py`` (defocusing field, ``ChrPlasmaLens``, tracking) | ||
|
|
||
| These all use the library ``run_APL.py`` internally to create the simulations. | ||
|
|
||
| Analyze | ||
| ------- | ||
|
|
||
| We run the following scripts to analyze correctness of the output: | ||
| * ``python3 analysis_APL_ChrPlasmaLens_zero.py`` (no field, ``ChrPlasmaLens``, tracking) | ||
| * ``python3 analysis_APL_ChrPlasmaLens_focusing.py`` (focusing field, ``ChrPlasmaLens``, tracking) | ||
| * ``python3 analysis_APL_ChrPlasmaLens_defocusing.py`` (defocusing field, ``ChrPlasmaLens``, tracking) | ||
|
|
||
| These all use the library ``analysis_APL_ChrPlasmaLens.py`` internally. | ||
|
|
||
| Visualize | ||
| --------- | ||
| You can run the following scripts to visualize the beam evolution over time (e.g. :math:`s`): | ||
| * ``python3 s_APL_ChrPlasmaLens_zero.py`` (no field, ``ChrPlasmaLens``, tracking)plot | ||
| * ``python3 plot_APL_ChrPlasmaLens_focusing.py`` (focusing field, ``ChrPlasmaLens``, tracking) | ||
| * ``python3 plot_APL_ChrPlasmaLens_defocusing.py`` (defocusing field, ``ChrPlasmaLens``, tracking) | ||
|
|
||
| These all use the library ``plot_APL_ChrPlasmaLens.py`` internally. | ||
|
|
||
| Additionally, it is also possible to run ``python3 plot_APL_ChrPlasmaLens_analytical.py``, which plots the expected Twiss :math:`\alpha` and :math:`\beta` functions at the end of the lens as a function of the lens gradient. This uses the stand-alone Twiss propagation function ``analytic_final_estimate()`` from ``run_APL.py``. | ||
This file contains hidden or 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,64 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Copyright 2022-2025 ImpactX contributors | ||
| # Authors: Axel Huebl, Chad Mitchell, Kyrre Sjobak | ||
| # License: BSD-3-Clause-LBNL | ||
| # | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| 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) | ||
|
|
||
|
|
||
| def get_twiss(beam): | ||
| "Calculate the beam Twiss parameters from position and momenta values" | ||
|
|
||
| epstrms = beam.cov(ddof=0) | ||
|
|
||
| sigx2 = epstrms["position_x"]["position_x"] | ||
| sigpx2 = epstrms["momentum_x"]["momentum_x"] | ||
| emittance_x = (sigx2 * sigpx2 - epstrms["position_x"]["momentum_x"] ** 2) ** 0.5 | ||
| beta_x = sigx2 / emittance_x | ||
| alpha_x = -epstrms["position_x"]["momentum_x"] / emittance_x | ||
|
|
||
| sigy2 = epstrms["position_y"]["position_y"] | ||
| sigpy2 = epstrms["momentum_y"]["momentum_y"] | ||
| emittance_y = (sigy2 * sigpy2 - epstrms["position_y"]["momentum_y"] ** 2) ** 0.5 | ||
| beta_y = sigy2 / emittance_y | ||
| alpha_y = -epstrms["position_y"]["momentum_y"] / emittance_y | ||
|
|
||
| return (beta_x, beta_y, alpha_x, alpha_y) | ||
|
Member
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. Note: This works, but the values defined here are computed internally and stored as reduced_diagnostics. See this example for an alternative approach: https://impactx.readthedocs.io/en/latest/usage/examples/fodo_space_charge/README.html |
||
|
|
||
|
|
||
| def get_beams(): | ||
| "Load the initial and final beam from last simulation" | ||
| 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() | ||
|
|
||
| return (initial, beam_final, final) | ||
86 changes: 86 additions & 0 deletions
86
examples/active_plasma_lens/analysis_APL_ChrPlasmaLens_defocusing.py
This file contains hidden or 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,86 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Copyright 2022-2025 ImpactX contributors | ||
| # Authors: Axel Huebl, Chad Mitchell, Kyrre Sjobak | ||
| # License: BSD-3-Clause-LBNL | ||
| # | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| import numpy as np | ||
| from analysis_APL_ChrPlasmaLens import get_beams, get_moments, get_twiss | ||
|
|
||
| # initial/final beam | ||
| (initial, beam_final, final) = get_beams() | ||
|
|
||
| # compare number of particles | ||
| num_particles = 10000 | ||
| assert num_particles == len(initial) | ||
| assert num_particles == len(final) | ||
|
|
||
| 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}" | ||
| ) | ||
|
|
||
| (betax, betay, alphax, alphay) = get_twiss(initial) | ||
| print(f" betax={betax}[m],betay={betay}[m],alphax={alphax},alphay={alphay}") | ||
|
|
||
| atol = 0.0 # ignored | ||
| rtol = 2.2 * num_particles**-0.5 # from random sampling of a smooth distribution | ||
| print(f" rtol={rtol} (ignored: atol~={atol})") | ||
|
|
||
| # Compare to analytical values | ||
| assert np.allclose( | ||
| [sigx, sigy, sigt, emittance_x, emittance_y, emittance_t], | ||
| [ | ||
| 0.00010003246877770656, | ||
| 0.00010003246877770656, | ||
| 0.001, | ||
| 2.548491664266332e-08, | ||
| 2.548491664266332e-08, | ||
| 1e-06, | ||
| ], | ||
| rtol=rtol, | ||
| atol=atol, | ||
| ) | ||
|
|
||
|
|
||
| print("") | ||
| print("Final Beam:") | ||
| sigx, sigy, sigt, emittance_x, emittance_y, emittance_t = get_moments(final) | ||
| s_ref = beam_final.get_attribute("s_ref") | ||
| gamma_ref = beam_final.get_attribute("gamma_ref") | ||
| 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}\n" | ||
| f" s_ref={s_ref:e} gamma_ref={gamma_ref:e}" | ||
| ) | ||
|
|
||
| (betax, betay, alphax, alphay) = get_twiss(final) | ||
| print(f" betax={betax}[m],betay={betay}[m],alphax={alphax},alphay={alphay}") | ||
|
|
||
| atol = 0.0 # ignored | ||
| # rtol = 2.2 * num_particles**-0.5 # from random sampling of a smooth distribution | ||
cemitch99 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| rtol = ( | ||
| 2.9 * num_particles**-0.5 | ||
| ) # from random sampling of a smooth distribution -- tolerance increased here | ||
| print(f" rtol={rtol} (ignored: atol~={atol})") | ||
|
|
||
| # Compare to analytical values | ||
| assert np.allclose( | ||
| [sigx, sigy, sigt, emittance_x, emittance_y, emittance_t, s_ref, gamma_ref], | ||
| [ | ||
| 0.0001314429025974998, | ||
| 0.0001314429025974998, | ||
| 0.001, | ||
| 2.514662e-08, | ||
| 2.514662e-08, | ||
| 1e-06, | ||
| 20e-3, | ||
| 3.923902e02, | ||
| ], | ||
| rtol=rtol, | ||
| atol=atol, | ||
| ) | ||
83 changes: 83 additions & 0 deletions
83
examples/active_plasma_lens/analysis_APL_ChrPlasmaLens_focusing.py
This file contains hidden or 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,83 @@ | ||
| #!/usr/bin/env python3 | ||
| # | ||
| # Copyright 2022-2025 ImpactX contributors | ||
| # Authors: Axel Huebl, Chad Mitchell, Kyrre Sjobak | ||
| # License: BSD-3-Clause-LBNL | ||
| # | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| import numpy as np | ||
| from analysis_APL_ChrPlasmaLens import get_beams, get_moments, get_twiss | ||
|
|
||
| # initial/final beam | ||
| (initial, beam_final, final) = get_beams() | ||
|
|
||
| # compare number of particles | ||
| num_particles = 10000 | ||
| assert num_particles == len(initial) | ||
| assert num_particles == len(final) | ||
|
|
||
| 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}" | ||
| ) | ||
|
|
||
| (betax, betay, alphax, alphay) = get_twiss(initial) | ||
| print(f" betax={betax}[m],betay={betay}[m],alphax={alphax},alphay={alphay}") | ||
|
|
||
| atol = 0.0 # ignored | ||
| rtol = 2.2 * num_particles**-0.5 # from random sampling of a smooth distribution | ||
| print(f" rtol={rtol} (ignored: atol~={atol})") | ||
|
|
||
| # Compare to analytical values | ||
| assert np.allclose( | ||
| [sigx, sigy, sigt, emittance_x, emittance_y, emittance_t], | ||
| [ | ||
| 0.00010003246877770656, | ||
| 0.00010003246877770656, | ||
| 0.001, | ||
| 2.548491664266332e-08, | ||
| 2.548491664266332e-08, | ||
| 1e-06, | ||
| ], | ||
| rtol=rtol, | ||
| atol=atol, | ||
| ) | ||
|
|
||
|
|
||
| print("") | ||
| print("Final Beam:") | ||
| sigx, sigy, sigt, emittance_x, emittance_y, emittance_t = get_moments(final) | ||
| s_ref = beam_final.get_attribute("s_ref") | ||
| gamma_ref = beam_final.get_attribute("gamma_ref") | ||
| 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}\n" | ||
| f" s_ref={s_ref:e} gamma_ref={gamma_ref:e}" | ||
| ) | ||
|
|
||
| (betax, betay, alphax, alphay) = get_twiss(final) | ||
| print(f" betax={betax}[m],betay={betay}[m],alphax={alphax},alphay={alphay}") | ||
|
|
||
| atol = 0.0 # ignored | ||
| rtol = 2.2 * num_particles**-0.5 # from random sampling of a smooth distribution | ||
| print(f" rtol={rtol} (ignored: atol~={atol})") | ||
|
|
||
| # Compare to analytical values | ||
| assert np.allclose( | ||
| [sigx, sigy, sigt, emittance_x, emittance_y, emittance_t, s_ref, gamma_ref], | ||
| [ | ||
| 7.161196476484095e-05, | ||
| 7.161196476484095e-05, | ||
| 0.001, | ||
| 2.548491664266332e-08, | ||
| 2.548491664266332e-08, | ||
| 1e-06, | ||
| 20e-3, | ||
| 3.923902e02, | ||
| ], | ||
| rtol=rtol, | ||
| atol=atol, | ||
| ) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.