ImpactX
Loading...
Searching...
No Matches
ChrPlasmaLens.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_CHRPLASMALENS_H
11#define IMPACTX_CHRPLASMALENS_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{
34 : public mixin::Named,
35 public mixin::BeamOptic<ChrPlasmaLens>,
36 public mixin::LinearTransport<ChrPlasmaLens>,
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 = "ChrPlasmaLens";
45
67 amrex::ParticleReal ds,
68 amrex::ParticleReal k,
69 int unit,
70 amrex::ParticleReal dx = 0,
71 amrex::ParticleReal dy = 0,
72 amrex::ParticleReal rotation_degree = 0,
73 amrex::ParticleReal aperture_x = 0,
74 amrex::ParticleReal aperture_y = 0,
75 int nslice = 1,
76 std::optional<std::string> name = std::nullopt
77 )
78 : Named(std::move(name)),
79 Thick(ds, nslice),
80 Alignment(dx, dy, rotation_degree),
82 m_k(k), m_unit(unit)
83 {
84 }
85
87 using BeamOptic::operator();
88
96 void compute_constants (RefPart const & refpart)
97 {
98 using namespace amrex::literals; // for _rt and _prt
100
101 Alignment::compute_constants(refpart);
102
103 // length of the current slice
104 m_slice_ds = m_ds / nslice();
105
106 // access reference particle values to find beta and gamma
107 m_beta = refpart.beta();
108 m_gamma = refpart.gamma();
109
110 // normalize focusing strength units to MAD-X convention if needed
111 m_g = m_unit == 1 ? m_k / refpart.rigidity_Tm() : m_k;
112
113 //For m_g=0 time propagation
114 m_const1 = 1_prt / (2_prt * powi<3>(m_beta) * powi<2>(m_gamma));
115 }
116
128 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
131 T_Real & AMREX_RESTRICT x,
132 T_Real & AMREX_RESTRICT y,
133 T_Real & AMREX_RESTRICT t,
134 T_Real & AMREX_RESTRICT px,
135 T_Real & AMREX_RESTRICT py,
136 T_Real & AMREX_RESTRICT pt,
137 T_IdCpu & AMREX_RESTRICT idcpu,
138 [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
139 ) const
140 {
141 using namespace amrex::literals; // for _rt and _prt
142 using amrex::Math::powi;
143 using namespace std; // for cmath(float)
144
145 // shift due to alignment errors of the element
146 shift_in(x, y, px, py);
147
148 // compute particle momentum deviation delta + 1
149 T_Real const delta1 = sqrt(1_prt - 2_prt*pt/m_beta + powi<2>(pt));
150 T_Real const delta = delta1 - 1_prt;
151
152 // compute phase advance per unit length in s (in rad/m)
153 // chromatic dependence on delta is included
154 T_Real const omega = sqrt(abs(m_g)/delta1);
155
156 // initialize output values
157 T_Real xout = x;
158 T_Real yout = y;
159 T_Real tout = t;
160
161 // initialize output values of momenta
162 T_Real pxout = px;
163 T_Real pyout = py;
164 T_Real const ptout = pt;
165
166 // placeholder variables -- canonical position and momentum
167 T_Real q1 = x;
168 T_Real q2 = y;
169 T_Real p1 = px;
170 T_Real p2 = py;
171
172 if (m_g > 0_prt)
173 {
174 auto const [sin_ods, cos_ods] = amrex::Math::sincos(omega*m_slice_ds);
175
176 // advance transverse position and momentum (focusing)
177 xout = cos_ods * x + sin_ods / (omega * delta1) * px;
178 pxout = -omega * delta1 * sin_ods * x + cos_ods * px;
179
180 yout = cos_ods * y + sin_ods / (omega * delta1) * py;
181 pyout = -omega * delta1 * sin_ods * y + cos_ods * py;
182
183 // the corresponding symplectic update to t (focusing both x and y)
184 T_Real const term = pt + delta/m_beta;
185 T_Real const t0 = t - term*m_slice_ds/delta1;
186
187 T_Real const w = omega*delta1;
188 T_Real const term1 = -(powi<2>(p2) - powi<2>(q2) * powi<2>(w)) * sin(2_prt*m_slice_ds*omega);
189 T_Real const term2 = -(powi<2>(p1) - powi<2>(q1) * powi<2>(w)) * sin(2_prt*m_slice_ds*omega);
190 T_Real const term3 = -2_prt * q2 * p2 * w * cos(2_prt*m_slice_ds*omega);
191 T_Real const term4 = -2_prt * q1 * p1 * w * cos(2_prt*m_slice_ds*omega);
192 T_Real const term5 = 2_prt * omega * (q1*p1*delta1 + q2*p2*delta1
193 -(powi<2>(p1) + powi<2>(p2))*m_slice_ds - (powi<2>(q1) + powi<2>(q2)) * powi<2>(w)*m_slice_ds);
194 tout = t0 + (-1_prt+m_beta*pt)
195 / (8_prt*m_beta * powi<3>(delta1)*omega)
196 * (term1+term2+term3+term4+term5);
197
198 }
199 else if (m_g < 0_prt)
200 {
201 auto const sinh_ods = sinh(omega*m_slice_ds);
202 auto const cosh_ods = cosh(omega*m_slice_ds);
203
204 // advance transverse position and momentum (defocusing)
205 xout = cosh_ods * x + sinh_ods / (omega * delta1) * px;
206 pxout = +omega * delta1 * sinh_ods * x + cosh_ods * px;
207
208 yout = cosh_ods * y + sinh_ods / (omega * delta1) * py;
209 pyout = +omega * delta1 * sinh_ods * y + cosh_ods * py;
210
211 // the corresponding symplectic update to t (defocusing both x and y)
212 T_Real const term = pt + delta/m_beta;
213 T_Real const t0 = t - term*m_slice_ds/delta1;
214
215 T_Real const w = omega*delta1;
216 T_Real const term1 = -(powi<2>(p2) + powi<2>(q2) * powi<2>(w)) * sinh(2_prt*m_slice_ds*omega);
217 T_Real const term2 = -(powi<2>(p1) + powi<2>(q1) * powi<2>(w)) * sinh(2_prt*m_slice_ds*omega);
218 T_Real const term3 = -2_prt * q2 * p2 * w * cosh(2_prt*m_slice_ds*omega);
219 T_Real const term4 = -2_prt * q1 * p1 * w * cosh(2_prt*m_slice_ds*omega);
220 T_Real const term5 = 2_prt * omega * (q1*p1*delta1 + q2*p2*delta1
221 -(powi<2>(p1) + powi<2>(p2))*m_slice_ds - (powi<2>(q1) + powi<2>(q2)) * powi<2>(w)*m_slice_ds);
222 tout = t0 + (-1_prt+m_beta*pt)
223 / (8_prt*m_beta * powi<3>(delta1)*omega)
224 * (term1+term2+term3+term4+term5);
225 }
226 else {
227 xout = x + px*m_slice_ds / delta1;
228 pxout = px;
229
230 yout = y + py*m_slice_ds / delta1;
231 pyout = py;
232
233 // the corresponding symplectic update to t (zero strength = drift),
234 // avoiding division by 0
235 T_Real term = 2_prt * powi<2>(pt) + powi<2>(px) + powi<2>(py);
236 term = 2_prt - 4_prt * m_beta * pt + powi<2>(m_beta) * term;
237 term = -2_prt + powi<2>(m_gamma)*term;
238 term = (-1_prt + m_beta * pt) * term;
239 term = term * m_const1;
240 tout = t - m_slice_ds * (1_prt / m_beta + term / powi<3>(delta1));
241 }
242 // advance longitudinal position and momentum
243
244
245 // assign updated position & momenta
246 x = xout;
247 y = yout;
248 t = tout;
249 px = pxout;
250 py = pyout;
251 pt = ptout;
252
253 // apply transverse aperture
254 apply_aperture(x, y, idcpu);
255
256 // undo shift due to alignment errors of the element
257 shift_out(x, y, px, py);
258 }
259
265 void operator() (RefPart & AMREX_RESTRICT refpart) const
266 {
267 using namespace amrex::literals; // for _rt and _prt
268 using amrex::Math::powi;
269
270 // assign input reference particle values
271 amrex::ParticleReal const x = refpart.x;
272 amrex::ParticleReal const px = refpart.px;
273 amrex::ParticleReal const y = refpart.y;
274 amrex::ParticleReal const py = refpart.py;
275 amrex::ParticleReal const z = refpart.z;
276 amrex::ParticleReal const pz = refpart.pz;
277 amrex::ParticleReal const t = refpart.t;
278 amrex::ParticleReal const pt = refpart.pt;
279 amrex::ParticleReal const s = refpart.s;
280
281 // length of the current slice
282 amrex::ParticleReal const slice_ds = m_ds / nslice();
283
284 // assign intermediate parameter
285 amrex::ParticleReal const step = slice_ds / std::sqrt(powi<2>(pt)-1.0_prt);
286
287 // advance position and momentum (straight element)
288 refpart.x = x + step*px;
289 refpart.y = y + step*py;
290 refpart.z = z + step*pz;
291 refpart.t = t - step*pt;
292
293 // advance integrated path length
294 refpart.s = s + slice_ds;
295 }
296
298 using LinearTransport::operator();
299
306 Map6x6
307 transport_map ([[maybe_unused]] RefPart const & AMREX_RESTRICT refpart) const
308 {
309 throw std::runtime_error(std::string(type) + ": Envelope tracking is not yet implemented!");
310 return Map6x6::Identity();
311 }
312
313 amrex::ParticleReal m_k;
314 int m_unit;
315
316 private:
317 // constants that are independent of the individually tracked particle,
318 // see: compute_constants() to refresh
319 amrex::ParticleReal m_slice_ds;
320 amrex::ParticleReal m_beta;
321 amrex::ParticleReal m_gamma;
322 amrex::ParticleReal m_g;
323 amrex::ParticleReal m_const1;
324 };
325
326} // namespace impactx
327
328#endif // IMPACTX_CHRPLASMALENS_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_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
focusing strength in 1/m^2 (or T/m)
Definition ChrPlasmaLens.H:314
static constexpr auto type
Definition ChrPlasmaLens.H:43
void compute_constants(RefPart const &refpart)
Definition ChrPlasmaLens.H:96
amrex::ParticleReal m_beta
m_ds / nslice();
Definition ChrPlasmaLens.H:320
amrex::ParticleReal m_k
Definition ChrPlasmaLens.H:313
amrex::ParticleReal m_const1
Definition ChrPlasmaLens.H:323
amrex::ParticleReal m_gamma
Definition ChrPlasmaLens.H:321
amrex::ParticleReal m_g
Definition ChrPlasmaLens.H:322
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 ChrPlasmaLens.H:130
ChrPlasmaLens(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 ChrPlasmaLens.H:66
amrex::ParticleReal m_slice_ds
unit specification for focusing strength
Definition ChrPlasmaLens.H:319
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 transport_map(RefPart const &AMREX_RESTRICT refpart) const
Definition ChrPlasmaLens.H:307
ImpactXParticleContainer::ParticleType PType
Definition ChrPlasmaLens.H:44
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