OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Vacuum.cpp
Go to the documentation of this file.
1 //
2 // Class Vacuum
3 // Defines the abstract interface environment for
4 // beam stripping physics.
5 //
6 // Copyright (c) 2018-2021, Pedro Calvo, CIEMAT, Spain
7 // All rights reserved
8 //
9 // Implemented as part of the PhD thesis
10 // "Optimizing the radioisotope production of the novel AMIT
11 // superconducting weak focusing cyclotron"
12 //
13 // This file is part of OPAL.
14 //
15 // OPAL is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
22 //
23 #include "AbsBeamline/Vacuum.h"
24 
26 #include "AbsBeamline/Cyclotron.h"
28 #include "Fields/Fieldmap.h"
29 #include "Physics/Physics.h"
32 #include "Utilities/LogicalError.h"
34 
35 #include <fstream>
36 #include <iostream>
37 #include <cmath>
38 #include <cstdio>
39 
40 #include "Utility/Inform.h"
41 
42 #define CHECK_VAC_FSCANF_EOF(arg) if (arg == EOF)\
43 throw GeneralClassicException("Vacuum::getPressureFromFile",\
44  "fscanf returned EOF at " #arg);
45 
46 extern Inform* gmsg;
47 
48 
50  Vacuum("")
51 {}
52 
53 Vacuum::Vacuum(const Vacuum& right):
54  Component(right),
55  gas_m(right.gas_m),
56  pressure_m(right.pressure_m),
57  pmapfn_m(right.pmapfn_m),
58  pscale_m(right.pscale_m),
59  temperature_m(right.temperature_m),
60  stop_m(right.stop_m),
61  minr_m(right.minr_m),
62  maxr_m(right.maxr_m),
63  minz_m(right.minz_m),
64  maxz_m(right.maxz_m),
65  parmatint_m(NULL) {
66 }
67 
68 Vacuum::Vacuum(const std::string& name):
69  Component(name),
70  gas_m(ResidualGas::NOGAS),
71  pressure_m(0.0),
72  pmapfn_m(""),
73  pscale_m(1.0),
74  temperature_m(0.0),
75  stop_m(true),
76  minr_m(0.0),
77  maxr_m(0.0),
78  minz_m(0.0),
79  maxz_m(0.0),
80  parmatint_m(NULL) {
81 }
82 
84  if (online_m)
85  goOffline();
86 }
87 
88 
89 void Vacuum::accept(BeamlineVisitor& visitor) const {
90  visitor.visitVacuum(*this);
91 }
92 
93 void Vacuum::setPressure(double pressure) {
94  pressure_m = pressure;
95 }
96 
97 double Vacuum::getPressure() const {
98  if (pressure_m > 0.0) {
99  return pressure_m;
100  } else {
101  throw LogicalError("Vacuum::getPressure",
102  "Pressure must not be zero");
103  }
104 }
105 
106 void Vacuum::setTemperature(double temperature) {
107  temperature_m = temperature;
108 }
109 
110 double Vacuum::getTemperature() const {
111  if (temperature_m > 0.0) {
112  return temperature_m;
113  } else {
114  throw LogicalError("Vacuum::getTemperature",
115  "Temperature must not be zero");
116  }
117 }
118 
119 void Vacuum::setPressureMapFN(std::string p) {
120  pmapfn_m = p;
121 }
122 
123 std::string Vacuum::getPressureMapFN() const {
124  return pmapfn_m;
125 }
126 
127 void Vacuum::setPScale(double ps) {
128  pscale_m = ps;
129 }
130 
131 double Vacuum::getPScale() const {
132  if (pscale_m > 0.0) {
133  return pscale_m;
134  } else {
135  throw LogicalError("Vacuum::getPScale",
136  "PScale must be positive");
137  }
138 }
139 
140 void Vacuum::setResidualGas(std::string gas) {
141  if (gas == "AIR") {
143  } else if (gas == "H2") {
145  }
146 }
147 
149  return gas_m;
150 }
151 
153  switch (gas_m) {
154  case ResidualGas::AIR: {
155  return "AIR";
156  }
157  case ResidualGas::H2: {
158  return "H2";
159  }
160  default: {
161  throw GeneralClassicException("Vacuum::getResidualGasName",
162  "Residual gas not set");
163  }
164  }
165 }
166 
167 void Vacuum::setStop(bool stopflag) {
168  stop_m = stopflag;
169 }
170 
171 bool Vacuum::getStop() const {
172  return stop_m;
173 }
174 
175 
177 
178  bool flagNeedUpdate = false;
179 
180  Vector_t rmin, rmax;
181  bunch->get_bounds(rmin, rmax);
182  std::pair<Vector_t, double> boundingSphere;
183  boundingSphere.first = 0.5 * (rmax + rmin);
184  boundingSphere.second = euclidean_norm(rmax - boundingSphere.first);
185 
186  maxr_m = cycl->getMaxR();
187  minr_m = cycl->getMinR();
188  maxz_m = cycl->getMaxZ();
189  minz_m = cycl->getMinZ();
190 
191  size_t tempnum = bunch->getLocalNum();
192  for (unsigned int i = 0; i < tempnum; ++i) {
193  int pflag = checkPoint(bunch->R[i](0), bunch->R[i](1), bunch->R[i](2));
194  if ( (pflag != 0) && (bunch->Bin[i] != -1) )
195  flagNeedUpdate = true;
196  }
197  reduce(&flagNeedUpdate, &flagNeedUpdate + 1, &flagNeedUpdate, OpBitwiseOrAssign());
198  if (flagNeedUpdate && parmatint_m) {
199  dynamic_cast<BeamStrippingPhysics*>(parmatint_m)->setCyclotron(cycl);
200  parmatint_m->apply(bunch, boundingSphere);
201  }
202  return flagNeedUpdate;
203 }
204 
205 
206 void Vacuum::initialise(PartBunchBase<double, 3>* bunch, double& startField, double& endField) {
207  endField = startField + getElementLength();
208  initialise(bunch, pscale_m);
209 }
210 
211 void Vacuum::initialise(PartBunchBase<double, 3>* bunch, const double& scaleFactor) {
212 
213  RefPartBunch_m = bunch;
214 
216 
217  if (pmapfn_m != "") {
218  getPressureFromFile(scaleFactor);
219  // calculate the radii of initial grid.
221  }
222 
223  goOnline(-1e6);
224 
225  // change the mass and charge to simulate real particles
226  for (size_t i = 0; i < bunch->getLocalNum(); ++i) {
227  bunch->M[i] = bunch->getM()*1E-9;
228  bunch->Q[i] = bunch->getQ() * Physics::q_e;
229  if (bunch->weHaveBins())
230  bunch->Bin[bunch->getLocalNum()-1] = bunch->Bin[i];
231  }
232 }
233 
235  if (online_m)
236  goOffline();
237  *gmsg << "* Finalize vacuum" << endl;
238 }
239 
240 void Vacuum::goOnline(const double &) {
241 }
242 
244  online_m = false;
245 }
246 
247 bool Vacuum::bends() const {
248  return false;
249 }
250 
251 void Vacuum::getDimensions(double& /*zBegin*/, double& /*zEnd*/) const {}
252 
254  return VACUUM;
255 }
256 
257 std::string Vacuum::getVacuumShape() {
258  return "Vacuum";
259 }
260 
261 int Vacuum::checkPoint(const double& x, const double& y, const double& z) {
262  int cn;
263  double rpos = std::sqrt(x * x + y * y);
264  if (z >= maxz_m || z <= minz_m || rpos >= maxr_m || rpos <= minr_m) {
265  cn = 0;
266  } else {
267  cn = 1;
268  }
269  return (cn); // 0 if out, and 1 if in
270 }
271 
272 double Vacuum::checkPressure(const double& x, const double& y) {
273 
274  double pressure = 0.0;
275 
276  if (pmapfn_m != "") {
277  const double rad = std::sqrt(x * x + y * y);
278  const double xir = (rad - PP.rmin) / PP.delr;
279 
280  // ir : the number of path whose radius is less than the 4 points of cell which surround the particle.
281  const int ir = (int)xir;
282  // wr1 : the relative distance to the inner path radius
283  const double wr1 = xir - (double)ir;
284  // wr2 : the relative distance to the outer path radius
285  const double wr2 = 1.0 - wr1;
286 
287  const double tempv = std::atan(y / x);
288  double tet = tempv;
289  if ((x < 0) && (y >= 0)) tet = Physics::pi + tempv;
290  else if ((x < 0) && (y <= 0)) tet = Physics::pi + tempv;
291  else if ((x > 0) && (y <= 0)) tet = Physics::two_pi + tempv;
292  else if ((x == 0) && (y > 0)) tet = Physics::pi / 2.0;
293  else if ((x == 0) && (y < 0)) tet = 1.5 * Physics::pi;
294 
295  // the actual angle of particle
296  tet = tet * Physics::rad2deg;
297 
298  // the corresponding angle on the field map
299  // Note: this does not work if the start point of field map does not equal zero.
300  double xit = tet / PP.dtet;
301  int it = (int) xit;
302  const double wt1 = xit - (double)it;
303  const double wt2 = 1.0 - wt1;
304  // it : the number of point on the inner path whose angle is less than the particle' corresponding angle.
305  // include zero degree point
306  it++;
307  double epsilon = 0.06;
308  if (tet > 360 - epsilon && tet < 360 + epsilon) it = 0;
309 
310  int r1t1, r2t1, r1t2, r2t2;
311  // r1t1 : the index of the "min angle, min radius" point in the 2D field array.
312  // considering the array start with index of zero, minus 1.
313 
314  r1t1 = idx(ir, it);
315  r2t1 = idx(ir + 1, it);
316  r1t2 = idx(ir, it + 1);
317  r2t2 = idx(ir + 1, it + 1);
318 
319  if ((it >= 0) && (ir >= 0) && (it < PField.ntetS) && (ir < PField.nrad)) {
320  pressure = (PField.pfld[r1t1] * wr2 * wt2 +
321  PField.pfld[r2t1] * wr1 * wt2 +
322  PField.pfld[r1t2] * wr2 * wt1 +
323  PField.pfld[r2t2] * wr1 * wt1);
324  if (pressure <= 0.0) {
325  *gmsg << level4 << getName() << ": Pressure data from file zero." << endl;
326  *gmsg << level4 << getName() << ": Take constant value through Vacuum::getPressure" << endl;
327  pressure = getPressure();
328  }
329  } else if (ir >= PField.nrad) {
330  *gmsg << level4 << getName() << ": Particle out of maximum radial position of pressure field map." << endl;
331  *gmsg << level4 << getName() << ": Take constant value through Vacuum::getPressure" << endl;
332  pressure = getPressure();
333  } else {
334  throw GeneralClassicException("Vacuum::checkPressure",
335  "Pressure data not found");
336  }
337  } else {
338  pressure = getPressure();
339  }
340 
341  return pressure;
342 }
343 
344 // Calculates radius of initial grid (dimensions in [m]!)
345 void Vacuum::initR(double rmin, double dr, int nrad) {
346  PP.rarr.resize(nrad);
347  for (int i = 0; i < nrad; i++)
348  PP.rarr[i] = rmin + i * dr;
349 
350  PP.delr = dr;
351 }
352 
353 // Read pressure map from external file.
354 void Vacuum::getPressureFromFile(const double& scaleFactor) {
355 
356  FILE* f = NULL;
357 
358  *gmsg << "* " << endl;
359  *gmsg << "* Reading pressure field map " << endl;
360 
361  PP.Pfact = scaleFactor;
362 
363  if ((f = std::fopen(pmapfn_m.c_str(), "r")) == NULL) {
364  throw GeneralClassicException("Vacuum::getPressureFromFile",
365  "failed to open file '" + pmapfn_m +
366  "', please check if it exists");
367  }
368 
369  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%lf", &PP.rmin));
370  *gmsg << "* --- Minimal radius of measured pressure map: " << PP.rmin << " [mm]" << endl;
371 
372  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%lf", &PP.delr));
373  //if the value is negative, the actual value is its reciprocal.
374  if (PP.delr < 0.0) PP.delr = 1.0 / (-PP.delr);
375  *gmsg << "* --- Stepsize in radial direction: " << PP.delr << " [mm]" << endl;
376 
377  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%lf", &PP.tetmin));
378  *gmsg << "* --- Minimal angle of measured pressure map: " << PP.tetmin << " [deg]" << endl;
379 
380  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%lf", &PP.dtet));
381  //if the value is negative, the actual value is its reciprocal.
382  if (PP.dtet < 0.0) PP.dtet = 1.0 / (-PP.dtet);
383  *gmsg << "* --- Stepsize in azimuthal direction: " << PP.dtet << " [deg]" << endl;
384 
385  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%d", &PField.ntet));
386  *gmsg << "* --- Grid points along azimuth (ntet): " << PField.ntet << endl;
387 
388  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%d", &PField.nrad));
389  *gmsg << "* --- Grid points along radius (nrad): " << PField.nrad << endl;
390  *gmsg << "* --- Maximum radial position: " << PP.rmin + (PField.nrad-1)*PP.delr << " [mm]" << endl;
391  PP.rmin *= 0.001; // mm --> m
392  PP.delr *= 0.001; // mm --> m
393 
394  PField.ntetS = PField.ntet + 1;
395  *gmsg << "* --- Adding a guard cell along azimuth" << endl;
396 
398  PField.pfld.resize(PField.ntot);
399  *gmsg << "* --- Total stored grid point number ((ntet+1) * nrad) : " << PField.ntot << endl;
400  *gmsg << "* --- Escale factor: " << PP.Pfact << endl;
401 
402  for (int i = 0; i < PField.nrad; i++) {
403  for (int k = 0; k < PField.ntet; k++) {
404  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%16lE", &(PField.pfld[idx(i, k)])));
405  PField.pfld[idx(i, k)] *= PP.Pfact;
406  }
407  }
408 
409  std::fclose(f);
410 }
411 
412 #undef CHECK_VAC_FSCANF_EOF
#define CHECK_VAC_FSCANF_EOF(arg)
Definition: Vacuum.cpp:42
Inform * gmsg
Definition: Main.cpp:62
ResidualGas
Definition: Vacuum.h:61
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
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
Definition: GlobalComm.hpp:55
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level4(Inform &inf)
Definition: Inform.cpp:48
const std::string name
constexpr double two_pi
The value of.
Definition: Physics.h:33
constexpr double q_e
The elementary charge in As.
Definition: Physics.h:75
constexpr double pi
The value of.
Definition: Physics.h:30
constexpr double rad2deg
The conversion factor from radians to degrees.
Definition: Physics.h:45
T rad(T x)
Convert degrees to radians.
Definition: matheval.hpp:78
ParticlePos_t & R
ParticleAttrib< int > Bin
double getQ() const
Access to reference data.
size_t getLocalNum() const
ParticleAttrib< double > M
bool weHaveBins() const
ParticleAttrib< double > Q
void get_bounds(Vector_t &rmin, Vector_t &rmax)
double getM() const
virtual void visitVacuum(const Vacuum &)=0
Apply the algorithm to a vacuum space.
Interface for a single beam element.
Definition: Component.h:50
bool online_m
Definition: Component.h:195
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:194
virtual double getMaxR() const
Definition: Cyclotron.cpp:320
virtual double getMaxZ() const
Definition: Cyclotron.cpp:340
virtual double getMinZ() const
Definition: Cyclotron.cpp:330
virtual double getMinR() const
Definition: Cyclotron.cpp:316
virtual const std::string & getName() const
Get element name.
virtual ParticleMatterInteractionHandler * getParticleMatterInteraction() const
Definition: ElementBase.h:500
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:432
int ntet
Definition: Vacuum.h:41
int ntetS
Definition: Vacuum.h:44
int ntot
Definition: Vacuum.h:47
std::vector< double > pfld
Definition: Vacuum.h:37
int nrad
Definition: Vacuum.h:41
std::vector< double > rarr
Definition: Vacuum.h:56
double Pfact
Definition: Vacuum.h:58
double rmin
Definition: Vacuum.h:52
double tetmin
Definition: Vacuum.h:53
double dtet
Definition: Vacuum.h:53
double delr
Definition: Vacuum.h:52
Definition: Vacuum.h:67
PFieldData PField
Definition: Vacuum.h:156
double minr_m
Flag if particles should be stripped or stopped.
Definition: Vacuum.h:146
virtual ElementBase::ElementType getType() const
Get element type std::string.
Definition: Vacuum.cpp:253
double pressure_m
Definition: Vacuum.h:138
void setPScale(double ps)
Definition: Vacuum.cpp:127
bool stop_m
K.
Definition: Vacuum.h:142
double pscale_m
stores the filename of the pressure map
Definition: Vacuum.h:140
double getPressure() const
Definition: Vacuum.cpp:97
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField)
Definition: Vacuum.cpp:206
virtual std::string getPressureMapFN() const
Definition: Vacuum.cpp:123
void initR(double rmin, double dr, int nrad)
Definition: Vacuum.cpp:345
void setTemperature(double temperature)
Definition: Vacuum.cpp:106
virtual ~Vacuum()
Definition: Vacuum.cpp:83
double minz_m
mm
Definition: Vacuum.h:148
virtual void goOffline()
Definition: Vacuum.cpp:243
int idx(int irad, int ktet)
Definition: Vacuum.h:132
double temperature_m
a scale factor for the P-field
Definition: Vacuum.h:141
ResidualGas getResidualGas() const
Definition: Vacuum.cpp:148
virtual double getPScale() const
Definition: Vacuum.cpp:131
virtual void getDimensions(double &zBegin, double &zEnd) const
Definition: Vacuum.cpp:251
virtual void finalise()
Definition: Vacuum.cpp:234
double checkPressure(const double &x, const double &y)
Definition: Vacuum.cpp:272
PPositions PP
Definition: Vacuum.h:159
void setPressureMapFN(std::string pmapfn)
Definition: Vacuum.cpp:119
std::string getVacuumShape()
Definition: Vacuum.cpp:257
virtual void accept(BeamlineVisitor &) const
Apply visitor to Vacuum.
Definition: Vacuum.cpp:89
virtual void goOnline(const double &kineticEnergy)
Definition: Vacuum.cpp:240
void setPressure(double pressure)
Definition: Vacuum.cpp:93
virtual bool checkVacuum(PartBunchBase< double, 3 > *bunch, Cyclotron *cycl)
Definition: Vacuum.cpp:176
ParticleMatterInteractionHandler * parmatint_m
mm
Definition: Vacuum.h:152
std::string pmapfn_m
mbar
Definition: Vacuum.h:139
double getTemperature() const
Definition: Vacuum.cpp:110
void setResidualGas(std::string gas)
Definition: Vacuum.cpp:140
void getPressureFromFile(const double &scaleFactor)
Definition: Vacuum.cpp:354
std::string getResidualGasName()
Definition: Vacuum.cpp:152
double maxr_m
mm
Definition: Vacuum.h:147
int checkPoint(const double &x, const double &y, const double &z)
Definition: Vacuum.cpp:261
Vacuum()
Definition: Vacuum.cpp:49
virtual bool getStop() const
Definition: Vacuum.cpp:171
double maxz_m
mm
Definition: Vacuum.h:149
virtual bool bends() const
Definition: Vacuum.cpp:247
ResidualGas gas_m
parameters for Vacuum
Definition: Vacuum.h:137
void setStop(bool stopflag)
Definition: Vacuum.cpp:167
virtual void apply(PartBunchBase< double, 3 > *bunch, const std::pair< Vector_t, double > &boundingSphere)=0
Logical error exception.
Definition: LogicalError.h:33
Definition: Inform.h:42