ImpactX
Loading...
Searching...
No Matches
ChrQuad.H
Go to the documentation of this file.
1/* Copyright 2022-2023 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: Chad Mitchell, Axel Huebl
8 * License: BSD-3-Clause-LBNL
9 */
10#ifndef IMPACTX_CHRQUAD_H
11#define IMPACTX_CHRQUAD_H
12
14#include "mixin/alignment.H"
15#include "mixin/pipeaperture.H"
16#include "mixin/beamoptic.H"
17#include "mixin/thick.H"
19#include "mixin/named.H"
20#include "mixin/nofinalize.H"
21
22#include <AMReX_Extension.H>
23#include <AMReX_Math.H>
24#include <AMReX_REAL.H>
25#include <AMReX_SIMD.H>
26
27#include <cmath>
28#include <stdexcept>
29
30
31namespace impactx::elements
32{
33 struct ChrQuad
34 : public mixin::Named,
35 public mixin::BeamOptic<ChrQuad>,
36 public mixin::LinearTransport<ChrQuad>,
37 public mixin::Thick,
38 public mixin::Alignment,
40 public mixin::NoFinalize,
41 public amrex::simd::Vectorized<amrex::simd::native_simd_size_particlereal>
42 {
43 static constexpr auto type = "ChrQuad";
45
69 amrex::ParticleReal ds,
70 amrex::ParticleReal k,
71 int unit,
72 amrex::ParticleReal dx = 0,
73 amrex::ParticleReal dy = 0,
74 amrex::ParticleReal rotation_degree = 0,
75 amrex::ParticleReal aperture_x = 0,
76 amrex::ParticleReal aperture_y = 0,
77 int nslice = 1,
78 std::optional<std::string> name = std::nullopt
79 )
80 : Named(std::move(name)),
81 Thick(ds, nslice),
82 Alignment(dx, dy, rotation_degree),
84 m_k(k), m_unit(unit)
85 {
86 }
87
89 using BeamOptic::operator();
90
91
99 void compute_constants (RefPart const & refpart)
100 {
101 using namespace amrex::literals; // for _rt and _prt
102 using amrex::Math::powi;
103
104 Alignment::compute_constants(refpart);
105
106 // length of the current slice
107 m_slice_ds = m_ds / nslice();
108
109 // access reference particle values to find beta and gamma
110 m_beta = refpart.beta();
111 m_gamma = refpart.gamma();
112
113 // normalize quad units to MAD-X convention if needed
114 m_g = m_unit == 1 ? m_k / refpart.rigidity_Tm() : m_k;
115
116 m_const1 = 1_prt / (2_prt * powi<3>(m_beta) * powi<2>(m_gamma));
117 }
118
130 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
133 T_Real & AMREX_RESTRICT x,
134 T_Real & AMREX_RESTRICT y,
135 T_Real & AMREX_RESTRICT t,
136 T_Real & AMREX_RESTRICT px,
137 T_Real & AMREX_RESTRICT py,
138 T_Real & AMREX_RESTRICT pt,
139 T_IdCpu & AMREX_RESTRICT idcpu,
140 [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
141 ) const
142 {
143 using namespace amrex::literals; // for _rt and _prt
144 using amrex::Math::powi;
145 using namespace std; // for cmath(float)
146
147 // shift due to alignment errors of the element
148 shift_in(x, y, px, py);
149
150 // access position data
151 T_Real const xout = x;
152 T_Real const yout = y;
153 T_Real const tout = t;
154
155 // compute particle momentum deviation delta + 1
156 T_Real const delta1 = sqrt(1_prt - 2_prt*pt/m_beta + powi<2>(pt));
157 T_Real const delta = delta1 - 1_prt;
158
159 // compute phase advance per unit length in s (in rad/m)
160 // chromatic dependence on delta is included
161 T_Real const omega = sqrt(abs(m_g)/delta1);
162
163 // initialize output values of momenta
164 T_Real pxout = px;
165 T_Real pyout = py;
166 T_Real const ptout = pt;
167
168 // paceholder variables
169 T_Real q1 = xout;
170 T_Real q2 = yout;
171 T_Real p1 = px;
172 T_Real p2 = py;
173
174 if (m_g > 0_prt)
175 {
176 // advance transverse position and momentum (focusing quad)
177 x = cos(omega*m_slice_ds) * xout +
178 sin(omega*m_slice_ds) / (omega*delta1)*px;
179 pxout = -omega * delta1 * sin(omega*m_slice_ds) * xout + cos(omega * m_slice_ds) * px;
180
181 y = cosh(omega*m_slice_ds) * yout +
182 sinh(omega*m_slice_ds) / (omega*delta1)*py;
183 pyout = omega * delta1 * sinh(omega*m_slice_ds) * yout + cosh(omega * m_slice_ds) * py;
184
185 } else if (m_g < 0_prt)
186 {
187 // advance transverse position and momentum (defocusing quad)
188 x = cosh(omega*m_slice_ds) * xout +
189 sinh(omega*m_slice_ds) / (omega*delta1)*px;
190 pxout = omega * delta1 * sinh(omega*m_slice_ds) * xout + cosh(omega * m_slice_ds) * px;
191
192 y = cos(omega*m_slice_ds) * yout +
193 sin(omega*m_slice_ds) / (omega*delta1) * py;
194 pyout = -omega * delta1 * sin(omega*m_slice_ds) * yout + cos(omega * m_slice_ds) * py;
195
196 q1 = yout;
197 q2 = xout;
198 p1 = py;
199 p2 = px;
200 } else
201 {
202 // advance transverse position and momentum (zero focusing strength = drift)
203 x = xout + m_slice_ds * px / delta1;
204 // pxout = px;
205 y = yout + m_slice_ds * py / delta1;
206 // pyout = py;
207 }
208
209
210 // advance longitudinal position and momentum
211
212 if (m_g == 0.0)
213 {
214 // the corresponding symplectic update to t (zero strength = drift)
215 T_Real term = 2_prt * powi<2>(pt) + powi<2>(px) + powi<2>(py);
216 term = 2_prt - 4_prt * m_beta * pt + powi<2>(m_beta) * term;
217 term = -2_prt + powi<2>(m_gamma)*term;
218 term = (-1_prt + m_beta * pt) * term;
219 term = term * m_const1;
220 t = tout - m_slice_ds * (1_prt / m_beta + term / powi<3>(delta1));
221 // ptout = pt;
222
223 } else
224 {
225 // the corresponding symplectic update to t (nonzero strength)
226 T_Real const term = pt + delta / m_beta;
227 T_Real const t0 = tout - term * m_slice_ds / delta1;
228
229 T_Real const w = omega * delta1;
230 T_Real const term1 = -(powi<2>(p2) + powi<2>(q2) * powi<2>(w)) * sinh(2_prt*m_slice_ds*omega);
231 T_Real const term2 = -(powi<2>(p1) - powi<2>(q1) * powi<2>(w)) * sin(2_prt*m_slice_ds*omega);
232 T_Real const term3 = -2_prt * q2 * p2 * w * cosh(2_prt*m_slice_ds*omega);
233 T_Real const term4 = -2_prt * q1 * p1 * w * cos(2_prt*m_slice_ds*omega);
234 T_Real const term5 = 2_prt * omega * (q1*p1*delta1 + q2*p2*delta1
235 -(powi<2>(p1) + powi<2>(p2))*m_slice_ds - (powi<2>(q1)-powi<2>(q2)) * powi<2>(w)*m_slice_ds);
236 t = t0 + (-1_prt+m_beta*pt)
237 / (8_prt*m_beta * powi<3>(delta1)*omega)
238 * (term1+term2+term3+term4+term5);
239 // ptout = pt;
240 }
241
242 // assign updated momenta
243 px = pxout;
244 py = pyout;
245 pt = ptout;
246
247 // apply transverse aperture
248 apply_aperture(x, y, idcpu);
249
250 // undo shift due to alignment errors of the element
251 shift_out(x, y, px, py);
252 }
253
259 void operator() (RefPart & AMREX_RESTRICT refpart) const
260 {
261 using namespace amrex::literals; // for _rt and _prt
262 using amrex::Math::powi;
263
264 // assign input reference particle values
265 amrex::ParticleReal const x = refpart.x;
266 amrex::ParticleReal const px = refpart.px;
267 amrex::ParticleReal const y = refpart.y;
268 amrex::ParticleReal const py = refpart.py;
269 amrex::ParticleReal const z = refpart.z;
270 amrex::ParticleReal const pz = refpart.pz;
271 amrex::ParticleReal const t = refpart.t;
272 amrex::ParticleReal const pt = refpart.pt;
273 amrex::ParticleReal const s = refpart.s;
274
275 // length of the current slice
276 amrex::ParticleReal const slice_ds = m_ds / nslice();
277
278 // assign intermediate parameter
279 amrex::ParticleReal const step = slice_ds / std::sqrt(powi<2>(pt)-1.0_prt);
280
281 // advance position and momentum (straight element)
282 refpart.x = x + step*px;
283 refpart.y = y + step*py;
284 refpart.z = z + step*pz;
285 refpart.t = t - step*pt;
286
287 // advance integrated path length
288 refpart.s = s + slice_ds;
289 }
290
292 using LinearTransport::operator();
293
300 Map6x6
301 transport_map ([[maybe_unused]] RefPart const & AMREX_RESTRICT refpart) const
302 {
303 throw std::runtime_error(std::string(type) + ": Envelope tracking is not yet implemented!");
304 return Map6x6::Identity();
305 }
306
307 amrex::ParticleReal m_k;
308 int m_unit;
309
310 private:
311 // constants that are independent of the individually tracked particle,
312 // see: compute_constants() to refresh
313 amrex::ParticleReal m_slice_ds;
314 amrex::ParticleReal m_beta;
315 amrex::ParticleReal m_gamma;
316 amrex::ParticleReal m_g;
317 amrex::ParticleReal m_const1;
318 };
319
320} // namespace impactx
321
322#endif // IMPACTX_CHRQUAD_H
#define AMREX_FORCE_INLINE
#define AMREX_RESTRICT
#define AMREX_GPU_HOST_DEVICE
#define AMREX_GPU_HOST
constexpr T powi(T x) noexcept
Definition All.H:54
@ s
fixed s as the independent variable
Definition ImpactXParticleContainer.H:37
@ t
fixed t as the independent variable
Definition ImpactXParticleContainer.H:38
amrex::SmallMatrix< amrex::ParticleReal, 6, 6, amrex::Order::F, 1 > Map6x6
Definition CovarianceMatrix.H:20
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Identity() noexcept
Definition ReferenceParticle.H:31
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal rigidity_Tm() const
Definition ReferenceParticle.H:203
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal beta() const
Definition ReferenceParticle.H:94
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal gamma() const
Definition ReferenceParticle.H:82
int m_unit
quadrupole strength in 1/m^2 (or T/m)
Definition ChrQuad.H:308
amrex::ParticleReal m_const1
Definition ChrQuad.H:317
amrex::ParticleReal m_slice_ds
unit specification for quad strength
Definition ChrQuad.H:313
ImpactXParticleContainer::ParticleType PType
Definition ChrQuad.H:44
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 transport_map(RefPart const &AMREX_RESTRICT refpart) const
Definition ChrQuad.H:301
void compute_constants(RefPart const &refpart)
Definition ChrQuad.H:99
amrex::ParticleReal m_gamma
Definition ChrQuad.H:315
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void operator()(T_Real &AMREX_RESTRICT x, T_Real &AMREX_RESTRICT y, T_Real &AMREX_RESTRICT t, T_Real &AMREX_RESTRICT px, T_Real &AMREX_RESTRICT py, T_Real &AMREX_RESTRICT pt, T_IdCpu &AMREX_RESTRICT idcpu, RefPart const &AMREX_RESTRICT refpart) const
Definition ChrQuad.H:132
ChrQuad(amrex::ParticleReal ds, amrex::ParticleReal k, int unit, amrex::ParticleReal dx=0, amrex::ParticleReal dy=0, amrex::ParticleReal rotation_degree=0, amrex::ParticleReal aperture_x=0, amrex::ParticleReal aperture_y=0, int nslice=1, std::optional< std::string > name=std::nullopt)
Definition ChrQuad.H:68
amrex::ParticleReal m_k
Definition ChrQuad.H:307
static constexpr auto type
Definition ChrQuad.H:43
amrex::ParticleReal m_beta
m_ds / nslice();
Definition ChrQuad.H:314
amrex::ParticleReal m_g
Definition ChrQuad.H:316
Definition alignment.H:27
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void shift_out(T_Real &AMREX_RESTRICT x, T_Real &AMREX_RESTRICT y, T_Real &AMREX_RESTRICT px, T_Real &AMREX_RESTRICT py) const
Definition alignment.H:109
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal dy() const
Definition alignment.H:146
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal dx() const
Definition alignment.H:136
Alignment(amrex::ParticleReal dx, amrex::ParticleReal dy, amrex::ParticleReal rotation_degree)
Definition alignment.H:36
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void shift_in(T_Real &AMREX_RESTRICT x, T_Real &AMREX_RESTRICT y, T_Real &AMREX_RESTRICT px, T_Real &AMREX_RESTRICT py) const
Definition alignment.H:78
Definition beamoptic.H:219
Definition lineartransport.H:29
Definition named.H:29
AMREX_GPU_HOST Named(std::optional< std::string > name)
Definition named.H:57
AMREX_FORCE_INLINE std::string name() const
Definition named.H:122
Definition nofinalize.H:22
Definition pipeaperture.H:26
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void apply_aperture(T_Real &AMREX_RESTRICT x, T_Real &AMREX_RESTRICT y, T_IdCpu &AMREX_RESTRICT idcpu) const
Definition pipeaperture.H:59
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal aperture_x() const
Definition pipeaperture.H:90
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal aperture_y() const
Definition pipeaperture.H:101
PipeAperture(amrex::ParticleReal aperture_x, amrex::ParticleReal aperture_y)
Definition pipeaperture.H:32
Definition thick.H:24
Thick(amrex::ParticleReal ds, int nslice)
Definition thick.H:30
amrex::ParticleReal m_ds
Definition thick.H:58
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal ds() const
Definition thick.H:53
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int nslice() const
Definition thick.H:43