OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
BeamStripping.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: BeamStripping.cpp,v $
3 // ------------------------------------------------------------------------
4 // Copyright: see Copyright.readme
5 // ------------------------------------------------------------------------
6 //
7 // Class: BeamStripping
8 // Defines the abstract interface for a beam stripping for cyclotrons.
9 //
10 // ------------------------------------------------------------------------
11 // Class category: AbsBeamline
12 // ------------------------------------------------------------------------
13 // $Date: 2018/11 $
14 // $Author: PedroCalvo$
15 // ------------------------------------------------------------------------
16 
19 #include "AbsBeamline/Cyclotron.h"
21 #include "Fields/Fieldmap.h"
22 #include "Physics/Physics.h"
25 #include "Utilities/LogicalError.h"
26 #include "Utilities/Options.h"
27 #include "Utilities/Util.h"
29 
30 #include <fstream>
31 #include <memory>
32 #include <fstream>
33 #include <iostream>
34 #include <fstream>
35 #include <algorithm>
36 
37 #include "Ippl.h"
38 
39 #include "gsl/gsl_spline.h"
40 #include "gsl/gsl_interp.h"
41 
42 using Physics::q_e;
43 using Physics::pi;
44 
45 #define CHECK_BSTP_FSCANF_EOF(arg) if(arg == EOF)\
46 throw GeneralClassicException("BeamStripping::getPressureFromFile",\
47  "fscanf returned EOF at " #arg);
48 
49 extern Inform *gmsg;
50 
51 using namespace std;
52 
53 // Class BeamStripping
54 // ------------------------------------------------------------------------
55 
57  BeamStripping("")
58 {}
59 
60 
62  Component(right),
63  gas_m(right.gas_m),
64  pressure_m(right.pressure_m),
65  pmapfn_m(right.pmapfn_m),
66  pscale_m(right.pscale_m),
67  temperature_m(right.temperature_m),
68  stop_m(right.stop_m),
69  minr_m(right.minr_m),
70  maxr_m(right.maxr_m),
71  minz_m(right.minz_m),
72  maxz_m(right.maxz_m),
73  parmatint_m(NULL) {
74 }
75 
76 BeamStripping::BeamStripping(const std::string &name):
77  Component(name),
78  gas_m(""),
79  pressure_m(0.0),
80  pmapfn_m(""),
81  pscale_m(0.0),
82  temperature_m(0.0),
83  stop_m(true),
84  minr_m(0.0),
85  maxr_m(0.0),
86  minz_m(0.0),
87  maxz_m(0.0),
88  parmatint_m(NULL) {
89 }
90 
91 
93  if (online_m)
94  goOffline();
95 }
96 
97 void BeamStripping::accept(BeamlineVisitor &visitor) const {
98  visitor.visitBeamStripping(*this);
99 }
100 
101 void BeamStripping::setPressure(double pressure) {
102  pressure_m = pressure;
103 }
104 
106  if(pressure_m > 0.0)
107  return pressure_m;
108  else {
109  throw LogicalError("BeamStripping::getPressure",
110  "Pressure must not be zero");
111  }
112 }
113 
114 void BeamStripping::setTemperature(double temperature) {
115  temperature_m = temperature;
116 }
117 
119  if(temperature_m > 0.0)
120  return temperature_m;
121  else {
122  throw LogicalError("BeamStripping::getTemperature",
123  "Temperature must not be zero");
124  }
125 }
126 
127 void BeamStripping::setPressureMapFN(std::string p) {
128  pmapfn_m = p;
129 }
130 
132  return pmapfn_m;
133 }
134 
135 void BeamStripping::setPScale(double ps) {
136  pscale_m = ps;
137 }
138 
139 double BeamStripping::getPScale() const {
140  return pscale_m;
141 }
142 
143 void BeamStripping::setResidualGas(std::string gas) {
144  gas_m = gas;
145 }
146 
148  if(gas_m == "H2" || gas_m == "AIR")
149  return gas_m;
150  else {
151  throw GeneralClassicException("BeamStripping::getResidualGas",
152  "Residual gas " + gas_m + " not found");
153  }
154 }
155 
156 void BeamStripping::setStop(bool stopflag) {
157  stop_m = stopflag;
158 }
159 
161  return stop_m;
162 }
163 
164 bool BeamStripping::apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) {
165  return false;
166 }
167 
168 bool BeamStripping::apply(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) {
169  return false;
170 }
171 
172 
174  int pflag = checkPoint(r(0), r(1), r(2));
175  bool isDead = (pflag != 0);
176  return isDead;
177 }
178 
180  const int turnnumber, const double t, const double tstep) {
181 
182  bool flagNeedUpdate = false;
183 
184  Vector_t rmin, rmax;
185  bunch->get_bounds(rmin, rmax);
186  std::pair<Vector_t, double> boundingSphere;
187  boundingSphere.first = 0.5 * (rmax + rmin);
188  boundingSphere.second = euclidean_norm(rmax - boundingSphere.first);
189 
190  maxr_m = 1000 * cycl->getMaxR();
191  minr_m = 1000 * cycl->getMinR();
192  maxz_m = 1000 * cycl->getMaxZ();
193  minz_m = 1000 * cycl->getMinZ();
194 
195  int pflag = 0;
196  size_t tempnum = bunch->getLocalNum();
197  for (unsigned int i = 0; i < tempnum; ++i) {
198  pflag = checkPoint(bunch->R[i](0), bunch->R[i](1), bunch->R[i](2));
199  if ( (pflag != 0) && (bunch->Bin[i] != -1) )
200  flagNeedUpdate = true;
201  }
202  reduce(&flagNeedUpdate, &flagNeedUpdate + 1, &flagNeedUpdate, OpBitwiseOrAssign());
203  if (flagNeedUpdate && parmatint_m) {
204  dynamic_cast<BeamStrippingPhysics*>(parmatint_m)->setCyclotron(cycl);
205  parmatint_m->apply(bunch, boundingSphere);
206  }
207  return flagNeedUpdate;
208 }
209 
210 
211 void BeamStripping::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
212  endField = startField + getElementLength();
213  initialise(bunch, pscale_m);
214 }
215 
216 void BeamStripping::initialise(PartBunchBase<double, 3> *bunch, const double &scaleFactor) {
217 
218  RefPartBunch_m = bunch;
219 
221 
222  if (pmapfn_m != "") {
223  getPressureFromFile(scaleFactor);
224  // calculate the radii of initial grid.
226  }
227 
228  goOnline(-1e6);
229 
230  // change the mass and charge to simulate real particles
231  //*gmsg << "* Mass and charge have been reseted for beam stripping " << endl;
232  for (size_t i = 0; i < bunch->getLocalNum(); ++i) {
233  bunch->M[i] = bunch->getM()*1E-9;
234  bunch->Q[i] = bunch->getQ() * q_e;
235  if(bunch->weHaveBins())
236  bunch->Bin[bunch->getLocalNum()-1] = bunch->Bin[i];
237  }
238 }
239 
241  if (online_m)
242  goOffline();
243  *gmsg << "* Finalize Beam Stripping" << endl;
244 }
245 
246 void BeamStripping::goOnline(const double &) {
247 }
248 
250  online_m = false;
251 }
252 
253 bool BeamStripping::bends() const {
254  return false;
255 }
256 
257 void BeamStripping::getDimensions(double &zBegin, double &zEnd) const {}
258 
260  return BEAMSTRIPPING;
261 }
262 
264  return "BeamStripping";
265 }
266 
267 
268 int BeamStripping::checkPoint(const double &x, const double &y, const double &z) {
269  int cn;
270  double rpos = sqrt(x * x + y * y);
271  double zpos = z;
272  if (zpos >= maxz_m || zpos <= minz_m || rpos >= maxr_m || rpos <= minr_m)
273  cn = 0;
274  else
275  cn = 1;
276  return (cn); // 0 if out, and 1 if in
277 }
278 
279 double BeamStripping::checkPressure(const double &x, const double &y) {
280 
281  double pressure = 0.0;
282 
283  if(pmapfn_m != "") {
284  const double rad = sqrt(x * x + y * y);
285  const double xir = (rad - PP.rmin) / PP.delr;
286 
287  // ir : the number of path whose radius is less than the 4 points of cell which surround the particle.
288  const int ir = (int)xir;
289  // wr1 : the relative distance to the inner path radius
290  const double wr1 = xir - (double)ir;
291  // wr2 : the relative distance to the outer path radius
292  const double wr2 = 1.0 - wr1;
293 
294  const double tempv = atan(y / x);
295  double tet = tempv, tet_map, xit;
296 
297  if((x < 0) && (y >= 0)) tet = pi + tempv;
298  else if((x < 0) && (y <= 0)) tet = pi + tempv;
299  else if((x > 0) && (y <= 0)) tet = 2.0 * pi + tempv;
300  else if((x == 0) && (y > 0)) tet = pi / 2.0;
301  else if((x == 0) && (y < 0)) tet = 1.5 * pi;
302 
303  // the actual angle of particle
304  tet = tet / pi * 180.0;
305 
306  // the corresponding angle on the field map
307  // Note: this does not work if the start point of field map does not equal zero.
308  double symmetry = 1.0;
309  tet_map = fmod(tet, 360.0 / symmetry);
310  xit = tet_map / PP.dtet;
311  int it = (int) xit;
312  const double wt1 = xit - (double)it;
313  const double wt2 = 1.0 - wt1;
314 
315  // it : the number of point on the inner path whose angle is less than the particle' corresponding angle.
316  // include zero degree point
317  it = it + 1;
318 
319  int r1t1, r2t1, r1t2, r2t2;
320  // r1t1 : the index of the "min angle, min radius" point in the 2D field array.
321  // considering the array start with index of zero, minus 1.
322 
323  //With this we have P-field AND this is far more intuitive for me ....
324  r1t1 = idx(ir, it);
325  r2t1 = idx(ir + 1, it);
326  r1t2 = idx(ir, it + 1);
327  r2t2 = idx(ir + 1, it + 1);
328 
329  if((it >= 0) && (ir >= 0) && (it < PField.ntetS) && (ir < PField.nrad)) {
330  pressure = (PField.pfld[r1t1] * wr2 * wt2 +
331  PField.pfld[r2t1] * wr1 * wt2 +
332  PField.pfld[r1t2] * wr2 * wt1 +
333  PField.pfld[r2t2] * wr1 * wt1);
334  }
335  }
336  else {
337  pressure = getPressure();
338  }
339 
340  if(pressure > 0.0)
341  return pressure;
342  else {
343  throw LogicalError("BeamStripping::checkPressure",
344  "Pressure must not be zero");
345  }
346 }
347 
348 // Calculates Radiae of initial grid (dimensions in [m]!)
349 void BeamStripping::initR(double rmin, double dr, int nrad) {
350  PP.rarr.resize(nrad);
351  for(int i = 0; i < nrad; i++)
352  PP.rarr[i] = rmin + i * dr;
353 
354  PP.delr = dr;
355 }
356 
357 // Read pressure map from external file.
358 void BeamStripping::getPressureFromFile(const double &scaleFactor) {
359 
360  FILE *f = NULL;
361 
362  *gmsg << "* " << endl;
363  *gmsg << "* Reading pressure field map " << pmapfn_m << endl;
364 
365  PP.Pfact = scaleFactor;
366 
367  if((f = fopen(pmapfn_m.c_str(), "r")) == NULL) {
368  throw GeneralClassicException("BeamStripping::getPressureFromFile",
369  "failed to open file '" + pmapfn_m + "', please check if it exists");
370  }
371 
372  CHECK_BSTP_FSCANF_EOF(fscanf(f, "%lf", &PP.rmin));
373  *gmsg << "* --- Minimal radius of measured pressure map: " << PP.rmin << " [mm]" << endl;
374  PP.rmin *= 0.001; // mm --> m
375 
376  CHECK_BSTP_FSCANF_EOF(fscanf(f, "%lf", &PP.delr));
377  //if the value is negative, the actual value is its reciprocal.
378  if(PP.delr < 0.0) PP.delr = 1.0 / (-PP.delr);
379  *gmsg << "* --- Stepsize in radial direction: " << PP.delr << " [mm]" << endl;
380  PP.delr *= 0.001; // mm --> m
381 
382  CHECK_BSTP_FSCANF_EOF(fscanf(f, "%lf", &PP.tetmin));
383  *gmsg << "* --- Minimal angle of measured pressure map: " << PP.tetmin << " [deg]" << endl;
384 
385  CHECK_BSTP_FSCANF_EOF(fscanf(f, "%lf", &PP.dtet));
386  //if the value is negative, the actual value is its reciprocal.
387  if(PP.dtet < 0.0) PP.dtet = 1.0 / (-PP.dtet);
388  *gmsg << "* --- Stepsize in azimuthal direction: " << PP.dtet << " [deg]" << endl;
389 
390  CHECK_BSTP_FSCANF_EOF(fscanf(f, "%d", &PField.ntet));
391  *gmsg << "* --- Grid points along azimuth (ntet): " << PField.ntet << endl;
392 
393  CHECK_BSTP_FSCANF_EOF(fscanf(f, "%d", &PField.nrad));
394  *gmsg << "* --- Grid points along radius (nrad): " << PField.nrad << endl;
395 
396  PField.ntetS = PField.ntet + 1;
398 
399  *gmsg << "* --- Total stored grid point number: " << PField.ntot << endl; //((ntet+1) * nrad)
400  PField.pfld.resize(PField.ntot);
401 
402  *gmsg << "* --- Escale factor: " << PP.Pfact << endl;
403 
404  for(int i = 0; i < PField.nrad; i++) {
405  for(int k = 0; k < PField.ntet; k++) {
406  CHECK_BSTP_FSCANF_EOF(fscanf(f, "%16lE", &(PField.pfld[idx(i, k)])));
407  PField.pfld[idx(i, k)] *= PP.Pfact;
408  }
409  }
410  *gmsg << "*" << endl;
411 
412  fclose(f);
413 }
414 
415 #undef CHECK_BSTP_FSCANF_EOF
bool weHaveBins() const
virtual void apply(PartBunchBase< double, 3 > *bunch, const std::pair< Vector_t, double > &boundingSphere, size_t numParticlesInSimulation=0)=0
virtual double getMaxR() const
Definition: Cyclotron.cpp:310
virtual void finalise()
virtual ParticleMatterInteractionHandler * getParticleMatterInteraction() const
Definition: ElementBase.h:579
virtual void goOffline()
virtual std::string getPressureMapFN() const
void initR(double rmin, double dr, int nrad)
int checkPoint(const double &x, const double &y, const double &z)
double pscale_m
stores the filename of the pressure map
double minr_m
size limits took from cyclotron
void getPressureFromFile(const double &scaleFactor)
virtual bool bends() const
virtual void visitBeamStripping(const BeamStripping &)=0
Apply the algorithm to a beam stripping interaction.
Interface for a Cyclotron.
Definition: Cyclotron.h:91
double getPressure() const
virtual bool checkBeamStripping(PartBunchBase< double, 3 > *bunch, Cyclotron *cycl, const int turnnumber, const double t, const double tstep)
ParticleAttrib< double > Q
virtual void goOnline(const double &kineticEnergy)
Inform * gmsg
Definition: Main.cpp:21
double getM() const
bool online_m
Definition: Component.h:201
#define CHECK_BSTP_FSCANF_EOF(arg)
ParticleMatterInteractionHandler * parmatint_m
virtual double getMinZ() const
Definition: Cyclotron.cpp:319
std::string gas_m
parameters for BeamStripping
virtual ~BeamStripping()
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
Definition: GlobalComm.hpp:55
PPositions PP
virtual double getMinR() const
Definition: Cyclotron.cpp:306
virtual void accept(BeamlineVisitor &) const
Apply visitor to BeamStripping.
int idx(int irad, int ktet)
constexpr double pi
The value of .
Definition: Physics.h:31
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:511
std::string pmapfn_m
mbar
const double pi
Definition: fftpack.cpp:894
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:810
void setPScale(double ps)
void setStop(bool stopflag)
virtual bool getStop() const
void setTemperature(double temperature)
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:200
void setPressureMapFN(std::string pmapfn)
double maxr_m
mm
double getTemperature() const
double minz_m
mm
std::string getBeamStrippingShape()
double checkPressure(const double &x, const double &y)
double rmin
Definition: BeamStripping.h:45
double Pfact
Definition: BeamStripping.h:51
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
size_t getLocalNum() const
double delr
Definition: BeamStripping.h:45
void setPressure(double pressure)
double temperature_m
a scale factor for the P-field
double dtet
Definition: BeamStripping.h:46
virtual double getPScale() const
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
virtual ElementBase::ElementType getType() const
Get element type std::string.
T rad(T x)
Convert degrees to radians.
Definition: matheval.hpp:86
void setResidualGas(std::string gas)
double maxz_m
mm
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
constexpr double q_e
The elementary charge in As.
Definition: Physics.h:76
double getQ() const
Access to reference data.
const std::string name
virtual std::string getResidualGas() const
ParticleAttrib< int > Bin
double stop_m
K.
ParticleAttrib< double > M
ParticlePos_t & R
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B)
virtual double getMaxZ() const
Definition: Cyclotron.cpp:327
PFieldData PField
Interface for a single beam element.
Definition: Component.h:51
std::vector< double > pfld
Definition: BeamStripping.h:30
void get_bounds(Vector_t &rmin, Vector_t &rmax)
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField)
Abstract algorithm.
Definition: Inform.h:41
Logical error exception.
Definition: LogicalError.h:33
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
double tetmin
Definition: BeamStripping.h:46
virtual void getDimensions(double &zBegin, double &zEnd) const
std::vector< double > rarr
Definition: BeamStripping.h:49