ImpactX
Loading...
Searching...
No Matches
LinearMap.H
Go to the documentation of this file.
1/* Copyright 2022-2024 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
30
31namespace impactx::elements
32{
33 struct LinearMap
34 : public mixin::Named,
35 public mixin::BeamOptic<LinearMap>,
36 public mixin::LinearTransport<LinearMap>,
37 public mixin::Alignment,
39 public mixin::NoFinalize,
40 public amrex::simd::Vectorized<amrex::simd::native_simd_size_particlereal>
41 {
42 static constexpr auto type = "LinearMap";
44
58 Map6x6 const & R,
62 amrex::ParticleReal rotation_degree = 0,
63 std::optional<std::string> name = std::nullopt
64 )
65 : Named(std::move(name)),
66 Alignment(dx, dy, rotation_degree)
67 {
69 m_ds = ds;
70 }
71
80 bool symplectic () const
81 {
82 using namespace amrex::literals;
83
85 Map6x6 const RT = m_transport_map.transpose();
86 Map6x6 const check = RT * J * m_transport_map;
87 amrex::ParticleReal max_err = 0_prt;
88 for (int i = 1; i <= 6; ++i) {
89 for (int j = 1; j <= 6; ++j) {
90 amrex::ParticleReal const err = std::abs(check(i,j) - J(i,j));
91 max_err = std::max(max_err, err);
92 }
93 }
94
95 amrex::ParticleReal constexpr tol = std::is_same_v<amrex::ParticleReal, float>
96 ? 1.0e-4_prt : 1.0e-10_prt;
97 return max_err <= tol;
98 }
99
109 void reverse ()
110 {
111 if (!symplectic()) {
112 throw std::runtime_error(
113 "LinearMap::reverse: transport map is not symplectic.");
114 }
115
116 Map6x6 const Omega = impactx::symplectic_form();
117
118 // R_inv = Omega^T * R^T * Omega = -Omega * R^T * Omega
119 Map6x6 const RT = m_transport_map.transpose();
120 Map6x6 const R_inv = (-Omega) * RT * Omega;
121 m_transport_map = R_inv;
122 m_ds = -m_ds;
123 }
124
126 using BeamOptic::operator();
127
140 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
143 T_Real & AMREX_RESTRICT x,
144 T_Real & AMREX_RESTRICT y,
145 T_Real & AMREX_RESTRICT t,
146 T_Real & AMREX_RESTRICT px,
147 T_Real & AMREX_RESTRICT py,
148 T_Real & AMREX_RESTRICT pt,
149 [[maybe_unused]] T_IdCpu & AMREX_RESTRICT idcpu,
150 [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
151 ) const
152 {
153 using namespace amrex::literals; // for _rt and _prt
154
155 // shift due to alignment errors of the element
156 shift_in(x, y, px, py);
157
158 // input and output phase space vectors
160 x, px, y, py, t, pt
161 };
162
163 // TODO amrex::SmallMatrix::operator* overloads on T for SIMD*scalar / scalar*SIMD
164 amrex::SmallVector<T_Real, 6, 1> const vectorout = m_transport_map * vectorin;
165
166 // assign updated values
167 x = vectorout(1);
168 px = vectorout(2);
169 y = vectorout(3);
170 py = vectorout(4);
171 t = vectorout(5);
172 pt = vectorout(6);
173
174 // undo shift due to alignment errors of the element
175 shift_out(x, y, px, py);
176 }
177
183 void operator() (RefPart & AMREX_RESTRICT refpart) const
184 {
185 if (m_ds != 0) // Drift forward or backward
186 {
187 using namespace amrex::literals; // for _rt and _prt
188 using amrex::Math::powi;
189
190 // assign input reference particle values
191 amrex::ParticleReal const x = refpart.x;
192 amrex::ParticleReal const px = refpart.px;
193 amrex::ParticleReal const y = refpart.y;
194 amrex::ParticleReal const py = refpart.py;
195 amrex::ParticleReal const z = refpart.z;
196 amrex::ParticleReal const pz = refpart.pz;
197 amrex::ParticleReal const t = refpart.t;
198 amrex::ParticleReal const pt = refpart.pt;
199 amrex::ParticleReal const s = refpart.s;
200
201 // length of the current slice
202 amrex::ParticleReal const slice_ds = m_ds / nslice();
203
204 // assign intermediate parameter
205 amrex::ParticleReal const step = slice_ds / std::sqrt(powi<2>(pt)-1.0_prt);
206
207 // advance position and momentum (drift)
208 refpart.x = x + step*px;
209 refpart.y = y + step*py;
210 refpart.z = z + step*pz;
211 refpart.t = t - step*pt;
212
213 // advance integrated path length
214 refpart.s = s + slice_ds;
215 }
216 // else nothing to do for a zero-length element
217 }
218
224 int nslice () const
225 {
226 return 1;
227 }
228
235 {
236 return m_ds;
237 }
238
239
254 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
257 [[maybe_unused]] T_Real & AMREX_RESTRICT x,
258 [[maybe_unused]] T_Real & AMREX_RESTRICT y,
259 [[maybe_unused]] T_Real & AMREX_RESTRICT t,
260 [[maybe_unused]] T_Real & AMREX_RESTRICT px,
261 [[maybe_unused]] T_Real & AMREX_RESTRICT py,
262 [[maybe_unused]] T_Real & AMREX_RESTRICT pt,
263 [[maybe_unused]] T_Real & AMREX_RESTRICT sx,
264 [[maybe_unused]] T_Real & AMREX_RESTRICT sy,
265 [[maybe_unused]] T_Real & AMREX_RESTRICT sz,
266 [[maybe_unused]] T_IdCpu & AMREX_RESTRICT idcpu,
267 [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
268 ) const
269 {
270 // spin is unaffected
271
272 // phase space push
273 (*this)(x, y, t, px, py, pt, idcpu, refpart);
274
275 }
276
277
279 using LinearTransport::operator();
280
287 Map6x6
288 transport_map ([[maybe_unused]] RefPart const & AMREX_RESTRICT refpart) const
289 {
291 R = m_transport_map;
292
293 return R;
294 }
295
296 Map6x6 m_transport_map; // 6x6 transport map
297 amrex::ParticleReal m_ds; // finite ds allowed for bookkeeping, but we do not allow slicing
298 };
299
300} // namespace impactx
301
303
304#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:56
@ 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:41
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 &AMREX_RESTRICT sx, T_Real &AMREX_RESTRICT sy, T_Real &AMREX_RESTRICT sz, T_IdCpu &AMREX_RESTRICT idcpu, RefPart const &AMREX_RESTRICT refpart) const
Definition LinearMap.H:256
bool symplectic() const
Definition LinearMap.H:80
Map6x6 m_transport_map
Definition LinearMap.H:296
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 transport_map(RefPart const &AMREX_RESTRICT refpart) const
Definition LinearMap.H:288
amrex::ParticleReal m_ds
Definition LinearMap.H:297
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::ParticleReal ds() const
Definition LinearMap.H:234
static constexpr auto type
Definition LinearMap.H:42
ImpactXParticleContainer::ParticleType PType
Definition LinearMap.H:43
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 LinearMap.H:142
LinearMap(Map6x6 const &R, amrex::ParticleReal ds=0, amrex::ParticleReal dx=0, amrex::ParticleReal dy=0, amrex::ParticleReal rotation_degree=0, std::optional< std::string > name=std::nullopt)
Definition LinearMap.H:57
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int nslice() const
Definition LinearMap.H:224
void reverse()
Definition LinearMap.H:109
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:436
Definition lineartransport.H:50
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 spintransport.H:36