OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
BendBase.cpp
Go to the documentation of this file.
2
7#include "Physics/Physics.h"
8
9#include <Kokkos_Core.hpp>
10
11#include <algorithm>
12#include <cmath>
13
14namespace {
15 CoordinateSystemTrafo toCoordinateSystemTrafo(const Euclid3D& frame) {
16 matrix3x3_t rotation;
17 const Rotation3D& euclidRotation = frame.getRotation();
18 for (int row = 0; row < 3; ++row) {
19 for (int col = 0; col < 3; ++col) {
20 rotation(row, col) = euclidRotation(row, col);
21 }
22 }
23
24 const Vector3D& displacement = frame.getVector();
25 const Vector_t<double, 3> origin(
26 displacement.getX(), displacement.getY(), displacement.getZ());
27
28 return CoordinateSystemTrafo(origin, Quaternion(rotation).conjugate());
29 }
30} // namespace
31
33
35 : Component(right),
36 startField_m(right.startField_m),
37 endField_m(right.endField_m),
38 angle_m(right.angle_m),
39 entranceAngle_m(right.entranceAngle_m),
40 exitAngle_m(right.exitAngle_m),
41 gap_m(right.gap_m),
42 designEnergy_m(right.designEnergy_m),
43 designEnergyChangeable_m(true),
44 fieldAmplitudeX_m(right.fieldAmplitudeX_m),
45 fieldAmplitudeY_m(right.fieldAmplitudeY_m),
46 fieldAmplitude_m(right.fieldAmplitude_m),
47 fileName_m(right.fileName_m),
48 entryFaceRotation_m(right.entryFaceRotation_m),
49 exitFaceRotation_m(right.exitFaceRotation_m),
50 entryFaceCurvature_m(right.entryFaceCurvature_m),
51 exitFaceCurvature_m(right.exitFaceCurvature_m),
52 slices_m(right.slices_m),
53 stepSize_m(right.stepSize_m),
54 nSlices_m(right.nSlices_m),
55 k1_m(right.k1_m) {}
56
57BendBase::BendBase(const std::string& name)
58 : Component(name),
59 startField_m(0.0),
60 endField_m(0.0),
61 angle_m(0.0),
62 entranceAngle_m(0.0),
63 exitAngle_m(0.0),
64 gap_m(0.0),
65 designEnergy_m(0.0),
66 designEnergyChangeable_m(true),
67 fieldAmplitudeX_m(0.0),
68 fieldAmplitudeY_m(0.0),
69 fieldAmplitude_m(0.0),
70 fileName_m(),
71 entryFaceRotation_m(0.0),
72 exitFaceRotation_m(0.0),
73 entryFaceCurvature_m(0.0),
74 exitFaceCurvature_m(0.0),
75 slices_m(1.0),
76 stepSize_m(0.0),
77 nSlices_m(1),
78 k1_m(0.0) {}
79
80BendBase::~BendBase() = default;
81
82void BendBase::initialise(PartBunch_t* bunch, double& startField, double& endField) {
83 RefPartBunch_m = bunch;
84 startField_m = startField;
85 endField_m = startField + getElementLength();
86 endField = endField_m;
87 online_m = true;
88}
89
90void BendBase::finalise() { online_m = false; }
91
92bool BendBase::apply(const std::shared_ptr<ParticleContainer_t>& pc) {
93 auto Rview = pc->R.getView();
94 auto Eview = pc->E.getView();
95 auto Bview = pc->B.getView();
96 const size_t nLocal = pc->getLocalNum();
97
98 const BMultipoleField& field = getField();
99 const int order = field.order();
100 Kokkos::View<double*> normal("BendBase::normal", order);
101 Kokkos::View<double*> skew("BendBase::skew", order);
102 auto normalHost = Kokkos::create_mirror_view(normal);
103 auto skewHost = Kokkos::create_mirror_view(skew);
104 for (int i = 0; i < order; ++i) {
105 normalHost(i) = field.getNormalComponent(i);
106 skewHost(i) = field.getSkewComponent(i);
107 }
108 Kokkos::deep_copy(normal, normalHost);
109 Kokkos::deep_copy(skew, skewHost);
110
111 const double elemLength = getElementLength();
112
113 Kokkos::parallel_for(
114 "BendBase::apply", nLocal, KOKKOS_LAMBDA(const size_t i) {
115 if (Rview(i)(2) < 0.0 || Rview(i)(2) > elemLength) {
116 return;
117 }
118
119 Vector_t<double, 3> Bf(0.0);
120 const double x = Rview(i)(0);
121 const double y = Rview(i)(1);
122
123 if (normal.extent(0) > 0) {
124 Bf(1) += normal(0);
125 }
126 if (skew.extent(0) > 0) {
127 Bf(0) -= skew(0);
128 }
129 if (normal.extent(0) > 1) {
130 Bf(0) += normal(1) * y;
131 Bf(1) += normal(1) * x;
132 }
133 if (skew.extent(0) > 1) {
134 Bf(0) -= skew(1) * x;
135 Bf(1) += skew(1) * y;
136 }
137
138 for (unsigned d = 0; d < 3; ++d) {
139 Eview(i)(d) += 0.0;
140 Bview(i)(d) += Bf(d);
141 }
142 });
143
144 return false;
145}
146
148 const size_t& i, const double&, Vector_t<double, 3>& E, Vector_t<double, 3>& B) {
149 std::shared_ptr<ParticleContainer_t> pc = RefPartBunch_m->getParticleContainer();
150 const Vector_t<double, 3> R = pc->R.getView()(i);
151
152 if (!isInside(R)) {
153 return false;
154 }
155 if (!isInsideTransverse(R)) {
157 }
158
159 computeFieldHost(R, getField(), B);
160 (void)E;
161 return false;
162}
163
165 const Vector_t<double, 3>& R, const Vector_t<double, 3>&, const double&,
167 if (!isInside(R)) {
168 return false;
169 }
170 if (!isInsideTransverse(R)) {
172 }
173
174 computeFieldHost(R, getField(), B);
175 (void)E;
176 return false;
177}
178
180 const Vector_t<double, 3>& R, const Vector_t<double, 3>&, const double&,
182 if (!isInside(R)) {
183 return false;
184 }
185 if (!isInsideTransverse(R)) {
186 return true;
187 }
188
189 computeFieldHost(R, getField(), B);
190 (void)E;
191 return false;
192}
193
194void BendBase::getFieldExtend(double& zBegin, double& zEnd) const {
195 zBegin = 0.0;
196 zEnd = getElementLength();
197}
198
200 return r(2) >= 0.0 && r(2) < getElementLength() && isInsideTransverse(r);
201}
202
204 return toCoordinateSystemTrafo(getEntranceFrame());
205}
206
208 return toCoordinateSystemTrafo(getExitFrame());
209}
210
212 const Euclid3D entrance = getEntranceFrame();
213 const Euclid3D exit = getExitFrame();
214 const Vector3D delta = exit.getVector() - entrance.getVector();
215 return std::sqrt(
216 delta.getX() * delta.getX() + delta.getY() * delta.getY()
217 + delta.getZ() * delta.getZ());
218}
219
220std::vector<Vector_t<double, 3>> BendBase::getDesignPath(std::size_t minSamples) const {
221 const double sBegin = getEntrance();
222 const double sEnd = getExit();
223 const double span = std::abs(sEnd - sBegin);
224 const std::size_t samples =
225 std::max<std::size_t>(minSamples, static_cast<std::size_t>(std::ceil(span / 0.01)) + 1);
226
227 std::vector<Vector_t<double, 3>> path;
228 path.reserve(samples);
229 for (std::size_t i = 0; i < samples; ++i) {
230 const double alpha =
231 (samples > 1) ? static_cast<double>(i) / static_cast<double>(samples - 1) : 0.0;
232 const double s = sBegin + alpha * (sEnd - sBegin);
233 const Euclid3D pose = getTransform(s);
234 path.emplace_back(pose.getX(), pose.getY(), pose.getZ());
235 }
236
237 return path;
238}
239
240double BendBase::calcDesignRadius(double fieldAmplitude) const {
241 const auto& reference = *RefPartBunch_m->getParticleContainer()->getReference();
242 const double mass = reference.getM();
243 const double betaGamma = calcBetaGamma();
244 const double charge = reference.getQ();
245 return std::abs(betaGamma * mass / (Physics::c * fieldAmplitude * charge));
246}
247
248double BendBase::calcFieldAmplitude(double radius) const {
249 const auto& reference = *RefPartBunch_m->getParticleContainer()->getReference();
250 const double mass = reference.getM();
251 const double betaGamma = calcBetaGamma();
252 const double charge = reference.getQ();
253 return betaGamma * mass / (Physics::c * radius * charge);
254}
255
256double BendBase::calcBendAngle(double chordLength, double radius) const {
257 return 2.0 * std::asin(chordLength / (2.0 * radius));
258}
259
260double BendBase::calcDesignRadius(double chordLength, double angle) const {
261 return chordLength / (2.0 * std::sin(angle / 2.0));
262}
263
264double BendBase::calcGamma() const {
265 const auto& reference = *RefPartBunch_m->getParticleContainer()->getReference();
266 const double mass = reference.getM();
267 return designEnergy_m / mass + 1.0;
268}
269
271 const double gamma = calcGamma();
272 return std::sqrt(gamma * gamma - 1.0);
273}
274
276 const Vector_t<double, 3>& R, const BMultipoleField& field, Vector_t<double, 3>& B) {
277 const int order = field.order();
278 if (order > 0) {
279 B(1) += field.getNormalComponent(0);
280 B(0) -= field.getSkewComponent(0);
281 }
282 if (order > 1) {
283 B(0) += field.getNormalComponent(1) * R(1);
284 B(1) += field.getNormalComponent(1) * R(0);
285 B(0) -= field.getSkewComponent(1) * R(0);
286 B(1) += field.getSkewComponent(1) * R(1);
287 }
288}
ippl::Vector< T, Dim > Vector_t
Template PIC bunch: IPPL PicManager, shared field mesh/solver, and multiple particle containers.
The magnetic field of a multipole.
int order() const
Return order.
double getNormalComponent(int n) const
Get component.
double getSkewComponent(int n) const
Get component.
Common OPALX interface for analytic horizontal bending magnets.
Definition BendBase.h:32
double endField_m
Definition BendBase.h:163
bool apply(const std::shared_ptr< ParticleContainer_t > &pc) override
Apply to all particles. Kernel launch moved inside the function.
Definition BendBase.cpp:92
double calcGamma() const
Definition BendBase.cpp:264
virtual BMultipoleField & getField() override=0
Return field.
double startField_m
Definition BendBase.h:162
std::vector< Vector_t< double, 3 > > getDesignPath(std::size_t minSamples=32) const
Sample the local curved reference path of the bend body.
Definition BendBase.cpp:220
double calcBendAngle(double chordLength, double radius) const
Definition BendBase.cpp:256
bool applyToReferenceParticle(const Vector_t< double, 3 > &R, const Vector_t< double, 3 > &P, const double &t, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B) override
Apply to reference particle with position R and momemtum P.
Definition BendBase.cpp:179
double calcBetaGamma() const
Definition BendBase.cpp:270
double getChordLength() const
Return the geometric chord between entrance and exit frames.
Definition BendBase.cpp:211
double designEnergy_m
Definition BendBase.h:168
void finalise() override
Definition BendBase.cpp:90
CoordinateSystemTrafo getEdgeToBegin() const override
Definition BendBase.cpp:203
void initialise(PartBunch_t *bunch, double &startField, double &endField) override
Definition BendBase.cpp:82
CoordinateSystemTrafo getEdgeToEnd() const override
Definition BendBase.cpp:207
~BendBase() override
void getFieldExtend(double &zBegin, double &zEnd) const override
Return the field-support extent of the component.
Definition BendBase.cpp:194
double calcFieldAmplitude(double radius) const
Definition BendBase.cpp:248
double calcDesignRadius(double fieldAmplitude) const
Definition BendBase.cpp:240
static void computeFieldHost(const Vector_t< double, 3 > &R, const BMultipoleField &field, Vector_t< double, 3 > &B)
Definition BendBase.cpp:275
bool isInside(const Vector_t< double, 3 > &r) const override
Definition BendBase.cpp:199
bool online_m
Definition Component.h:226
PartBunch_t * RefPartBunch_m
Definition Component.h:225
Rigid spatial transform between a parent frame and a local frame.
virtual double getExit() const
Get exit position.
bool getFlagDeleteOnTransverseExit() const
virtual double getElementLength() const
Get design length.
virtual Euclid3D getExitFrame() const
Get transform.
virtual Euclid3D getEntranceFrame() const
Get transform.
bool isInsideTransverse(const Vector_t< double, 3 > &r) const
virtual Euclid3D getTransform(double fromS, double toS) const
Get transform.
virtual double getEntrance() const
Get entrance position.
Displacement and rotation in space.
Definition Euclid3D.h:67
const Vector3D & getVector() const
Get displacement.
Definition Euclid3D.cpp:45
const Rotation3D & getRotation() const
Get rotation.
Definition Euclid3D.cpp:47
Vector_t< double, Dim > R(size_t)
Do not use; throws (access positions via ParticleContainer::R).
Definition PartBunch.h:611
const PartData * getReference() const
Definition PartBunch.h:494
KOKKOS_INLINE_FUNCTION double getM() const
The constant mass per particle.
Definition PartData.h:109
Quaternion storage and rotation algebra used by OPALX geometry code.
Rotation in 3-dimensional space.
Definition Rotation3D.h:45
A 3-dimension vector.
Definition Vector3D.h:30
double getY() const
Get component.
Definition Vector3D.h:134
double getX() const
Get component.
Definition Vector3D.h:132
double getZ() const
Get component.
Definition Vector3D.h:136
constexpr double c
The velocity of light in m/s.
Definition Physics.h:60