ImpactX
Loading...
Searching...
No Matches
beamoptic.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: Axel Huebl
8 * License: BSD-3-Clause-LBNL
9 */
10#ifndef IMPACTX_ELEMENTS_MIXIN_BEAMOPTIC_H
11#define IMPACTX_ELEMENTS_MIXIN_BEAMOPTIC_H
12
14#include "particles/PushAll.H"
15
16#include <AMReX_Extension.H> // for AMREX_RESTRICT
17#include <AMReX_REAL.H>
18#include <AMReX_SIMD.H>
19
20#include <type_traits>
21
22
24{
25namespace detail
26{
40 template <typename T_Element>
42 {
45
58 PushSingleParticle (T_Element element,
59 amrex::ParticleReal* AMREX_RESTRICT part_x,
60 amrex::ParticleReal* AMREX_RESTRICT part_y,
61 amrex::ParticleReal* AMREX_RESTRICT part_t,
62 amrex::ParticleReal* AMREX_RESTRICT part_px,
63 amrex::ParticleReal* AMREX_RESTRICT part_py,
64 amrex::ParticleReal* AMREX_RESTRICT part_pt,
65 uint64_t* AMREX_RESTRICT part_idcpu,
66 RefPart ref_part)
67 : m_element(std::move(element)),
68 m_part_x(part_x), m_part_y(part_y), m_part_t(part_t),
69 m_part_px(part_px), m_part_py(part_py), m_part_pt(part_pt),
70 m_part_idcpu(part_idcpu),
71 m_ref_part(std::move(ref_part))
72 {
73 // pre-compute and cache constants that are independent of the
74 // individually tracked particle
75 m_element.compute_constants(m_ref_part);
76 }
77
78 PushSingleParticle () = delete;
81 ~PushSingleParticle () = default;
82
88 void
89 operator() (int i) const
90 {
91 // access SoA Real data
92 // note: an optimizing compiler will eliminate loads of unused parameters
93 amrex::ParticleReal & AMREX_RESTRICT x = m_part_x[i];
94 amrex::ParticleReal & AMREX_RESTRICT y = m_part_y[i];
95 amrex::ParticleReal & AMREX_RESTRICT t = m_part_t[i];
96 amrex::ParticleReal & AMREX_RESTRICT px = m_part_px[i];
97 amrex::ParticleReal & AMREX_RESTRICT py = m_part_py[i];
98 amrex::ParticleReal & AMREX_RESTRICT pt = m_part_pt[i];
99 uint64_t & AMREX_RESTRICT idcpu = m_part_idcpu[i];
100
101 // push through element
102 m_element(x, y, t, px, py, pt, idcpu, m_ref_part);
103 }
104
105#ifdef AMREX_USE_SIMD
110 template<int SIMD_WIDTH>
112 void
114 {
115 using namespace amrex::simd;
116
117 int const i = idx.index;
118
119 // uninitialized memory
126 SIMDIdCpu<decltype(part_x)> part_idcpu;
127
128 // initialize vector registers
129 // TODO stdx::vector_aligned needs alignment guarantees
130 // https://github.com/AMReX-Codes/amrex/issues/4592
131 // https://en.cppreference.com/w/cpp/experimental/simd/simd/copy_from
132 part_x.copy_from(&m_part_x[i], stdx::element_aligned);
133 part_y.copy_from(&m_part_y[i], stdx::element_aligned);
134 part_t.copy_from(&m_part_t[i], stdx::element_aligned);
135 part_px.copy_from(&m_part_px[i], stdx::element_aligned);
136 part_py.copy_from(&m_part_py[i], stdx::element_aligned);
137 part_pt.copy_from(&m_part_pt[i], stdx::element_aligned);
138 part_idcpu.copy_from(&m_part_idcpu[i], stdx::element_aligned);
139
140 // push through element
141 m_element(part_x, part_y, part_t, part_px, part_py, part_pt, part_idcpu, m_ref_part);
142
143 // write back to memory
144 // TODO stdx::vector_aligned needs alignment guarantees
145 // https://github.com/AMReX-Codes/amrex/issues/4592
146 // https://en.cppreference.com/w/cpp/experimental/simd/simd/copy_from
147 if constexpr (is_nth_arg_non_const(&T_Element::template operator()<decltype(part_x), decltype(part_idcpu)>, 0))
148 part_x.copy_to(&m_part_x[i], stdx::element_aligned);
149 if constexpr (is_nth_arg_non_const(&T_Element::template operator()<decltype(part_x), decltype(part_idcpu)>, 1))
150 part_y.copy_to(&m_part_y[i], stdx::element_aligned);
151 if constexpr (is_nth_arg_non_const(&T_Element::template operator()<decltype(part_x), decltype(part_idcpu)>, 2))
152 part_t.copy_to(&m_part_t[i], stdx::element_aligned);
153 if constexpr (is_nth_arg_non_const(&T_Element::template operator()<decltype(part_x), decltype(part_idcpu)>, 3))
154 part_px.copy_to(&m_part_px[i], stdx::element_aligned);
155 if constexpr (is_nth_arg_non_const(&T_Element::template operator()<decltype(part_x), decltype(part_idcpu)>, 4))
156 part_py.copy_to(&m_part_py[i], stdx::element_aligned);
157 if constexpr (is_nth_arg_non_const(&T_Element::template operator()<decltype(part_x), decltype(part_idcpu)>, 5))
158 part_pt.copy_to(&m_part_pt[i], stdx::element_aligned);
159 if constexpr (is_nth_arg_non_const(&T_Element::template operator()<decltype(part_x), decltype(part_idcpu)>, 6))
160 part_idcpu.copy_to(&m_part_idcpu[i], stdx::element_aligned);
161 }
162#endif
163
164 private:
165 T_Element m_element;
166 amrex::ParticleReal* const AMREX_RESTRICT m_part_x;
167 amrex::ParticleReal* const AMREX_RESTRICT m_part_y;
168 amrex::ParticleReal* const AMREX_RESTRICT m_part_t;
169 amrex::ParticleReal* const AMREX_RESTRICT m_part_px;
170 amrex::ParticleReal* const AMREX_RESTRICT m_part_py;
171 amrex::ParticleReal* const AMREX_RESTRICT m_part_pt;
174 };
175
178 template< typename T_Element >
181 RefPart & AMREX_RESTRICT ref_part,
182 T_Element & element
183 ) {
184 const int np = pti.numParticles();
185
186 // preparing access to particle data: SoA of Reals
187 auto& soa_real = pti.GetStructOfArrays().GetRealData();
188 amrex::ParticleReal* const AMREX_RESTRICT part_x = soa_real[RealSoA::x].dataPtr();
189 amrex::ParticleReal* const AMREX_RESTRICT part_y = soa_real[RealSoA::y].dataPtr();
190 amrex::ParticleReal* const AMREX_RESTRICT part_t = soa_real[RealSoA::t].dataPtr();
191 amrex::ParticleReal* const AMREX_RESTRICT part_px = soa_real[RealSoA::px].dataPtr();
192 amrex::ParticleReal* const AMREX_RESTRICT part_py = soa_real[RealSoA::py].dataPtr();
193 amrex::ParticleReal* const AMREX_RESTRICT part_pt = soa_real[RealSoA::pt].dataPtr();
194
195 uint64_t* const AMREX_RESTRICT part_idcpu = pti.GetStructOfArrays().GetIdCPUData().dataPtr();
196
197 detail::PushSingleParticle<T_Element> const pushSingleParticle(
198 element, part_x, part_y, part_t, part_px, part_py, part_pt, part_idcpu, ref_part);
199
200 // loop over beam particles in the box
201#ifdef AMREX_USE_SIMD
203 amrex::ParallelForSIMD<T_Element::simd_width>(np, pushSingleParticle); // TODO: test 2,4,8, ... and handle remainder
204 } else
205#endif
206 {
207 amrex::ParallelFor(np, pushSingleParticle);
208 }
209 }
210} // namespace detail
211
217 template<typename T_Element>
219 {
228 int step,
229 int period
230 )
231 {
232 static_assert(
233 std::is_base_of_v<BeamOptic, T_Element>,
234 "BeamOptic can only be used as a mixin class!"
235 );
236
237 T_Element& element = *static_cast<T_Element*>(this);
238 push_all(pc, element, step, period);
239 }
240
250 RefPart & AMREX_RESTRICT ref_part
251 )
252 {
253 static_assert(
254 std::is_base_of_v<BeamOptic, T_Element>,
255 "BeamOptic can only be used as a mixin class!"
256 );
257
258 T_Element& element = *static_cast<T_Element*>(this);
259 detail::push_all_particles<T_Element>(pti, ref_part, element);
260 }
261 };
262
263} // namespace impactx::elements::mixin
264
265#endif // IMPACTX_ELEMENTS_MIXIN_BEAMOPTIC_H
#define AMREX_FORCE_INLINE
#define AMREX_RESTRICT
#define AMREX_GPU_DEVICE
SoARef GetStructOfArrays() const
Definition ImpactXParticleContainer.H:133
impactx::ParIterSoA iterator
amrex iterator for particle boxes
Definition ImpactXParticleContainer.H:136
std::uint64_t SIMDIdCpu
constexpr bool is_vectorized
constexpr bool is_nth_arg_non_const(R(*)(Args...), int n)
amrex::ParticleReal SIMDParticleReal
std::enable_if_t< std::is_integral_v< T > > ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
AMREX_ATTRIBUTE_FLATTEN_FOR void ParallelForSIMD(N n, L const &f) noexcept
void push_all_particles(ImpactXParticleContainer::iterator &pti, RefPart &AMREX_RESTRICT ref_part, T_Element &element)
Definition beamoptic.H:179
Definition alignment.H:23
@ t
fixed t as the independent variable
Definition ImpactXParticleContainer.H:38
void push_all(ImpactXParticleContainer &pc, T_Element &element, int step, int period, bool omp_parallel=true)
Definition PushAll.H:33
@ nattribs
the number of attributes above (always last)
Definition ImpactXParticleContainer.H:80
@ pt
energy deviation, scaled by speed of light * the magnitude of the reference momentum [unitless] (at f...
Definition ImpactXParticleContainer.H:53
@ y
position in y [m] (at fixed s or t)
Definition ImpactXParticleContainer.H:49
@ t
time-of-flight ct [m] (at fixed s)
Definition ImpactXParticleContainer.H:50
@ px
momentum in x, scaled by the magnitude of the reference momentum [unitless] (at fixed s or t)
Definition ImpactXParticleContainer.H:51
@ nattribs
the number of attributes above (always last)
Definition ImpactXParticleContainer.H:56
@ py
momentum in y, scaled by the magnitude of the reference momentum [unitless] (at fixed s or t)
Definition ImpactXParticleContainer.H:52
@ x
position in x [m] (at fixed s or t)
Definition ImpactXParticleContainer.H:48
Definition ReferenceParticle.H:31
Definition beamoptic.H:219
void operator()(ImpactXParticleContainer &pc, int step, int period)
Definition beamoptic.H:226
amrex::ParticleReal *const AMREX_RESTRICT m_part_px
Definition beamoptic.H:169
amrex::ParticleReal *const AMREX_RESTRICT m_part_t
Definition beamoptic.H:168
T_Element m_element
Definition beamoptic.H:165
amrex::ParticleReal *const AMREX_RESTRICT m_part_pt
Definition beamoptic.H:171
PushSingleParticle(PushSingleParticle &&)=default
uint64_t *const AMREX_RESTRICT m_part_idcpu
Definition beamoptic.H:172
amrex::ParticleReal *const AMREX_RESTRICT m_part_x
Definition beamoptic.H:166
amrex::ParticleReal *const AMREX_RESTRICT m_part_y
Definition beamoptic.H:167
PushSingleParticle(T_Element element, amrex::ParticleReal *AMREX_RESTRICT part_x, amrex::ParticleReal *AMREX_RESTRICT part_y, amrex::ParticleReal *AMREX_RESTRICT part_t, amrex::ParticleReal *AMREX_RESTRICT part_px, amrex::ParticleReal *AMREX_RESTRICT part_py, amrex::ParticleReal *AMREX_RESTRICT part_pt, uint64_t *AMREX_RESTRICT part_idcpu, RefPart ref_part)
Definition beamoptic.H:58
amrex::ParticleTile< amrex::SoAParticle< RealSoA::nattribs, IntSoA::nattribs >, RealSoA::nattribs, IntSoA::nattribs > ParticleTileType
Definition beamoptic.H:44
amrex::ParticleReal *const AMREX_RESTRICT m_part_py
Definition beamoptic.H:170
ImpactXParticleContainer::ParticleType PType
Definition beamoptic.H:43
AMREX_GPU_DEVICE AMREX_FORCE_INLINE void operator()(int i) const
Definition beamoptic.H:89
RefPart m_ref_part
Definition beamoptic.H:173
PushSingleParticle(PushSingleParticle const &)=default