OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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 "Structure/LossDataSink.h"
25 #include "Utilities/Options.h"
26 #include "Utilities/Util.h"
27 
28 
30 {}
31 
32 PluginElement::PluginElement(const std::string &name):
33  Component(name) {
34  setDimensions(0.0, 0.0, 0.0, 0.0);
35 }
36 
38  Component(right) {
39  setDimensions(right.xstart_m, right.xend_m, right.ystart_m, right.yend_m);
40 }
41 
43  if (online_m)
44  goOffline();
45 }
46 
47 void PluginElement::initialise(PartBunchBase<double, 3> *bunch, double &, double &) {
48  initialise(bunch);
49 }
50 
52  RefPartBunch_m = bunch;
53  lossDs_m = std::unique_ptr<LossDataSink>(new LossDataSink(getOutputFN(), !Options::asciidump));
54  // virtual hook
55  doInitialise(bunch);
56  goOnline(-1e6);
57 }
58 
60  doFinalise();
61  if (online_m)
62  goOffline();
63 }
64 
66  if (online_m && lossDs_m)
67  lossDs_m->save();
68  lossDs_m.reset(nullptr);
69  doGoOffline();
70  online_m = false;
71 }
72 
73 bool PluginElement::bends() const {
74  return false;
75 }
76 
77 bool PluginElement::apply(const size_t &/*i*/, const double &, Vector_t &, Vector_t &) {
78  return false;
79 }
80 
81 bool PluginElement::applyToReferenceParticle(const Vector_t &, const Vector_t &, const double &, Vector_t &, Vector_t &) {
82  return false;
83 }
84 
85 void PluginElement::setDimensions(double xstart, double xend, double ystart, double yend) {
86  xstart_m = xstart;
87  ystart_m = ystart;
88  xend_m = xend;
89  yend_m = yend;
90  rstart_m = std::hypot(xstart, ystart);
91  rend_m = std::hypot(xend, yend);
92  // start position is the one with lowest radius
93  if (rstart_m > rend_m) {
94  std::swap(xstart_m, xend_m);
95  std::swap(ystart_m, yend_m);
96  std::swap(rstart_m, rend_m);
97  }
98  A_m = yend_m - ystart_m;
99  B_m = xstart_m - xend_m;
100  R_m = std::sqrt(A_m*A_m+B_m*B_m);
102 
103  // element equation: A*X + B*Y + C = 0
104  // point closest to origin https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
105  double x_close = 0.0;
106  if (R_m > 0.0)
107  x_close = - A_m * C_m / (R_m * R_m);
108 
109  if (x_close > std::min(xstart_m, xend_m) && x_close < std::max(xstart_m, xend_m) )
110  rmin_m = std::abs(C_m) / std::hypot(A_m,B_m);
111  else
112  rmin_m = rstart_m;
113 }
114 
115 void PluginElement::setGeom(const double dist) {
116 
117  double slope;
118  if (xend_m == xstart_m)
119  slope = 1.0e12;
120  else
121  slope = (yend_m - ystart_m) / (xend_m - xstart_m);
122 
123  double coeff2 = std::sqrt(1 + slope * slope);
124  double coeff1 = slope / coeff2;
125  double halfdist = dist / 2.0;
126  geom_m[0].x = xstart_m - halfdist * coeff1;
127  geom_m[0].y = ystart_m + halfdist / coeff2;
128 
129  geom_m[1].x = xstart_m + halfdist * coeff1;
130  geom_m[1].y = ystart_m - halfdist / coeff2;
131 
132  geom_m[2].x = xend_m + halfdist * coeff1;
133  geom_m[2].y = yend_m - halfdist / coeff2;
134 
135  geom_m[3].x = xend_m - halfdist * coeff1;
136  geom_m[3].y = yend_m + halfdist / coeff2;
137 
138  geom_m[4].x = geom_m[0].x;
139  geom_m[4].y = geom_m[0].y;
140 
141  doSetGeom();
142 }
143 
144 void PluginElement::changeWidth(PartBunchBase<double, 3> *bunch, int i, const double tstep, const double tangle) {
145 
146  constexpr double c_mtns = Physics::c * 1.0e-9; // m/s --> m/ns
147  double lstep = euclidean_norm(bunch->P[i]) / Util::getGamma(bunch->P[i]) * c_mtns * tstep; // [m]
148  double sWidth = lstep / std::sqrt( 1 + 1/tangle/tangle );
149  setGeom(sWidth);
150 }
151 
152 double PluginElement::calculateIncidentAngle(double xp, double yp) const {
153  double k1, k2, tangle = 0.0;
154  if ( B_m == 0.0 && xp == 0.0) {
155  // width is 0.0, keep non-zero
156  tangle = 0.1;
157  } else if ( B_m == 0.0 ){
158  k1 = yp / xp;
159  if (k1 == 0.0)
160  tangle = 1.0e12;
161  else
162  tangle = std::abs(1 / k1);
163  } else if ( xp == 0.0 ) {
164  k2 = - A_m / B_m;
165  if ( k2 == 0.0 )
166  tangle = 1.0e12;
167  else
168  tangle = std::abs(1 / k2);
169  } else {
170  k1 = yp / xp;
171  k2 = - A_m / B_m;
172  tangle = std::abs(( k1-k2 ) / (1 + k1*k2));
173  }
174  return tangle;
175 }
176 
177 double PluginElement::getXStart() const {
178  return xstart_m;
179 }
180 
181 double PluginElement::getXEnd() const {
182  return xend_m;
183 }
184 
185 double PluginElement::getYStart() const {
186  return ystart_m;
187 }
188 
189 double PluginElement::getYEnd() const {
190  return yend_m;
191 }
192 
193 bool PluginElement::check(PartBunchBase<double, 3> *bunch, const int turnnumber, const double t, const double tstep) {
194  bool flag = false;
195  // check if bunch close
196  bool bunchClose = preCheck(bunch);
197 
198  if (bunchClose == true) {
199  flag = doCheck(bunch, turnnumber, t, tstep); // virtual hook
200  }
201  // finalise, can have reduce
202  flag = finaliseCheck(bunch, flag);
203 
204  return flag;
205 }
206 
207 void PluginElement::getDimensions(double &zBegin, double &zEnd) const {
208  zBegin = -0.005;
209  zEnd = 0.005;
210 }
211 
212 int PluginElement::checkPoint(const double &x, const double &y) const {
213  int cn = 0;
214  for (int i = 0; i < 4; i++) {
215  if (( (geom_m[i].y <= y) && (geom_m[i+1].y > y))
216  || ((geom_m[i].y > y) && (geom_m[i+1].y <= y))) {
217 
218  float vt = (float)(y - geom_m[i].y) / (geom_m[i+1].y - geom_m[i].y);
219  if(x < geom_m[i].x + vt * (geom_m[i+1].x - geom_m[i].x))
220  ++cn;
221  }
222  }
223  return (cn & 1); // 0 if even (out), and 1 if odd (in)
224 }
225 
227  OpalData::OPENMODE openMode;
228  if (numPassages_m > 0) {
229  openMode = OpalData::OPENMODE::APPEND;
230  } else {
231  openMode = OpalData::getInstance()->getOpenMode();
232  }
233  lossDs_m->save(1, openMode);
234  numPassages_m++;
235 }
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
const std::string name
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:51
bool asciidump
Definition: Options.cpp:85
double getGamma(Vector_t p)
Definition: Util.h:27
ParticleAttrib< Vector_t > P
OPENMODE getOpenMode() const
Definition: OpalData.cpp:352
OPENMODE
Enum for writing to files.
Definition: OpalData.h:64
static OpalData * getInstance()
Definition: OpalData.cpp:195
double x
Definition: Component.h:38
double y
Definition: Component.h:39
Interface for a single beam element.
Definition: Component.h:50
bool online_m
Definition: Component.h:195
virtual void goOnline(const double &kineticEnergy)
Definition: Component.cpp:83
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:194
std::string getOutputFN() const
Get output filename.
virtual void doInitialise(PartBunchBase< double, 3 > *)
Pure virtual hook for initialise.
Definition: PluginElement.h:92
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.
Definition: PluginElement.h:96
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.
Definition: PluginElement.h:90
bool preCheck(PartBunchBase< double, 3 > *bunch)
Check if bunch is close to element.
Definition: PluginElement.h:88
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.
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
virtual ~PluginElement()
void save()
Save output.