ImpactX
Loading...
Searching...
No Matches
PolygonAperture.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: Eric G. Stern, Chad Mitchell, Axel Huebl
8 * License: BSD-3-Clause-LBNL
9 */
10#ifndef IMPACTX_POLYGONAPERTURE_H
11#define IMPACTX_POLYGONAPERTURE_H
12
13
15#include "mixin/alignment.H"
16#include "mixin/beamoptic.H"
17#include "mixin/thin.H"
19#include "mixin/named.H"
20#include "mixin/nofinalize.H"
21
22#include <ablastr/constant.H>
23
24#include <AMReX_Extension.H>
25#include <AMReX_Math.H>
26#include <AMReX_REAL.H>
27#include <AMReX_SIMD.H>
28
29#include <cmath>
30#include <map>
31#include <stdexcept>
32#include <vector>
33
34
35namespace impactx::elements
36{
37
45 {
47 inline int next_id = 0;
48
50 inline std::map<int, std::vector<amrex::ParticleReal>> h_vertices_x = {};
52 inline std::map<int, std::vector<amrex::ParticleReal>> h_vertices_y = {};
53
55 inline std::map<int, amrex::Gpu::DeviceVector<amrex::ParticleReal>> d_vertices_x = {};
57 inline std::map<int, amrex::Gpu::DeviceVector<amrex::ParticleReal>> d_vertices_y = {};
58
59 } // namespace PolygonApertureData
60
62 : public mixin::Named,
63 public mixin::BeamOptic<PolygonAperture>,
64 public mixin::LinearTransport<PolygonAperture>,
65 public mixin::Thin,
66 public mixin::Alignment,
68 // public amrex::simd::Vectorized<amrex::simd::native_simd_size_particlereal>
69 {
70 static constexpr auto type = "PolygonAperture";
72
73 enum Action
74 {
77 };
78
79 static std::string
80 action_name (Action const & action);
81
99 std::vector< amrex::ParticleReal> vertices_x,
100 std::vector< amrex::ParticleReal> vertices_y,
101 amrex::ParticleReal min_radius2,
102 amrex::ParticleReal repeat_x,
103 amrex::ParticleReal repeat_y,
104 bool shift_odd_x,
105 Action action,
106 amrex::ParticleReal dx = 0,
107 amrex::ParticleReal dy = 0,
108 amrex::ParticleReal rotation_degree = 0,
109 std::optional<std::string> name = std::nullopt
110 )
111 //
112 : Named(std::move(name)),
113 Alignment(dx, dy, rotation_degree),
114 m_action(action), m_repeat_x(repeat_x), m_repeat_y(repeat_y), m_shift_odd_x(shift_odd_x),
115 m_id(PolygonApertureData::next_id),
116 m_min_radius2(min_radius2) {
117
118 using namespace amrex::literals; // for _rt and _prt
119
120 if (m_repeat_y == 0_prt && m_shift_odd_x) {
121 throw std::runtime_error("PolygonAperture: shift_odd_x can only be used if repeat_y is set, too!");
122 }
123
124 // next created MulPolygonAperture has another id for its data
126
127 m_nvert = vertices_x.size();
128 // there must be the same number of horizontal and vertical vertices
129 if (m_nvert != vertices_y.size()) {
130 throw std::runtime_error("PolygonAperture: horizontal and vertical vertices arrays must have same length!");
131 }
132
133 // verify that first and last vertices are the same
134 if ((vertices_x[0] != vertices_x[m_nvert-1]) ||
135 (vertices_y[0] != vertices_y[m_nvert-1])) {
136 throw std::runtime_error("PolygonAperture: first and last vertex must be exactly equal!");
137 }
138
139 // host data
144
145 // device data
149 vertices_x.begin(), vertices_x.end(),
152 vertices_y.begin(), vertices_y.end(),
155
156 // low-level objects we can use on device
159
160 }
161
163 using BeamOptic::operator();
164
172 void compute_constants ([[maybe_unused]] RefPart const & refpart)
173 {
174 Alignment::compute_constants(refpart);
175 }
176
189 template<typename T_Real=amrex::ParticleReal, typename T_IdCpu=uint64_t>
192 T_Real & AMREX_RESTRICT x,
193 T_Real & AMREX_RESTRICT y,
194 [[maybe_unused]] T_Real & AMREX_RESTRICT t,
195 T_Real & AMREX_RESTRICT px,
196 T_Real & AMREX_RESTRICT py,
197 [[maybe_unused]] T_Real & AMREX_RESTRICT pt,
198 T_IdCpu & AMREX_RESTRICT idcpu,
199 [[maybe_unused]] RefPart const & AMREX_RESTRICT refpart
200 ) const
201 {
202 // a complex type with two T_Real
204
205 using namespace amrex::literals; // for _rt and _prt
206 namespace stdx = amrex::simd::stdx;
207 using amrex::Math::powi;
208 using std::fmod;
209 using std::abs;
210 using amrex::arg;
211 using VBool = decltype(x>0_prt);
212
213 // shift due to alignment errors of the element
214 shift_in(x, y, px, py);
215
216 // define intermediate variables
217 amrex::ParticleReal const dx = m_repeat_x * 0.5_prt;
218 amrex::ParticleReal const dy = m_repeat_y * 0.5_prt;
219
220 // shift every 2nd row by half of m_repeat_x
221 T_Real sx = x;
222 T_Real const sy = y;
223 VBool const shift_x = m_shift_odd_x == false ? VBool{false} : fmod(floor((y+dy)/m_repeat_y), 2) != T_Real{0};
224#ifdef AMREX_USE_SIMD
225 amrex::simd::stdx::where(shift_x, sx) += dx;
226#else
227 sx += shift_x ? dx : 0_prt;
228#endif
229
230 // if the aperture is periodic, shift sx,sy coordinates to the fundamental domain
231 T_Real u = (m_repeat_x == 0_prt) ? sx : (fmod(abs(sx)+dx, m_repeat_x)-dx);
232 T_Real v = (m_repeat_y == 0_prt) ? sy : (fmod(abs(sy)+dy, m_repeat_y)-dy);
233
234 // compare against the aperture boundary
235 VBool inside_aperture;
236
237 // calculate whether point is inside polygon or not
238 T_Real r2 = powi<2>(u) + powi<2>(v);
239 // are we inside the minimum radius?
240 if (r2 < m_min_radius2) {
241 inside_aperture = VBool(true); // yes!
242 } else{
243
244#if AMREX_DEVICE_COMPILE
245 amrex::ParticleReal* vertices_x = m_vertices_x_d_data;
246 amrex::ParticleReal* vertices_y = m_vertices_y_d_data;
247#else
248 amrex::ParticleReal* vertices_x = m_vertices_x_h_data;
249 amrex::ParticleReal* vertices_y = m_vertices_y_h_data;
250#endif
251
252 // no, we have to do the polygon calculation
253
254 /*
255 * The algorithms works as follows:
256 *
257 * You have a polygon (in 2D) described by points V_1, ..., V_n arranged
258 * counter-clockwise. You have a particle with coordinates w = (x,y).
259 * Get the difference vector from the particle to each of
260 * the vertices in turn expressed as a complex number z_k, k=1,n. Now the angle
261 * between the particle and vertex i and vertex j is
262 *
263 * theta_{ij} = arg(\bar{z_i} z_j)
264 * This is easily demonstrated by expressing the complex numbers in exponential
265 * polar notation and also the angle is positive in the counter-clockwise direction.
266 *
267 * Take the sum of all the angles. The angle sum for particle inside the polygon will
268 * be 2 pi. The sum of angles of particle outside of the polygon will be 0.
269 */
270 T_Real thetasum = 0.0;
271 Complex v1conj, v2;
272
273 for (size_t i = 0; i < m_nvert-1; ++i) {
274 v1conj = Complex(u - vertices_x[i], -(v-vertices_y[i]));
275 v2 = Complex(u - vertices_x[i+1], v-vertices_y[i+1]);
276 thetasum += arg(v2 * v1conj);
277 }
278 inside_aperture = abs(thetasum/(2*ablastr::constant::math::pi)) > 1.0e-12_prt;
279 }
280
281 // For transmit (default): invalidate if outside aperture
282 // For absorb: invalidate if inside aperture
283 auto const invalid_mask = m_action == Action::transmit ? !inside_aperture : inside_aperture;
285
286 // undo shift due to alignment errors of the element
287 shift_out(x, y, px, py);
288 }
289
291 using Thin::operator();
292
294 using LinearTransport::operator();
295
302 Map6x6
303 transport_map ([[maybe_unused]] RefPart const & AMREX_RESTRICT refpart) const
304 {
305 throw std::runtime_error(std::string(type) + ": Envelope tracking is not yet implemented!");
306 return Map6x6::Identity();
307 }
308
310 // class data
311
313 amrex::ParticleReal m_repeat_x;
314 amrex::ParticleReal m_repeat_y;
316
317 int m_id;
318
319 amrex::ParticleReal m_min_radius2; // minimum radius in which all pass squared
320
321 std::vector<double>::size_type m_nvert = 0;
322 amrex::ParticleReal* m_vertices_x_h_data = nullptr;
323 amrex::ParticleReal* m_vertices_y_h_data = nullptr;
324 amrex::ParticleReal* m_vertices_x_d_data = nullptr;
325 amrex::ParticleReal* m_vertices_y_d_data = nullptr;
326
327 };
328
329} // namespace impactx
330
331#endif // IMPACTX_POLYGONAPERTURE_H
#define AMREX_FORCE_INLINE
#define AMREX_RESTRICT
#define AMREX_GPU_HOST_DEVICE
#define AMREX_GPU_HOST
amrex::GpuComplex< amrex::Real > Complex
void copyAsync(HostToDevice, InIter begin, InIter end, OutIter result) noexcept
static constexpr HostToDevice hostToDevice
void streamSynchronize() noexcept
PODVector< T, ArenaAllocator< T > > DeviceVector
constexpr T powi(T x) noexcept
__host__ __device__ T arg(const GpuComplex< T > &a_z) noexcept
Definition PolygonAperture.H:45
std::map< int, amrex::Gpu::DeviceVector< amrex::ParticleReal > > d_vertices_y
device: skew multipole coefficients of the magnetic field
Definition PolygonAperture.H:57
std::map< int, std::vector< amrex::ParticleReal > > h_vertices_x
host: normal multipole coefficients of the magnetic field
Definition PolygonAperture.H:50
std::map< int, amrex::Gpu::DeviceVector< amrex::ParticleReal > > d_vertices_x
device: normal multipole coefficients of the magnetic field
Definition PolygonAperture.H:55
int next_id
last used id for a created ExactMultipole
Definition PolygonAperture.H:47
std::map< int, std::vector< amrex::ParticleReal > > h_vertices_y
host: skew multipole coefficients of the magnetic field
Definition PolygonAperture.H:52
Definition All.H:55
@ 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
__host__ __device__ void make_invalid() const noexcept
static constexpr __host__ __device__ SmallMatrix< T, NRows, NCols, ORDER, StartIndex > Identity() noexcept
Definition ReferenceParticle.H:31
AMREX_GPU_HOST AMREX_FORCE_INLINE Map6x6 transport_map(RefPart const &AMREX_RESTRICT refpart) const
Definition PolygonAperture.H:303
amrex::ParticleReal * m_vertices_x_h_data
number of vertices
Definition PolygonAperture.H:322
amrex::ParticleReal m_repeat_y
horizontal period for repeated masking
Definition PolygonAperture.H:314
amrex::ParticleReal * m_vertices_x_d_data
non-owning pointer to host vertices
Definition PolygonAperture.H:324
std::vector< double >::size_type m_nvert
Definition PolygonAperture.H:321
void compute_constants(RefPart const &refpart)
Definition PolygonAperture.H:172
Action m_action
Definition PolygonAperture.H:312
int m_id
for hexagonal/triangular mask patterns: horizontal shift of every 2nd (odd) vertical period by m_repe...
Definition PolygonAperture.H:317
static constexpr auto type
Definition PolygonAperture.H:70
bool m_shift_odd_x
vertical period for repeated masking
Definition PolygonAperture.H:315
amrex::ParticleReal m_min_radius2
unique PolygonAperture id used for data lookup map
Definition PolygonAperture.H:319
amrex::ParticleReal * m_vertices_y_d_data
non-owning pointer to device x vertices
Definition PolygonAperture.H:325
Action
Definition PolygonAperture.H:74
@ absorb
Definition PolygonAperture.H:76
@ transmit
Definition PolygonAperture.H:75
PolygonAperture(std::vector< amrex::ParticleReal > vertices_x, std::vector< amrex::ParticleReal > vertices_y, amrex::ParticleReal min_radius2, amrex::ParticleReal repeat_x, amrex::ParticleReal repeat_y, bool shift_odd_x, Action action, amrex::ParticleReal dx=0, amrex::ParticleReal dy=0, amrex::ParticleReal rotation_degree=0, std::optional< std::string > name=std::nullopt)
Definition PolygonAperture.H:98
static std::string action_name(Action const &action)
Definition PolygonAperture.cpp:16
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 PolygonAperture.H:191
ImpactXParticleContainer::ParticleType PType
Definition PolygonAperture.H:71
amrex::ParticleReal * m_vertices_y_h_data
non-owning pointer to host x vertices
Definition PolygonAperture.H:323
amrex::ParticleReal m_repeat_x
action type (transmit, absorb)
Definition PolygonAperture.H:313
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 thin.H:24