Conversation
| from scipy.constants import c as clight | ||
|
|
||
| env = xt.load('b075_2024.09.25.madx') | ||
| env = xt.load('sls.madx') |
There was a problem hiding this comment.
check that this uses the file in test_data folder
There was a problem hiding this comment.
Checked, was incorrect, corrected it.
| from scipy.constants import c as clight | ||
|
|
||
| env = xt.load('b075_2024.09.25.madx') | ||
| env = xt.load('sls.madx') |
There was a problem hiding this comment.
Same, was incorrect, corrected it.
| print("=" * 80) | ||
|
|
||
| # Write results to file | ||
| output_dir = Path("/home/simonfan/cernbox/Documents/Presentations/Section_Meeting_Undulators") |
There was a problem hiding this comment.
This path refers to your computer
| if __name__ == "__main__": | ||
| # Build and run the fitter (file path is parsed inline by FieldFitter) | ||
| fitter = FieldFitter( | ||
| raw_data=file_path, |
There was a problem hiding this comment.
Still taking a path, let's use a DataFrame
There was a problem hiding this comment.
Let's not Taylor the fitter to a specific format
There was a problem hiding this comment.
Removed the "path acceptance" from the FieldFitter. Now only accepts DataFrames. The user has to convert their data to a DataFrame of the correct format.
| splineboris = xt.SplineBoris( | ||
| par_table=param_table, | ||
| s_start=s_start, | ||
| s_end=s_end, | ||
| multipole_order=1, | ||
| n_steps=n_steps, | ||
| ) |
There was a problem hiding this comment.
Give directly the field component derivaritives at edges and average
There was a problem hiding this comment.
Done. We now only store:
Field evaluator still requires the usual polynomial coefficients (or we would have to cut open bpmeth). This makes the fitter much cleaner. Conversion from the above to normal polynomial coefficients happens only at construction of SplineBoris.
| from pathlib import Path | ||
|
|
||
| import sympy as sp | ||
| import bpmeth as bp |
There was a problem hiding this comment.
note down the version of BPMETH you used (as it is still evolving quite a bit, it might be useful for future debugging to be able to go back
There was a problem hiding this comment.
Done. Version seems to be stuck at 0.0.0, so specified the commit hash. Let me know if that should be done differently.
| #include <stddef.h> | ||
| #include <stdio.h> | ||
|
|
||
| #ifndef _SPLINE_B_FIELD_EVAL_H |
There was a problem hiding this comment.
If this is part of the Xtrack source code, the understore should go away
| ] | ||
|
|
||
|
|
||
| class SplineBoris(BeamElement): |
There was a problem hiding this comment.
Add a method to evaluate the field (you can import "_spline_B_field_eval_python.py")
Rename it to have no underscore.
Keep the underscore only for files that are not executed by the user
There was a problem hiding this comment.
Done, do we need a plotter as well?
There was a problem hiding this comment.
Done. Also added a demonstration of the field evaluation in examples/splineboris/005_solenoid.py, which plots the field against the analytical solution (and matches very well).
…nstruction of SplineBoris. Only store f(s_1), f'(s_1), f(s_2), f'(s_2) and the integral over the region in the fit parameters. More consistent and intuitive.
…tor code (generated from the same file as the C field evaluator). SplineBorisSequence selects the correct SplineBoris based on the s-value and calls that element's field evaluator. If s is outside the bounds of the element, it gives an error.
…ata to a dataframe in the correct format first and pass the dataframe instead.
…ld evaluator now present in the SplineBoris(Sequence). Slow, but it works.
…se filter for small multipole components (compared higher-order multipoles to the main field). Was not part of the constructor yet, but now it is.
…pective constructors.
…atives and average. SplineBorisSequence passes normal polynomial coefficients under the hood.
Description
This is a pull request from the splineboris_cleaned branch, which itself is a squashed commit from the splineboris branch (see PR Splineboris#750). The reason for this was to remove large data files from the commit history.
Added the SplineBoris and SplineBorisSequence to the elements.
SplineBoris (
xtrack/beam_elements/elements.py)The SplineBoris is based on a magnetic field description from bpmeth. We describe the field components (Bx, By, Bs) and the derivatives of Bx and By w.r.t. x as fourth order polynomials. These coefficients are ultimately passed to a field-evaluation function that is constructed using bpmeth. SplineBoris accepts the coefficients of these polynomials, as well as the start and end s-coordinate of the element and the number of steps to track particles through the magnetic field. The tracking algorithm is the Boris integrator (see
xtrack/beam_elements/elements_src/splineboris.handxtrack/beam_elements/elements_src/track_splineboris.h), which is written in C, but adopted from the existing Python implementation from BorisSpatialIntegrator. The magnetic field evaluation function is generated fromxtrack/beam_elements/elements_src/_generate_bpmeth_to_C.py. The resulting file isxtrack/beam_elements/elements_src/_spline_B_field_eval.h.SplineBorisSequence (
xtrack/beam_elements/elements.py)The SplineBorisSequence element allows for defining a sequence of SplineBoris elements to describe more complicated field structures. It requires a pandas dataframe of aforementioned polynomial coefficients indexed by their start and end s-coordinates. The SplineBorisSequence constructs a line consisting of individual SplineBoris elements, which can used as a usual line.
FieldFitter (see
xtrack/_temp/field_fitter.py)The required pandas dataframe can be generated using the FieldFitter class, which requires a path to a file of raw data which can either be a csv file or pandas dataframe and is set to df_raw_data. At each$s$ -point in the data, it fits $B_x(x)$ and $B_y(x)$ as a polynomial of deg+1. It then computes successive derivatives of these polynomials and evaluates them at $x=x_0$ , the $x$ -coordinate of the longitudinal axis. The values of these derivatives are stored in df_on_axis_raw.
After df_on_axis_raw is filled, the fitter checks the order-of-magnitude of the derivatives w.r.t. the main field. This tolerance can be set with field_tol, which is$10^-3$ by default. More specifically, it checks if:
Here,$n$ is the order of the derivative and $i \in (x,\ y)$ . If the above is true, it is assumed that the particular combination of $B_i$ and derivative order $n$ has negligible effect on the dynamics and will not be fitted. This serves as a noise-filter.
Then, the FieldFitter finds extrema in the remaining fields/derivatives and defines these extrema as region boundaries. Then, it cuts the regions between the extrema in regions of min_region_size points. The aim of this method is to provide good accuracy around the extrema, as well as in between them.
To each of these regions, a polynomial of degree 4 is fitted. The resulting polynomial coefficients are stored in df_fit_pars, indexed by their magnetic field, derivative, s_start, s_end, idx_start and idx_end. This df_fit_pars can be read directly by SplineBorisSequence to build a sequence of individual SplineBoris elements with the correct set of parameters.
Parameter Ordering
An important point of note: The field evaluation function (_spline_B_field_eval.h) requires the parameters to be ordered as: The coefficients of the Bs polynomial, the coefficients of Bx and subsequent derivatives, the coefficients of By and subsequent derivatives. This parameter ordering is defined inside SplineBoris under the ParamFormat class, which contains several methods to check parameter ordering, as well as the definition of the polynomial used to describe the field. The FieldFitter etc. derive their parameter ordering and naming convention from ParamFormat.
Tests:
test_splineboris_homogeneous_analytic: Tests the SplineBoris for a homogeneous magnetic field at various angles against an analytical solution.test_splineboris_homogeneous_rbend: Tests the SplineBoris for a similar field as in the test above, but against the RBend in Xsuite.test_uniform_solenoid: Tests the SplineBoris for a uniform solenoid against the UniformSolenoid in Xsuite.test_splineboris_solenoid_vs_variable_solenoid: Tests the SplineBoris(Sequence) against the VariableSolenoid in Xsuite.test_splineboris_undulator_vs_boris_spatial: Tests the SplineBoris(Sequence) against the BorisSpatialIntegrator in Xsuite on the same field map.test_splineboris_rotated_undulator_vs_boris_spatial: Rotates the field map from the previous test by 90 degrees and checks that the fit-parameters are also rotated by 90 degrees (that is,test_splineboris_radiation: Tests mean and quantum radiation in a homogeneous magnetic field against an analytical solution.test_splineboris_variable_solenoid_radiation: Similar totest_splineboris_solenoid_vs_variable_solenoid, but tests radiation.test_splineboris_spin_uniform_solenoid: Tests the SplineBoris spin tracking against the UniformSolenoid in Xsuite.test_splineboris_spin_quadrupole: Tests the SplineBoris spin tracking in an ideal quadrupole against the Quadrupole in Xsuite.Examples:
000a_sls_no_undulators: Reference to later examples, twissing the SLS000b_sls_no_undulators_closed_spin: Reference to later examples, SLS with spin tracking001_fieldfitter_basic_usage: Simple example applying the FieldFitter and plotting the results002_homogeneous_rbend: Similar to the RBend test, demonstrates the SplineBoris against the RBend for several "roll" angles003a_undulator_open_spin_tracking: Open spin-tracking through the undulator003b_undulator_open_spin_tracking_radiation: Open spin and radiation tracking through the undulator004a_sls_with_undulators: Inserts the undulators in the SLS and performs a closed orbit Twiss004b_sls_with_undulators_closed_spin: Same as 004a but with spin004c_sls_with_undulators_closed_spin_radiation: Same as 004a but with spin and radiation004d_sls_offset_undulators: Same as 004a, but with the undulators offset004e_sls_offset_undulators_closed_spin: Same as 004d, but with spin tracking005_solenoid: Similar to thetest_splineboris_solenoid_vs_variable_solenoidtest, but with a few plots to show the tracksSmall Fix
In test_data, there used to be two directories, named sls and sls_2.0, which contained madx files with different names, but same content. Removed sls_2.0 and changed all references to the file therein to test_data/sls. These changes occur in examples/tests involving the radiation integrals. The relevant tests pass.
In addition: Added the calculation of the damping partition numbers to the radiation integrals in twiss.py:
$$J_x = 1 - I_{4x}/I_2$$
$$J_y = 1 - I_{4y}/I_2$$
$$J_\epsilon = 2 + I_4/I_2$$
Closes # .
Checklist
Mandatory:
Optional: