OPAL (Object Oriented Parallel Accelerator Library)  2024.1
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"
25 #include "Structure/LossDataSink.h"
26 #include "Utilities/Options.h"
27 #include "Utilities/Util.h"
28 
29 
31 {}
32 
33 PluginElement::PluginElement(const std::string &name):
34  Component(name) {
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 
48 void 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)
63  goOffline();
64 }
65 
67  if (online_m && lossDs_m)
68  lossDs_m->save();
69  lossDs_m.reset(nullptr);
70  doGoOffline();
71  online_m = false;
72 }
73 
74 bool PluginElement::bends() const {
75  return false;
76 }
77 
78 bool PluginElement::apply(const size_t &/*i*/, const double &, Vector_t &, Vector_t &) {
79  return false;
80 }
81 
82 bool PluginElement::applyToReferenceParticle(const Vector_t &, const Vector_t &, const double &, Vector_t &, Vector_t &) {
83  return false;
84 }
85 
86 void 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  }
99  A_m = yend_m - ystart_m;
100  B_m = xstart_m - xend_m;
101  R_m = std::sqrt(A_m*A_m+B_m*B_m);
102  C_m = ystart_m*xend_m - xstart_m*yend_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
113  rmin_m = rstart_m;
114 }
115 
116 void 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 
145 void 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 
151 double 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 
176 double PluginElement::getXStart() const {
177  return xstart_m;
178 }
179 
180 double PluginElement::getXEnd() const {
181  return xend_m;
182 }
183 
184 double PluginElement::getYStart() const {
185  return ystart_m;
186 }
187 
188 double PluginElement::getYEnd() const {
189  return yend_m;
190 }
191 
192 bool 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 
206 void PluginElement::getDimensions(double &zBegin, double &zEnd) const {
207  zBegin = -0.005;
208  zEnd = 0.005;
209 }
210 
211 int 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) {
228  openMode = OpalData::OpenMode::APPEND;
229  } else {
230  openMode = OpalData::getInstance()->getOpenMode();
231  }
232  lossDs_m->save(1, openMode);
233  numPassages_m++;
234 }
void setDimensions(double xstart, double xend, double ystart, double yend)
Set dimensions and consistency checks.
static OpalData * getInstance()
Definition: OpalData.cpp:196
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
virtual void doFinalise()
Virtual hook for finalise.
virtual ~PluginElement()
double getXEnd() const
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
virtual void doInitialise(PartBunchBase< double, 3 > *)
Pure virtual hook for initialise.
Definition: PluginElement.h:92
ParticleAttrib< Vector_t > P
bool check(PartBunchBase< double, 3 > *bunch, const int turnnumber, const double t, const double tstep)
virtual bool doCheck(PartBunchBase< double, 3 > *bunch, const int turnnumber, const double t, const double tstep)=0
Pure virtual hook for check.
virtual void finalise() final
double xstart_m
input geometry positions
double y
Definition: Component.h:39
bool asciidump
Definition: Options.cpp:85
virtual void doGoOffline()
Virtual hook for goOffline.
bool finaliseCheck(PartBunchBase< double, 3 > *bunch, bool flagNeedUpdate)
Finalise call after check.
Definition: PluginElement.h:90
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
double getYEnd() const
virtual void getDimensions(double &zBegin, double &zEnd) const override
std::unique_ptr< LossDataSink > lossDs_m
Pointer to Loss instance.
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Pure virtual implementation of Component.
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
double rmin_m
radius closest to the origin
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
int checkPoint(const double &x, const double &y) const
Checks if coordinate is within element.
bool online_m
Definition: Component.h:192
virtual void doSetGeom()
Virtual hook for setGeom.
Definition: PluginElement.h:96
double x
Definition: Component.h:38
virtual void goOffline() final
bool preCheck(PartBunchBase< double, 3 > *bunch)
Check if bunch is close to element.
Definition: PluginElement.h:88
virtual void goOnline(const double &kineticEnergy)
Definition: Component.cpp:83
Point geom_m[5]
actual geometry positions with adaptive width such that each particle hits element once per turn ...
OpenMode
Enum for writing to files.
Definition: OpalData.h:64
double calculateIncidentAngle(double xp, double yp) const
Calculate angle of particle/bunch wrt to element.
OpenMode getOpenMode() const
Definition: OpalData.cpp:353
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.
virtual bool bends() const override
double getGamma(Vector_t p)
Definition: Util.h:46
const std::string name
double getYStart() const
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
void save()
Save output.
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
double C_m
Geometric lengths used in calculations.
Interface for a single beam element.
Definition: Component.h:50
std::string getOutputFN() const
Get output filename.
int numPassages_m
Number of turns (number of times save() method is called)
double getXStart() const
Member variable access.
void setGeom(const double dist)
Sets geometry geom_m with element width dist.