OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
PluginElement.cpp
Go to the documentation of this file.
1//
2// Class PluginElement
3// Abstract Interface for (Cyclotron) Plugin Elements (CCollimator, Probe, Stripper, Septum)
4// Implementation via Non-Virtual Interface Template Method
5//
6// Copyright (c) 2018-2020, Paul Scherrer Institut, Villigen PSI, Switzerland
7// All rights reserved
8//
9// This file is part of OPAL.
10//
11// OPAL is free software: you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation, either version 3 of the License, or
14// (at your option) any later version.
15//
16// You should have received a copy of the GNU General Public License
17// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
18//
20
23#include "Physics/Physics.h"
24#include "Physics/Units.h"
26#include "Utilities/Options.h"
27#include "Utilities/Util.h"
28
29
32
35 setDimensions(0.0, 0.0, 0.0, 0.0);
36}
37
39 Component(right) {
40 setDimensions(right.xstart_m, right.xend_m, right.ystart_m, right.yend_m);
41}
42
44 if (online_m)
45 goOffline();
46}
47
48void PluginElement::initialise(PartBunchBase<double, 3> *bunch, double &, double &) {
49 initialise(bunch);
50}
51
53 RefPartBunch_m = bunch;
54 lossDs_m = std::unique_ptr<LossDataSink>(new LossDataSink(getOutputFN(), !Options::asciidump));
55 // virtual hook
56 doInitialise(bunch);
57 goOnline(-1e6);
58}
59
61 doFinalise();
62 if (online_m)
64}
65
67 if (online_m && lossDs_m)
68 lossDs_m->save();
69 lossDs_m.reset(nullptr);
71 online_m = false;
72}
73
75 return false;
76}
77
78bool PluginElement::apply(const size_t &/*i*/, const double &, Vector_t &, Vector_t &) {
79 return false;
80}
81
82bool PluginElement::applyToReferenceParticle(const Vector_t &, const Vector_t &, const double &, Vector_t &, Vector_t &) {
83 return false;
84}
85
86void PluginElement::setDimensions(double xstart, double xend, double ystart, double yend) {
87 xstart_m = xstart;
88 ystart_m = ystart;
89 xend_m = xend;
90 yend_m = yend;
91 rstart_m = std::hypot(xstart, ystart);
92 rend_m = std::hypot(xend, yend);
93 // start position is the one with lowest radius
94 if (rstart_m > rend_m) {
95 std::swap(xstart_m, xend_m);
96 std::swap(ystart_m, yend_m);
97 std::swap(rstart_m, rend_m);
98 }
100 B_m = xstart_m - xend_m;
101 R_m = std::sqrt(A_m*A_m+B_m*B_m);
103
104 // element equation: A*X + B*Y + C = 0
105 // point closest to origin https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
106 double x_close = 0.0;
107 if (R_m > 0.0)
108 x_close = - A_m * C_m / (R_m * R_m);
109
110 if (x_close > std::min(xstart_m, xend_m) && x_close < std::max(xstart_m, xend_m) )
111 rmin_m = std::abs(C_m) / std::hypot(A_m,B_m);
112 else
114}
115
116void PluginElement::setGeom(const double dist) {
117
118 double slope;
119 if (xend_m == xstart_m) {
120 slope = 1.0e12;
121 } else {
122 slope = (yend_m - ystart_m) / (xend_m - xstart_m);
123 }
124 double coeff2 = std::sqrt(1 + slope * slope);
125 double coeff1 = slope / coeff2;
126 double halfdist = dist / 2.0;
127 geom_m[0].x = xstart_m - halfdist * coeff1;
128 geom_m[0].y = ystart_m + halfdist / coeff2;
129
130 geom_m[1].x = xstart_m + halfdist * coeff1;
131 geom_m[1].y = ystart_m - halfdist / coeff2;
132
133 geom_m[2].x = xend_m + halfdist * coeff1;
134 geom_m[2].y = yend_m - halfdist / coeff2;
135
136 geom_m[3].x = xend_m - halfdist * coeff1;
137 geom_m[3].y = yend_m + halfdist / coeff2;
138
139 geom_m[4].x = geom_m[0].x;
140 geom_m[4].y = geom_m[0].y;
141
142 doSetGeom();
143}
144
145void PluginElement::changeWidth(PartBunchBase<double, 3> *bunch, int i, const double tstep, const double tangle) {
146 double lstep = euclidean_norm(bunch->P[i]) / Util::getGamma(bunch->P[i]) * Physics::c * tstep;
147 double sWidth = lstep / std::sqrt( 1 + 1/tangle/tangle );
148 setGeom(sWidth);
149}
150
151double PluginElement::calculateIncidentAngle(double xp, double yp) const {
152 double k1, k2, tangle = 0.0;
153 if ( B_m == 0.0 && xp == 0.0) {
154 // width is 0.0, keep non-zero
155 tangle = 0.1;
156 } else if ( B_m == 0.0 ){
157 k1 = yp / xp;
158 if (k1 == 0.0)
159 tangle = 1.0e12;
160 else
161 tangle = std::abs(1 / k1);
162 } else if ( xp == 0.0 ) {
163 k2 = - A_m / B_m;
164 if ( k2 == 0.0 )
165 tangle = 1.0e12;
166 else
167 tangle = std::abs(1 / k2);
168 } else {
169 k1 = yp / xp;
170 k2 = - A_m / B_m;
171 tangle = std::abs(( k1-k2 ) / (1 + k1*k2));
172 }
173 return tangle;
174}
175
177 return xstart_m;
178}
179
181 return xend_m;
182}
183
185 return ystart_m;
186}
187
189 return yend_m;
190}
191
192bool PluginElement::check(PartBunchBase<double, 3> *bunch, const int turnnumber, const double t, const double tstep) {
193 bool flag = false;
194 // check if bunch close
195 bool bunchClose = preCheck(bunch);
196
197 if (bunchClose == true) {
198 flag = doCheck(bunch, turnnumber, t, tstep); // virtual hook
199 }
200 // finalise, can have reduce
201 flag = finaliseCheck(bunch, flag);
202
203 return flag;
204}
205
206void PluginElement::getDimensions(double &zBegin, double &zEnd) const {
207 zBegin = -0.005;
208 zEnd = 0.005;
209}
210
211int PluginElement::checkPoint(const double &x, const double &y) const {
212 int cn = 0;
213 for (int i = 0; i < 4; i++) {
214 if (( (geom_m[i].y <= y) && (geom_m[i+1].y > y))
215 || ((geom_m[i].y > y) && (geom_m[i+1].y <= y))) {
216
217 float vt = (float)(y - geom_m[i].y) / (geom_m[i+1].y - geom_m[i].y);
218 if(x < geom_m[i].x + vt * (geom_m[i+1].x - geom_m[i].x))
219 ++cn;
220 }
221 }
222 return (cn & 1); // 0 if even (out), and 1 if odd (in)
223}
224
226 OpalData::OpenMode openMode;
227 if (numPassages_m > 0) {
229 } else {
230 openMode = OpalData::getInstance()->getOpenMode();
231 }
232 lossDs_m->save(1, openMode);
234}
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition Vector.h:243
const std::string name
constexpr double c
The velocity of light in m/s.
Definition Physics.h:45
bool asciidump
Definition Options.cpp:85
double getGamma(Vector_t p)
Definition Util.h:46
ParticleAttrib< Vector_t > P
OpenMode getOpenMode() const
Definition OpalData.cpp:353
static OpalData * getInstance()
Definition OpalData.cpp:196
OpenMode
Enum for writing to files.
Definition OpalData.h:64
bool online_m
Definition Component.h:192
virtual void goOnline(const double &kineticEnergy)
Definition Component.cpp:83
Component(const std::string &name)
Constructor with given name.
Definition Component.cpp:53
PartBunchBase< double, 3 > * RefPartBunch_m
Definition Component.h:191
std::string getOutputFN() const
Get output filename.
virtual void doInitialise(PartBunchBase< double, 3 > *)
Pure virtual hook for initialise.
int checkPoint(const double &x, const double &y) const
Checks if coordinate is within element.
void setGeom(const double dist)
Sets geometry geom_m with element width dist.
virtual void getDimensions(double &zBegin, double &zEnd) const override
virtual bool bends() const override
double C_m
Geometric lengths used in calculations.
double getYStart() const
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Pure virtual implementation of Component.
virtual void finalise() final
virtual void doSetGeom()
Virtual hook for setGeom.
virtual void doGoOffline()
Virtual hook for goOffline.
void changeWidth(PartBunchBase< double, 3 > *bunch, int i, const double tstep, const double tangle)
Change probe width depending on step size and angle of particle.
int numPassages_m
Number of turns (number of times save() method is called).
Point geom_m[5]
actual geometry positions with adaptive width such that each particle hits element once per turn
bool check(PartBunchBase< double, 3 > *bunch, const int turnnumber, const double t, const double tstep)
virtual void doFinalise()
Virtual hook for finalise.
virtual void goOffline() final
double getXEnd() const
double calculateIncidentAngle(double xp, double yp) const
Calculate angle of particle/bunch wrt to element.
double xstart_m
input geometry positions
void setDimensions(double xstart, double xend, double ystart, double yend)
Set dimensions and consistency checks.
std::unique_ptr< LossDataSink > lossDs_m
Pointer to Loss instance.
double getXStart() const
Member variable access.
bool finaliseCheck(PartBunchBase< double, 3 > *bunch, bool flagNeedUpdate)
Finalise call after check.
bool preCheck(PartBunchBase< double, 3 > *bunch)
Check if bunch is close to element.
double getYEnd() const
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
double rmin_m
radius closest to the origin
virtual bool doCheck(PartBunchBase< double, 3 > *bunch, const int turnnumber, const double t, const double tstep)=0
Pure virtual hook for check.
PluginElement(const std::string &name)
Constructor with given name.
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Virtual implementation of Component.
virtual ~PluginElement()
void save()
Save output.
Vektor< double, 3 > Vector_t