Skip to content
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

User-Defined Linear Map #743

Merged
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
4e2a733
[Draft] Transport and Covariance Matrices
ax3l Sep 24, 2024
5d09112
Update InitElement.cpp
cemitch99 Sep 25, 2024
7d95ca5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 25, 2024
65c9bd0
Update LinearMap.H
cemitch99 Sep 25, 2024
2ad47d2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 25, 2024
c2fe2be
Update InitDistribution.cpp
cemitch99 Sep 26, 2024
a5df0a3
Add Drift return linear map.
cemitch99 Sep 26, 2024
b2f158c
Use LinearMap struct in Drift.H.
cemitch99 Sep 27, 2024
0044f78
Merge branch 'development' into topic-covariance-and-transport-maps
cemitch99 Oct 10, 2024
cd4c989
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 10, 2024
a9888ce
Merge remote-tracking branch 'mainline/development' into topic-covari…
ax3l Oct 11, 2024
817cc51
Transport/Covariane: Use `SmallMatrix`
ax3l Oct 11, 2024
1ef158e
Add Python bindings for LinearMap element.
cemitch99 Oct 15, 2024
ccad983
Update elements.cpp
cemitch99 Oct 15, 2024
2b288db
Update elements.cpp
cemitch99 Oct 15, 2024
06718d8
Update elements.cpp
cemitch99 Oct 23, 2024
2e57e91
Add LinearMap to 'Named' elements.
cemitch99 Nov 2, 2024
911fbec
Update LinearMap.H
cemitch99 Nov 2, 2024
ac6556c
Modify LinearMap Python bindings.
cemitch99 Nov 2, 2024
0444b5d
Update src/initialization/InitDistribution.cpp
cemitch99 Nov 5, 2024
fa67921
Update src/initialization/InitDistribution.cpp
cemitch99 Nov 5, 2024
d460272
Update InitDistribution.cpp
cemitch99 Nov 20, 2024
9fb2a2a
Leftover Improvements from first PR
ax3l Jan 6, 2025
f1a13af
Finalize Python
ax3l Jan 6, 2025
0807b41
More Detailed Warning
ax3l Jan 6, 2025
f7cb2e2
Start Examples
ax3l Jan 6, 2025
e1706eb
Start Documentation
ax3l Jan 6, 2025
26f45db
Fix Bugs (incl. AMReX)
ax3l Jan 6, 2025
a0e147f
Docs Updates
ax3l Jan 6, 2025
74dacd0
Merge remote-tracking branch 'mainline/development' into topic-covari…
ax3l Jan 10, 2025
317e6bf
`LinearMap`: `ds` bookkeeping
ax3l Jan 10, 2025
2fee7e2
Add thin linear map example.
cemitch99 Jan 12, 2025
611a0ea
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 12, 2025
7081416
Document example README.
cemitch99 Jan 12, 2025
c81a012
Update run_map.py
cemitch99 Jan 12, 2025
04be1fb
Update run_map.py
cemitch99 Jan 12, 2025
1a36a89
Update run_map.py
cemitch99 Jan 12, 2025
4fa891b
Update input_map.in
cemitch99 Jan 12, 2025
6c975f7
Apply suggestions from code review
ax3l Jan 12, 2025
57c2f3d
Add docs for matrix elements.
cemitch99 Jan 13, 2025
baf0fa0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 13, 2025
d5897ac
Doc Updates
ax3l Jan 13, 2025
aff0764
Generalize CMake Args for inputs
ax3l Jan 13, 2025
c8ac06c
Add symplectic warning in app element documentation.
cemitch99 Jan 13, 2025
46a0f5d
Add symplectic warning in Python element documentation.
cemitch99 Jan 13, 2025
697661b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 13, 2025
a1c2d80
Remove runtime warning.
cemitch99 Jan 13, 2025
b81732b
Add support for nonzero ds to app input.
cemitch99 Jan 13, 2025
bdb2d7f
Update examples/CMakeLists.txt
cemitch99 Jan 13, 2025
d729b2f
FODO Analysis: Check s and gamma
ax3l Jan 13, 2025
d0ffd9c
__repr__: no select entries
ax3l Jan 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/source/usage/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ Single Particle Dynamics
examples/aperture/README.rst
examples/iota_lens/README.rst
examples/achromatic_spectrometer/README.rst
examples/fodo_userdef/README.rst
examples/fodo_programmable/README.rst
examples/dogleg/README.rst
examples/coupled_optics/README.rst

