ImpactX
Loading...
Searching...
No Matches
CFbend.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_CFBEND_H
11#define IMPACTX_CFBEND_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 CFbend
34 : public mixin::Named,
35 public mixin::BeamOptic<CFbend>,
36 public mixin::LinearTransport<CFbend>,
37 public mixin::Thick,
38 public mixin::Alignment,
41 // At least on Intel AVX512, there is a small overhead to vectorize this element, see
42 // https://github.com/BLAST-ImpactX/impactx/pull/1002
43 // public amrex::simd::Vectorized<amrex::simd::native_simd_size_particlereal>
44 {
45 static constexpr auto type = "CFbend";
47
66 amrex::ParticleReal ds,
67 amrex::ParticleReal rc,
68 amrex::ParticleReal k,
69 amrex::ParticleReal dx = 0,
70 amrex::ParticleReal dy = 0,
71 amrex::ParticleReal rotation_degree = 0,
72 amrex::ParticleReal aperture_x = 0,
73 amrex::ParticleReal aperture_y = 0,
74 int nslice = 1,
75 std::optional<std::string> name = std::nullopt
76 )
77 : Named(std::move(name)),
78 Thick(ds, nslice),
79 Alignment(dx, dy, rotation_degree),
81 m_rc(rc), m_k(k)
82 {
83 }
84
86 using BeamOptic::operator();
87
95 void compute_constants (RefPart const & refpart)
96 {
97 using namespace amrex::literals; // for _rt and _prt
99
100 Alignment::compute_constants(refpart);
101
102 // length of the current slice
103 amrex::ParticleReal const slice_ds = m_ds / nslice();
104
105 // find beta*gamma^2, beta
106 amrex::ParticleReal const betgam2 = powi<2>(refpart.pt) - 1_prt;
107 amrex::ParticleReal const bet = refpart.beta();
108 amrex::ParticleReal const ibetgam2 = 1_prt / betgam2;
109 amrex::ParticleReal const b2rc2 = powi<2>(bet) * powi<2>(m_rc);
110
111 // update horizontal and longitudinal phase space variables
112 amrex::ParticleReal const gx = m_k + powi<-2>(m_rc);
113 amrex::ParticleReal const omega_x = std::sqrt(std::abs(gx));
114
115 // update vertical phase space variables
116 amrex::ParticleReal const gy = -m_k;
117 amrex::ParticleReal const omega_y = std::sqrt(std::abs(gy));
118
119 // trigonometry
120 auto const [sinx, cosx] = amrex::Math::sincos(omega_x * slice_ds);
121 amrex::ParticleReal const sinhx = std::sinh(omega_x * slice_ds);
122 amrex::ParticleReal const coshx = std::cosh(omega_x * slice_ds);
123 auto const [siny, cosy] = amrex::Math::sincos(omega_y * slice_ds);
124 amrex::ParticleReal const sinhy = std::sinh(omega_y * slice_ds);
125 amrex::ParticleReal const coshy = std::cosh(omega_y * slice_ds);
126
127 amrex::ParticleReal const igbrc = 1_prt / (gx * bet * m_rc);
128 amrex::ParticleReal const iobrc = 1_prt / (omega_x * bet * m_rc);
129 amrex::ParticleReal const igobr = 1_prt / (gx * omega_x * b2rc2);
130
131 m_R11 = gx > 0_prt ? cosx : coshx;
132 m_R12 = gx > 0_prt ? sinx / omega_x : sinhx / omega_x;
133 m_R16 = gx > 0_prt ? -(1_prt - cosx) * igbrc : -(1_prt - coshx) * igbrc;
134 m_R21 = gx > 0_prt ? -omega_x * sinx : omega_x * sinhx;
135 m_R22 = gx > 0_prt ? cosx : coshx;
136 m_R26 = gx > 0_prt ? -sinx * iobrc : -sinhx * iobrc;
137 m_R33 = gy > 0_prt ? cosy : coshy;
138 m_R34 = gy > 0_prt ? siny / omega_y : sinhy / omega_y;
139 m_R43 = gy > 0_prt ? -omega_y * siny : omega_y * sinhy;
140 m_R44 = gy > 0_prt ? cosy : coshy;
141 m_R51 = gx > 0_prt ? sinx * iobrc : sinhx * iobrc;
142 m_R52 = gx > 0_prt ? (1_prt - cosx) * igbrc : (1_prt - coshx) * igbrc;
143 m_R56 = gx > 0_prt ?
144 slice_ds * ibetgam2 + (sinx - omega_x * slice_ds) * igobr :
145 slice_ds * ibetgam2 + (sinhx - omega_x * slice_ds) * igobr;
146 }
147
161 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
164 T_Real & AMREX_RESTRICT x,
165 T_Real & AMREX_RESTRICT y,
166 T_Real & AMREX_RESTRICT t,
167 T_Real & AMREX_RESTRICT px,
168 T_Real & AMREX_RESTRICT py,
169 T_Real & AMREX_RESTRICT pt,
170 T_IdCpu & AMREX_RESTRICT idcpu,
171 [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
172 ) const
173 {
174 using namespace amrex::literals; // for _rt and _prt
175
176 // shift due to alignment errors of the element
177 shift_in(x, y, px, py);
178
179 // initialize output values
180 T_Real xout = x;
181 T_Real yout = y;
182 T_Real tout = t;
183
184 // initialize output values of momenta
185 T_Real pxout = px;
186 T_Real pyout = py;
187 T_Real ptout = pt;
188
189 // update horizontal and longitudinal phase space variables
190 // advance position and momentum: (de)focusing
191 x = m_R11 * xout + m_R12 * px + m_R16 * pt;
192 pxout = m_R21 * xout + m_R22 * px + m_R26 * pt;
193 t = m_R51 * xout + m_R52 * px + m_R56 * pt + tout;
194 ptout = pt;
195
196 // update vertical phase space variables
197 // advance position and momentum (de)focusing
198 y = m_R33 * yout + m_R34 * py;
199 pyout = m_R43 * yout + m_R44 * py;
200
201 // assign updated momenta
202 px = pxout;
203 py = pyout;
204 pt = ptout;
205
206 // apply transverse aperture
207 apply_aperture(x, y, idcpu);
208
209 // undo shift due to alignment errors of the element
210 shift_out(x, y, px, py);
211 }
212
218 void operator() (RefPart & AMREX_RESTRICT refpart) const
219 {
220 using namespace amrex::literals; // for _rt and _prt
221 using amrex::Math::powi;
222
223 // assign input reference particle values
224 amrex::ParticleReal const x = refpart.x;
225 amrex::ParticleReal const px = refpart.px;
226 amrex::ParticleReal const y = refpart.y;
227 amrex::ParticleReal const py = refpart.py;
228 amrex::ParticleReal const z = refpart.z;
229 amrex::ParticleReal const pz = refpart.pz;
230 amrex::ParticleReal const t = refpart.t;
231 amrex::ParticleReal const pt = refpart.pt;
232 amrex::ParticleReal const s = refpart.s;
233
234 // length of the current slice
235 amrex::ParticleReal const slice_ds = m_ds / nslice();
236
237 // assign intermediate parameter
238 amrex::ParticleReal const theta = slice_ds/m_rc;
239 amrex::ParticleReal const B = std::sqrt(powi<2>(pt)-1.0_prt)/m_rc;
240
241 // calculate expensive terms once
242 auto const [sin_theta, cos_theta] = amrex::Math::sincos(theta);
243
244 // advance position and momentum (bend)
245 refpart.px = px*cos_theta - pz*sin_theta;
246 refpart.py = py;
247 refpart.pz = pz*cos_theta + px*sin_theta;
248 refpart.pt = pt;
249
250 refpart.x = x + (refpart.pz - pz)/B;
251 refpart.y = y + (theta/B)*py;
252 refpart.z = z - (refpart.px - px)/B;
253 refpart.t = t - (theta/B)*pt;
254
255 // advance integrated path length
256 refpart.s = s + slice_ds;
257 }
258
260 using LinearTransport::operator();
261
268 Map6x6
269 transport_map ([[maybe_unused]] RefPart const & AMREX_RESTRICT refpart) const
270 {
271 using namespace amrex::literals; // for _rt and _prt
272 using amrex::Math::powi;
273
274 // length of the current slice
275 amrex::ParticleReal const slice_ds = m_ds / nslice();
276
277 // find beta*gamma^2, beta
278 amrex::ParticleReal const betgam2 = powi<2>(refpart.pt) - 1_prt;
279 amrex::ParticleReal const bet = refpart.beta();
280 amrex::ParticleReal const ibetgam2 = 1_prt / betgam2;
281 amrex::ParticleReal const b2rc2 = powi<2>(bet) * powi<2>(m_rc);
282
283 // update horizontal and longitudinal phase space variables
284 amrex::ParticleReal const gx = m_k + powi<-2>(m_rc);
285 amrex::ParticleReal const omega_x = std::sqrt(std::abs(gx));
286
287 // update vertical phase space variables
288 amrex::ParticleReal const gy = -m_k;
289 amrex::ParticleReal const omega_y = std::sqrt(std::abs(gy));
290
291 // trigonometry
292 auto const [sinx, cosx] = amrex::Math::sincos(omega_x * slice_ds);
293 amrex::ParticleReal const sinhx = std::sinh(omega_x * slice_ds);
294 amrex::ParticleReal const coshx = std::cosh(omega_x * slice_ds);
295 auto const [siny, cosy] = amrex::Math::sincos(omega_y * slice_ds);
296 amrex::ParticleReal const sinhy = std::sinh(omega_y * slice_ds);
297 amrex::ParticleReal const coshy = std::cosh(omega_y * slice_ds);
298
299 amrex::ParticleReal const igbrc = 1_prt / (gx * bet * m_rc);
300 amrex::ParticleReal const iobrc = 1_prt / (omega_x * bet * m_rc);
301 amrex::ParticleReal const igobr = 1_prt / (gx * omega_x * b2rc2);
302
303 // initialize linear map matrix elements
305
306 R(1,1) = gx > 0_prt ? cosx : coshx;
307 R(1,2) = gx > 0_prt ? sinx / omega_x : sinhx / omega_x;
308 R(1,6) = gx > 0_prt ? -(1_prt - cosx) * igbrc : -(1_prt - coshx) * igbrc;
309 R(2,1) = gx > 0_prt ? -omega_x * sinx : omega_x * sinhx;
310 R(2,2) = gx > 0_prt ? cosx : coshx;
311 R(2,6) = gx > 0_prt ? -sinx * iobrc : -sinhx * iobrc;
312 R(3,3) = gy > 0_prt ? cosy : coshy;
313 R(3,4) = gy > 0_prt ? siny / omega_y : sinhy / omega_y;
314 R(4,3) = gy > 0_prt ? -omega_y * siny : omega_y * sinhy;
315 R(4,4) = gy > 0_prt ? cosy : coshy;
316 R(5,1) = gx > 0_prt ? sinx * iobrc : sinhx * iobrc;
317 R(5,2) = gx > 0_prt ? (1_prt - cosx) * igbrc : (1_prt - coshx) * igbrc;
318 R(5,6) = gx > 0_prt ?
319 slice_ds * ibetgam2 + (sinx - omega_x * slice_ds) * igobr :
320 slice_ds * ibetgam2 + (sinhx - omega_x * slice_ds) * igobr;
321
322 return R;
323 }
324
325 amrex::ParticleReal m_rc;
326 amrex::ParticleReal m_k;
327
328 private:
329 // constants that are independent of the individually tracked particle,
330 // see: compute_constants() to refresh
331 amrex::ParticleReal m_R11, m_R12, m_R16, m_R21, m_R22, m_R26, m_R33, m_R34, m_R43, m_R44, m_R51, m_R52, m_R56;
332 };
333
334} // namespace impactx
335
336#endif // IMPACTX_CFBEND_H
#define AMREX_FORCE_INLINE
#define AMREX_RESTRICT
#define AMREX_GPU_HOST_DEVICE
#define AMREX_GPU_HOST
__host__ __device__ std::pair< double, double > sincos(double x)
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::ParticleReal pt
energy, normalized by rest energy
Definition ReferenceParticle.H:40
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal beta() const
Definition ReferenceParticle.H:94
amrex::ParticleReal m_R21
Definition CFbend.H:331
void compute_constants(RefPart const &refpart)
Definition CFbend.H:95
amrex::ParticleReal m_R43
Definition CFbend.H:331
static constexpr auto type
Definition CFbend.H:45
amrex::ParticleReal m_R11
quadrupole strength in m^(-2)
Definition CFbend.H:331
amrex::ParticleReal m_rc
Definition CFbend.H:325
amrex::ParticleReal m_R44
Definition CFbend.H:331
CFbend(amrex::ParticleReal ds, amrex::ParticleReal rc, amrex::ParticleReal k, 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 CFbend.H:65
amrex::ParticleReal m_R56
Definition CFbend.H:331
ImpactXParticleContainer::ParticleType PType
Definition CFbend.H:46
amrex::ParticleReal m_R33
Definition CFbend.H:331
amrex::ParticleReal m_k
bend radius in m
Definition CFbend.H:326
amrex::ParticleReal m_R16
Definition CFbend.H:331
amrex::ParticleReal m_R52
Definition CFbend.H:331
amrex::ParticleReal m_R26
Definition CFbend.H:331
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 CFbend.H:163
amrex::ParticleReal m_R51
Definition CFbend.H:331
amrex::ParticleReal m_R34
Definition CFbend.H:331
amrex::ParticleReal m_R12
Definition CFbend.H:331
amrex::ParticleReal m_R22
Definition CFbend.H:331
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 transport_map(RefPart const &AMREX_RESTRICT refpart) const
Definition CFbend.H:269
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