ImpactX
Loading...
Searching...
No Matches
LinearMap.H
Go to the documentation of this file.
1/* Copyright 2022-2026 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_ELEMENT_LINEAR_MAP_H
11#define IMPACTX_ELEMENT_LINEAR_MAP_H
12
14#include "mixin/alignment.H"
15#include "mixin/beamoptic.H"
17#include "mixin/spintransport.H"
18#include "mixin/named.H"
19#include "mixin/nofinalize.H"
20
21#include <AMReX_Extension.H>
22#include <AMReX_Math.H>
23#include <AMReX_REAL.H>
24#include <AMReX_SIMD.H>
25
26#include <cmath>
27#include <stdexcept>
28#include <type_traits>
29
30namespace impactx::elements
31{
32 struct LinearMap
33 : public mixin::Named,
34 public mixin::BeamOptic<LinearMap>,
35 public mixin::LinearTransport<LinearMap>,
36 public mixin::Alignment,
38 public mixin::NoFinalize,
39 public amrex::simd::Vectorized<amrex::simd::native_simd_size_particlereal>
40 {
41 static constexpr auto type = "LinearMap";
43
44 static constexpr amrex::ParticleReal DEFAULT_ds = 0;
45
59 Map6x6 const & R,
64 std::optional<std::string> name = DEFAULT_name
65 )
66 : Named(std::move(name)),
67 Alignment(dx, dy, rotation_degree)
68 {
70 m_ds = ds;
71 }
72
81 bool symplectic () const
82 {
83 using namespace amrex::literals;
84
86 Map6x6 const RT = m_transport_map.transpose();
87 Map6x6 const check = RT * J * m_transport_map;
88 amrex::ParticleReal max_err = 0_prt;
89 for (int i = 1; i <= 6; ++i) {
90 for (int j = 1; j <= 6; ++j) {
91 amrex::ParticleReal const err = std::abs(check(i,j) - J(i,j));
92 max_err = std::max(max_err, err);
93 }
94 }
95
96 amrex::ParticleReal constexpr tol = std::is_same_v<amrex::ParticleReal, float>
97 ? 1.0e-4_prt : 1.0e-10_prt;
98 return max_err <= tol;
99 }
100
110 void reverse ()
111 {
112 if (!symplectic()) {
113 throw std::runtime_error(
114 "LinearMap::reverse: transport map is not symplectic.");
115 }
116
117 Map6x6 const Omega = impactx::symplectic_form();
118
119 // R_inv = Omega^T * R^T * Omega = -Omega * R^T * Omega
120 Map6x6 const RT = m_transport_map.transpose();
121 Map6x6 const R_inv = (-Omega) * RT * Omega;
122 m_transport_map = R_inv;
123 m_ds = -m_ds;
124 }
125
127 using BeamOptic::operator();
128
141 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
144 T_Real & AMREX_RESTRICT x,
145 T_Real & AMREX_RESTRICT y,
146 T_Real & AMREX_RESTRICT t,
147 T_Real & AMREX_RESTRICT px,
148 T_Real & AMREX_RESTRICT py,
149 T_Real & AMREX_RESTRICT pt,
150 [[maybe_unused]] T_IdCpu const & AMREX_RESTRICT idcpu,
151 [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
152 ) const
153 {
154 using namespace amrex::literals; // for _rt and _prt
155
156 // input and output phase space vectors
158 x, px, y, py, t, pt
159 };
160
161 // TODO amrex::SmallMatrix::operator* overloads on T for SIMD*scalar / scalar*SIMD
162 amrex::SmallVector<T_Real, 6, 1> const vectorout = m_transport_map * vectorin;
163
164 // assign updated values
165 x = vectorout(1);
166 px = vectorout(2);
167 y = vectorout(3);
168 py = vectorout(4);
169 t = vectorout(5);
170 pt = vectorout(6);
171 }
172
178 void operator() (RefPart & AMREX_RESTRICT refpart) const
179 {
180 if (m_ds != 0) // Drift forward or backward
181 {
182 using namespace amrex::literals; // for _rt and _prt
183 using amrex::Math::powi;
184
185 // assign input reference particle values
186 amrex::ParticleReal const x = refpart.x;
187 amrex::ParticleReal const px = refpart.px;
188 amrex::ParticleReal const y = refpart.y;
189 amrex::ParticleReal const py = refpart.py;
190 amrex::ParticleReal const z = refpart.z;
191 amrex::ParticleReal const pz = refpart.pz;
192 amrex::ParticleReal const t = refpart.t;
193 amrex::ParticleReal const pt = refpart.pt;
194 amrex::ParticleReal const s = refpart.s;
195
196 // length of the current slice
197 amrex::ParticleReal const slice_ds = m_ds / nslice();
198
199 // assign intermediate parameter
200 amrex::ParticleReal const step = slice_ds / std::sqrt(powi<2>(pt)-1.0_prt);
201
202 // advance position and momentum (drift)
203 refpart.x = x + step*px;
204 refpart.y = y + step*py;
205 refpart.z = z + step*pz;
206 refpart.t = t - step*pt;
207
208 // advance integrated path length
209 refpart.s = s + slice_ds;
210 }
211 // else nothing to do for a zero-length element
212 }
213
219 int nslice () const
220 {
221 return 1;
222 }
223
230 {
231 return m_ds;
232 }
233
248 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
251 T_Real & AMREX_RESTRICT x,
252 T_Real & AMREX_RESTRICT y,
253 T_Real & AMREX_RESTRICT t,
254 T_Real & AMREX_RESTRICT px,
255 T_Real & AMREX_RESTRICT py,
256 T_Real & AMREX_RESTRICT pt,
257 [[maybe_unused]] T_Real const & AMREX_RESTRICT sx,
258 [[maybe_unused]] T_Real const & AMREX_RESTRICT sy,
259 [[maybe_unused]] T_Real const & AMREX_RESTRICT sz,
260 T_IdCpu const & AMREX_RESTRICT idcpu,
261 RefPart const & AMREX_RESTRICT refpart
262 ) const
263 {
264 // spin is unaffected
265
266 // phase space push
267 (*this)(x, y, t, px, py, pt, idcpu, refpart);
268
269 }
270
272 using LinearTransport::operator();
273
280 Map6x6
281 transport_map ([[maybe_unused]] RefPart const & AMREX_RESTRICT refpart) const
282 {
284 R = m_transport_map;
285
286 // apply the transverse rotation (roll) alignment error
287 return rotate_aligned_map(R);
288 }
289
290 Map6x6 m_transport_map; // 6x6 transport map
291 amrex::ParticleReal m_ds; // finite ds allowed for bookkeeping, but we do not allow slicing
292 };
293
294} // namespace impactx
295
297
298#endif // IMPACTX_ELEMENT_LINEAR_MAP_H
#define AMREX_FORCE_INLINE
#define AMREX_RESTRICT
#define AMREX_GPU_HOST_DEVICE
#define AMREX_GPU_HOST
#define IMPACTX_PUSH_EXTERN_TEMPLATE(ElementType)
Definition PushAll.H:78
amrex_particle_real ParticleReal
constexpr T powi(T x) noexcept
SmallMatrix< T, N, 1, Order::F, StartIndex > SmallVector
Definition All.H:55
@ 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
Map6x6 symplectic_form()
Definition CovarianceMatrix.H:38
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Identity() noexcept
Definition ReferenceParticle.H:33
Definition LinearMap.H:40
static constexpr amrex::ParticleReal DEFAULT_ds
Definition LinearMap.H:44
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void spin_and_phasespace_push(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_Real const &AMREX_RESTRICT sx, T_Real const &AMREX_RESTRICT sy, T_Real const &AMREX_RESTRICT sz, T_IdCpu const &AMREX_RESTRICT idcpu, RefPart const &AMREX_RESTRICT refpart) const
Definition LinearMap.H:250
bool symplectic() const
Definition LinearMap.H:81
Map6x6 m_transport_map
Definition LinearMap.H:290
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 transport_map(RefPart const &AMREX_RESTRICT refpart) const
Definition LinearMap.H:281
amrex::ParticleReal m_ds
Definition LinearMap.H:291
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal ds() const
Definition LinearMap.H:229
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 const &AMREX_RESTRICT idcpu, RefPart const &AMREX_RESTRICT refpart) const
Definition LinearMap.H:143
static constexpr auto type
Definition LinearMap.H:41
ImpactXParticleContainer::ParticleType PType
Definition LinearMap.H:42
LinearMap(Map6x6 const &R, amrex::ParticleReal ds=DEFAULT_ds, amrex::ParticleReal dx=DEFAULT_dx, amrex::ParticleReal dy=DEFAULT_dy, amrex::ParticleReal rotation_degree=DEFAULT_rotation_degree, std::optional< std::string > name=DEFAULT_name)
Definition LinearMap.H:58
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int nslice() const
Definition LinearMap.H:219
void reverse()
Definition LinearMap.H:110
Definition alignment.H:29
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal dy() const
Definition alignment.H:193
static constexpr amrex::ParticleReal DEFAULT_dy
Definition alignment.H:34
static constexpr amrex::ParticleReal DEFAULT_dx
Definition alignment.H:33
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal dx() const
Definition alignment.H:183
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 rotate_aligned_map(Map6x6 const &R) const
Definition alignment.H:267
Alignment(amrex::ParticleReal dx, amrex::ParticleReal dy, amrex::ParticleReal rotation_degree)
Definition alignment.H:43
static constexpr amrex::ParticleReal DEFAULT_rotation_degree
Definition alignment.H:35
Definition beamoptic.H:567
Definition lineartransport.H:50
Definition named.H:29
static constexpr std::nullopt_t DEFAULT_name
Definition named.H:30
AMREX_GPU_HOST Named(std::optional< std::string > name)
Definition named.H:59
AMREX_FORCE_INLINE std::string name() const
Definition named.H:124
Definition nofinalize.H:22
Definition spintransport.H:36