examples/linear_map/README.rst

Collective Effects
------------------
Expand Down
16 changes: 16 additions & 0 deletions docs/source/usage/parameters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,22 @@ Lattice Elements
* ``<element_name>.rotation`` (``float``, in degrees) rotation error in the transverse plane
* ``<element_name>.nslice`` (``integer``) number of slices used for the application of space charge (default: ``1``)

* ``linear_map`` for a custom, linear transport matrix.

The matrix elements :math:`R(i,j)` are indexed beginning with 1, so that :math:`i,j=1,2,3,4,5,6`.
The transport matrix :math:`R` is defaulted to the identity matrix, so only matrix entries that differ from that need to be specified.

The matrix :math:`R` multiplies the phase space vector :math:`(x,px,y,py,t,pt)`, where coordinates :math:`(x,y,t)` have units of m
and momenta :math:`(px,py,pt)` are dimensionless. So, for example, :math:`R(1,1)` is dimensionless, and :math:`R(1,2)` has units of m.

This requires these additional parameters:

* ``<element_name>.R(i,j)`` (``float``, ...) matrix entries
a 1-indexed, 6x6, linear transport map to multiply with the the phase space vector :math:`x,px,y,py,t,pt`.
* ``<element_name>.dx`` (``float``, in meters) horizontal translation error
* ``<element_name>.dy`` (``float``, in meters) vertical translation error
* ``<element_name>.rotation`` (``float``, in degrees) rotation error in the transverse plane

* ``multipole`` for a thin multipole element.
This requires these additional parameters:

Expand Down
15 changes: 15 additions & 0 deletions docs/source/usage/python.rst
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,21 @@ This module provides elements for the accelerator lattice.
:param unit: specification of units (``"dimensionless"`` in units of the magnetic rigidity of the reference particle or ``"T-m"``)
:param name: an optional name for the element

.. py::class:: impactx.elements.LinearMap(R, dx=0, dy=0, rotation=0, name=None)

A custom, linear transport matrix.

The matrix elements :math:`R(i,j)` are indexed beginning with 1, so that :math:`i,j=1,2,3,4,5,6`.

The matrix :math:`R` multiplies the phase space vector :math:`(x,px,y,py,t,pt)`, where coordinates :math:`(x,y,t)` have units of m
and momenta :math:`(px,py,pt)` are dimensionless. So, for example, :math:`R(1,1)` is dimensionless, and :math:`R(1,2)` has units of m.

:param R: a linear transport map to multiply with the the phase space vector :math:`(x,px,y,py,t,pt)`.
:param dx: horizontal translation error in m
:param dy: vertical translation error in m
:param rotation: rotation error in the transverse plane [degrees]
:param name: an optional name for the element

.. py:class:: impactx.elements.Multipole(multipole, K_normal, K_skew, dx=0, dy=0, rotation=0, name=None)

A general thin multipole element.
Expand Down
31 changes: 23 additions & 8 deletions docs/source/usage/workflows/add_element.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@ The workflows described here apply both for thin kicks or thick elements.
Thick elements can also use soft-edged fringe fields (see `existing soft-edged elements for implementation details <https://github.com/ECP-WarpX/impactx/tree/development/src/particles/elements>`__).


.. _usage-workflows-add-element-linmap:

Linear Map
----------

