ImpactX
Loading...
Searching...
No Matches
particles.H
Go to the documentation of this file.
1/* Copyright 2022-2025 The Regents of the University of California, through Lawrence
2 * Berkeley National Laboratory (subject to receipt of any required
3 * approvals from the U.S. Dept. of Energy). All rights reserved.
4 *
5 * This file is part of ImpactX.
6 *
7 * Authors: Axel Huebl, Chad Mitchell
8 * License: BSD-3-Clause-LBNL
9 */
10#ifndef IMPACTX_TRACKING_PARTICLES_H
11#define IMPACTX_TRACKING_PARTICLES_H
12
13#include "elements/All.H"
17
18#include <AMReX_BLProfiler.H>
19#include <AMReX_ParmParse.H>
20#include <AMReX_Print.H>
21#include <AMReX_REAL.H>
22
23#include <list>
24#include <string>
25#include <variant>
26
27
28namespace impactx
29{
65 template <typename HookFn, typename CollectiveKicks, typename ElementPush>
67 std::list<elements::KnownElements> & lattice,
69 TrackingState & tracking_state,
70 HookFn const & call_hook,
71 CollectiveKicks && collective_kicks,
72 ElementPush && element_push
73 )
74 {
75 bool const forward = tracking_state.forward();
76
77 // periods through the lattice (turns/cycles) and verbosity
78 int num_periods = 1;
79 amrex::ParmParse("lattice").queryAddWithParser("periods", num_periods);
80 int verbose = 1;
81 amrex::ParmParse("impactx").queryAddWithParser("verbose", verbose);
82
83 int & step = tracking_state.m_step;
84
85 // visit one element for all of its space-charge slices
86 auto visit_element = [&] (
87 elements::KnownElements & element_variant,
88 int period
89 )
90 {
91 if (forward)
92 {
93 // update element edge of the reference particle
95
96 // book-keeping: currently visited element reference
97 tracking_state.m_element = &element_variant;
98
99 // optional, user-defined function call
100 call_hook("before_element");
101 }
102 else
103 {
104 // back-tracking: invert this element's map in place so the element
105 // transport below applies the inverse map.
106 std::visit([](auto && element){ element.reverse(); }, element_variant);
107 }
108
109 // number of slices used for the application of space charge
110 int nslice = 1;
111 amrex::ParticleReal slice_ds = 0; // in meters
112 std::visit([&nslice, &slice_ds](auto && element) {
113 nslice = element.nslice();
114 slice_ds = element.ds() / nslice;
115 }, element_variant);
116
117 // sub-steps for space charge within the element
118 for (int s = 0; s < nslice; ++s)
119 {
120 BL_PROFILE("ImpactX::evolve::slice_step");
121 int const slice_step = forward ? s : (nslice - 1 - s);
122
123 if (forward)
124 {
125 step++;
126 if (verbose > 0) {
127 amrex::Print() << "\n++++ Starting step=" << step
128 << " slice_step=" << slice_step;
129 }
130
131 // optional, user-defined function call
132 call_hook("before_slice");
133 }
134
135 // TODO: Strang-split here (#846 / #920)
136 if (forward)
137 {
138 collective_kicks(element_variant, slice_ds);
139 element_push(element_variant, step, period);
140 }
141 else
142 {
143 element_push(element_variant, step, period);
144 collective_kicks(element_variant, slice_ds);
145 }
146 }
147
148 if (forward)
149 {
150 // optional, user-defined function call
151 call_hook("after_element");
152 }
153 else
154 {
155 // restore the forward element map (reverse() is an involution)
156 std::visit([](auto && element){ element.reverse(); }, element_variant);
157 }
158 };
159
160 // loop over channel periods or ring turns
161 for (int p = 0; p < num_periods; ++p)
162 {
163 int const period = forward ? p : (num_periods - 1 - p);
164
165 if (forward)
166 {
167 // book-keeping update
168 tracking_state.m_period = period;
169 tracking_state.m_element = &lattice.front();
170
171 // optional, user-defined function call
172 call_hook("before_period");
173 }
174
175 // loop over lattice elements
176 if (forward)
177 {
178 for (auto & element_variant : lattice)
179 {
180 visit_element(element_variant, period);
181 }
182 }
183 else
184 {
185 for (auto it = lattice.rbegin(); it != lattice.rend(); ++it)
186 {
187 visit_element(*it, period);
188 }
189 }
190
191 // optional, user-defined function call
192 if (forward) { call_hook("after_period"); }
193 }
194
195 if (forward)
196 {
197 // avoid dangling references if users manipulate the lattice
198 tracking_state.set_no_element();
199 }
200 }
201} // namespace impactx
202
203#endif // IMPACTX_TRACKING_PARTICLES_H
#define BL_PROFILE(a)
int queryAddWithParser(std::string_view name, T &ref)
Definition ImpactXParticleContainer.H:136
void SetRefParticleEdge()
Definition ImpactXParticleContainer.cpp:431
amrex_particle_real ParticleReal
std::variant< Empty, Aperture, Buncher, CFbend, ChrAcc, ChrDrift, ChrPlasmaLens, ChrQuad, ConstF, diagnostics::BeamMonitor, DipEdge, Drift, ExactCFbend, ExactDrift, ExactMultipole, ExactQuad, ExactSbend, Kicker, LinearMap, Marker, Multipole, NonlinearLens, PlaneXYRot, PolygonAperture, Programmable, PRot, Quad, QuadEdge, RFCavity, Sbend, ShortRF, SoftSolenoid, SoftQuadrupole, Sol, Source, SpinMap, TaperedPL, ThinDipole > KnownElements
Definition All.H:56
Definition CovarianceMatrixMath.H:25
@ s
fixed s as the independent variable
Definition ImpactXParticleContainer.H:37
void track_lattice_particles(std::list< elements::KnownElements > &lattice, ImpactXParticleContainer &pc, TrackingState &tracking_state, HookFn const &call_hook, CollectiveKicks &&collective_kicks, ElementPush &&element_push)
Definition particles.H:66
Definition TrackingState.H:26
std::optional< elements::KnownElements * > m_element
Definition TrackingState.H:38
bool forward() const
Definition TrackingState.H:45
void set_no_element()
Definition TrackingState.H:43
int m_step
Definition TrackingState.H:32
int m_period
Definition TrackingState.H:35