A custom linear element can be provided by specifying the 6x6 linear transport matrix :math:`R` as an input.
See the :ref:` example <examples-fodo-userdef>` for Python and inputs file syntax to specify a custom linear element.

The matrix elements :math:`R(i,j)` are indexed beginning with 1, so that :math:`i,j=1,2,3,4,5,6`.

The matrix :math:`R` multiplies the phase space vector :math:`(x,px,y,py,t,pt)`, where coordinates :math:`(x,y,t)` have units of m
and momenta :math:`(px,py,pt)` are dimensionless. So, for example, :math:`R(1,1)` is dimensionless, and :math:`R(1,2)` has units of m.


.. note::

If a user-provided linear map is used, it is up to the user to ensure that the 6x6 transport matrix is symplectic.
If a more general form of user-defined transport is needed, the :ref:`Python Programmable Element <usage-workflows-add-element-python>` and the :ref:`C++ Element <usage-workflows-add-element-cxx>` provide a more general approach.


.. _usage-workflows-add-element-python:

Python Programmable Element
---------------------------

Expand All @@ -30,14 +52,7 @@ Detailed examples that show usage of the programmable element are:
Detailed particle computing interfaces are presented in the `pyAMReX examples <https://pyamrex.readthedocs.io/en/latest/usage/compute.html#particles>`__.


Linear Map
----------

.. note::

We plan to add a simple, linear map element that can be configured in user input.
Follow `issue #538 <https://github.com/ECP-WarpX/impactx/issues/538>`__ for progress.

.. _usage-workflows-add-element-cxx:

C++ Element
-----------
Expand Down
64 changes: 60 additions & 4 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,30 @@ function(add_impactx_test name input is_mpi analysis_script plot_script)
# make a unique run directory
file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name})

# get input file/script and optional command-line arguments
separate_arguments(INPUTS_LIST UNIX_COMMAND "${input}")
list(GET INPUTS_LIST 0 INPUTS_FILE)
list(LENGTH INPUTS_LIST INPUTS_LIST_LENGTH)
if(INPUTS_LIST_LENGTH GREATER 1)
list(SUBLIST INPUTS_LIST 1 -1 INPUTS_ARGS)
list(JOIN INPUTS_ARGS " " INPUTS_ARGS)
else()
set(INPUTS_ARGS "")
endif()
cmake_path(SET INPUTS_FILE "${ImpactX_SOURCE_DIR}/${INPUTS_FILE}")

# get analysis script and optional command-line arguments
separate_arguments(ANALYSIS_LIST UNIX_COMMAND "${analysis_script}")
list(GET ANALYSIS_LIST 0 ANALYSIS_FILE)
cmake_path(SET ANALYSIS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${ANALYSIS_FILE}")
list(LENGTH ANALYSIS_LIST ANALYSIS_LIST_LENGTH)
if(ANALYSIS_LIST_LENGTH GREATER 1)
list(SUBLIST ANALYSIS_LIST 1 -1 ANALYSIS_ARGS)
list(JOIN ANALYSIS_ARGS " " ANALYSIS_ARGS)
else()
set(ANALYSIS_ARGS "")
endif()

# test run
set(THIS_WORKING_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name})
set(THIS_MPI_TEST_EXE)
Expand All @@ -64,10 +88,10 @@ function(add_impactx_test name input is_mpi analysis_script plot_script)
set(THIS_Python_EXE)
if(is_python)
set(THIS_Python_EXE ${Python_EXECUTABLE})
endif()
if(is_python)
# for argparse, do not pass command-line arguments as one quoted string
separate_arguments(INPUTS_ARGS UNIX_COMMAND "${INPUTS_ARGS}")
add_test(NAME ${name}.run
COMMAND ${THIS_MPI_TEST_EXE} ${THIS_Python_EXE} ${ImpactX_SOURCE_DIR}/${input}
COMMAND ${THIS_MPI_TEST_EXE} ${THIS_Python_EXE} ${INPUTS_FILE} ${INPUTS_ARGS}
WORKING_DIRECTORY ${THIS_WORKING_DIR}
)
# TODO:
Expand All @@ -77,12 +101,13 @@ function(add_impactx_test name input is_mpi analysis_script plot_script)
else()
add_test(NAME ${name}.run
COMMAND
${THIS_MPI_TEST_EXE} $<TARGET_FILE:app> ${ImpactX_SOURCE_DIR}/${input}
${THIS_MPI_TEST_EXE} $<TARGET_FILE:app> ${INPUTS_FILE}
amrex.abort_on_unused_inputs=1
amrex.throw_exception = 1
amrex.signal_handling = 0
impactx.always_warn_immediately=1
impactx.abort_on_warning_threshold=low
${INPUTS_ARGS}
WORKING_DIRECTORY ${THIS_WORKING_DIR}
)
endif()
Expand Down Expand Up @@ -210,6 +235,21 @@ add_impactx_test(FODO.MADX.py
examples/fodo/plot_fodo.py
)

# Python: FODO Cell w/ custom linear element #################################
#
add_impactx_test(FODO.userdef
"examples/fodo_userdef/input_fodo_userdef.in impactx.abort_on_warning_threshold=medium"
cemitch99 marked this conversation as resolved.
Show resolved Hide resolved
ON # ImpactX MPI-parallel
examples/fodo_userdef/analysis_fodo.py
examples/fodo_userdef/plot_fodo.py
)
add_impactx_test(FODO.userdef.py
examples/fodo_userdef/run_fodo_userdef.py
OFF # ImpactX MPI-parallel
examples/fodo_userdef/analysis_fodo.py
examples/fodo_userdef/plot_fodo.py
)

# Python: MPI-parallel FODO Cell ##############################################
#
add_impactx_test(FODO.py.MPI
Expand Down Expand Up @@ -1056,3 +1096,19 @@ add_impactx_test(linac-segment.py
examples/linac_segment/analysis_linac_segment.py
OFF # no plot script yet
)

# Iteration of a linear one-turn map #########################################
#
# w/o space charge
add_impactx_test(linear-map
examples/linear_map/input_map.in
ON # ImpactX MPI-parallel
examples/linear_map/analysis_map.py
OFF # no plot script yet
)
add_impactx_test(linear-map.py
examples/linear_map/run_map.py
ON # ImpactX MPI-parallel
examples/linear_map/analysis_map.py
OFF # no plot script yet
)
85 changes: 85 additions & 0 deletions examples/fodo_userdef/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
.. _examples-fodo-userdef:

User-Defined Linear Element
===========================

This implements the same FODO cell as the :ref:`stable FODO cell example <examples-fodo>`.
However, in the example here we define *additional user-defined, custom linear elements* by providing a custom matrix.
ax3l marked this conversation as resolved.
Show resolved Hide resolved

.. note::

Note that generally, if a user-provided linear map is used, the beam transport may not be symplectic.
For an even more general, user-defined element, see :ref:`the FODO Cell example that uses a Programmable Element <examples-fodo-programmable>`.
For more details, see :ref:`this section <usage-workflows-add-element>`.

The matched Twiss parameters at entry are:

* :math:`\beta_\mathrm{x} = 2.82161941` m
* :math:`\alpha_\mathrm{x} = -1.59050035`
* :math:`\beta_\mathrm{y} = 2.82161941` m
* :math:`\alpha_\mathrm{y} = 1.59050035`

We use a 2 GeV electron beam with initial unnormalized rms emittance of 2 nm.

The second moments of the particle distribution after the FODO cell should coincide with the second moments of the particle distribution before the FODO cell, to within the level expected due to noise due to statistical sampling.

In this test, the initial and final values of :math:`\lambda_x`, :math:`\lambda_y`, :math:`\lambda_t`, :math:`\epsilon_x`, :math:`\epsilon_y`, and :math:`\epsilon_t` must agree with nominal values.


Run
---

This example can be run **either** as:

* **Python** script: ``python3 run_fodo_userdef.py`` or
* ImpactX **executable** using an input file: ``impactx input_fodo_userdef.in``

For `MPI-parallel <https://www.mpi-forum.org>`__ runs, prefix these lines with ``mpiexec -n 4 ...`` or ``srun -n 4 ...``, depending on the system.

.. tab-set::

.. tab-item:: Python: Script

.. literalinclude:: run_fodo_userdef.py
:language: python3
:caption: You can copy this file from ``examples/fodo_userdef/run_fodo_userdef.py``.

.. tab-item:: Executable: Input File

.. literalinclude:: input_fodo_userdef.in
:language: ini
:caption: You can copy this file from ``examples/fodo_userdef/input_fodo_userdef.in``.


Analyze
-------

We run the following script to analyze correctness:

.. dropdown:: Script ``analysis_fodo.py``

.. literalinclude:: analysis_fodo.py
:language: python3
:caption: You can copy this file from ``examples/fodo_userdef/analysis_fodo.py``.


Visualize
---------

You can run the following script to visualize the beam evolution over time:

.. dropdown:: Script ``plot_fodo.py``

.. literalinclude:: plot_fodo.py
:language: python3
:caption: You can copy this file from ``examples/fodo_userdef/plot_fodo.py``.

.. figure:: https://user-images.githubusercontent.com/1353258/180287840-8561f6fd-278f-4856-abd8-04fbdb78c8ff.png
:alt: focusing, defocusing and preserved emittance in our FODO cell benchmark.

FODO transversal beam width and emittance evolution

.. figure:: https://user-images.githubusercontent.com/1353258/180287845-eb0210a7-2500-4aa9-844c-67fb094329d3.png
:alt: focusing, defocusing and phase space rotation in our FODO cell benchmark.

FODO transversal beam width and phase space evolution
1 change: 1 addition & 0 deletions examples/fodo_userdef/analysis_fodo.py
59 changes: 59 additions & 0 deletions examples/fodo_userdef/input_fodo_userdef.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
###############################################################################
# Particle Beam(s)
###############################################################################
beam.npart = 10000
beam.units = static
beam.kin_energy = 2.0e3
beam.charge = 1.0e-9
beam.particle = electron
beam.distribution = waterbag_from_twiss
beam.alphaX = -1.5905003499999992
beam.alphaY = 1.5905003499999992
beam.alphaT = 0.0
beam.betaX = 2.8216194100262637
beam.betaY = 2.8216194100262637
beam.betaT = 0.5
beam.emittX = 2e-09
beam.emittY = 2e-09
beam.emittT = 2e-06


###############################################################################
# Beamline: lattice elements and segments
###############################################################################
lattice.elements = monitor drift1 monitor quad1 monitor drift2 monitor quad2 monitor drift1 monitor
lattice.nslice = 25

monitor.type = beam_monitor
monitor.backend = h5

drift1.type = linear_map
drift1.R12 = 0.25 # ds
drift1.R34 = 0.25 # ds
drift1.R56 = 0.25 / 16.6464 # ds / (beta*gamma^2)

quad1.type = quad
quad1.ds = 1.0
quad1.k = 1.0

drift2.type = linear_map
drift2.R12 = 0.5 # ds
drift2.R34 = 0.5 # ds
drift2.R56 = 0.5 / 16.6464 # ds / (beta*gamma^2)

quad2.type = quad
quad2.ds = 1.0
quad2.k = -1.0


###############################################################################
# Algorithms
###############################################################################
algo.particle_shape = 2
algo.space_charge = false


###############################################################################
# Diagnostics
###############################################################################
diag.slice_step_diagnostics = true
1 change: 1 addition & 0 deletions examples/fodo_userdef/plot_fodo.py
Loading
Loading