OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
Vacuum.cpp
Go to the documentation of this file.
1 //
2 // Class Vacuum
3 // Defines the abstract interface for vacuum.
4 //
5 // Copyright (c) 2018 - 2021, Pedro Calvo, CIEMAT, Spain
6 // All rights reserved.
7 //
8 // Implemented as part of the PhD thesis
9 // "Optimizing the radioisotope production of the novel AMIT
10 // superconducting weak focusing cyclotron"
11 //
12 // This file is part of OPAL.
13 //
14 // OPAL is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
21 //
22 #include "AbsBeamline/Vacuum.h"
23 
27 #include "Physics/Physics.h"
28 #include "Physics/Units.h"
32 #include "Utilities/LogicalError.h"
33 
34 #include <boost/assign.hpp>
35 
36 #include <cmath>
37 #include <cstdio>
38 #include <filesystem>
39 #include <fstream>
40 #include <iostream>
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 const boost::bimap<ResidualGas, std::string> Vacuum::bmResidualGasString_s =
49  boost::assign::list_of<const boost::bimap<ResidualGas, std::string>::relation>
50  (ResidualGas::NOGAS, "NOGAS")
51  (ResidualGas::AIR, "AIR")
52  (ResidualGas::H2, "H2");
53 
54 
56  Vacuum("")
57 {}
58 
59 
60 Vacuum::Vacuum(const Vacuum& right):
61  Component(right),
62  gas_m(right.gas_m),
63  pressure_m(right.pressure_m),
64  pmapfn_m(right.pmapfn_m),
65  pscale_m(right.pscale_m),
66  temperature_m(right.temperature_m),
67  stop_m(right.stop_m),
68  minr_m(right.minr_m),
69  maxr_m(right.maxr_m),
70  minz_m(right.minz_m),
71  maxz_m(right.maxz_m),
72  parmatint_m(nullptr)
73 {}
74 
75 
76 Vacuum::Vacuum(const std::string& name):
77  Component(name),
78  gas_m(ResidualGas::NOGAS),
79  pressure_m(0.0),
80  pmapfn_m(""),
81  pscale_m(1.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(nullptr)
89 {}
90 
91 
93  if (online_m)
94  goOffline();
95 }
96 
97 
98 void Vacuum::accept(BeamlineVisitor& visitor) const {
99  visitor.visitVacuum(*this);
100 }
101 
102 void Vacuum::setResidualGas(std::string gas) {
103  auto it = bmResidualGasString_s.right.find(gas);
104  if (it != bmResidualGasString_s.right.end()) {
105  gas_m = it->second;
106  } else {
108  }
109 }
110 
112  return gas_m;
113 }
114 
116  if (gas_m != ResidualGas::NOGAS) {
117  return bmResidualGasString_s.left.at(gas_m);
118  } else {
119  throw GeneralClassicException("Vacuum::getResidualGasName",
120  "Residual gas not set");
121  }
122 }
123 
124 void Vacuum::setPressure(double pressure) {
125  pressure_m = pressure;
126 }
127 
128 double Vacuum::getPressure() const {
129  if (pressure_m > 0.0) {
130  return pressure_m;
131  } else {
132  throw LogicalError("Vacuum::getPressure",
133  "Pressure must be positive");
134  }
135 }
136 
137 void Vacuum::setPressureMapFN(std::string p) {
138  pmapfn_m = p;
139 }
140 
141 std::string Vacuum::getPressureMapFN() const {
142  return pmapfn_m;
143 }
144 
145 void Vacuum::setPScale(double ps) {
146  pscale_m = ps;
147 }
148 
149 double Vacuum::getPScale() const {
150  if (pscale_m > 0.0) {
151  return pscale_m;
152  } else {
153  throw LogicalError("Vacuum::getPScale",
154  "PScale must be positive");
155  }
156 }
157 
158 void Vacuum::setTemperature(double temperature) {
159  temperature_m = temperature;
160 }
161 
162 double Vacuum::getTemperature() const {
163  if (temperature_m > 0.0) {
164  return temperature_m;
165  } else {
166  throw LogicalError("Vacuum::getTemperature",
167  "Temperature must be positive");
168  }
169 }
170 
171 void Vacuum::setStop(bool stopflag) {
172  stop_m = stopflag;
173 }
174 
175 bool Vacuum::getStop() const {
176  return stop_m;
177 }
178 
180  bool hit = false;
181  if (OpalData::getInstance()->isInOPALCyclMode()) {
182  double rpos = std::sqrt(R(0) * R(0) + R(1) * R(1));
183  if (R(2) <= maxz_m || R(2) >= minz_m || rpos <= maxr_m || rpos >= minr_m) {
184  hit = true;
185  }
186  } else {
187  hit = ((R(2) > 0.0) && (R(2) <= getElementLength()));
188  }
189  return hit;
190 }
191 
192 bool Vacuum::apply(const size_t& /*i*/, const double& /*t*/, Vector_t& /*E*/, Vector_t& /*B*/) {
193  return false;
194 }
195 
196 bool Vacuum::applyToReferenceParticle(const Vector_t& /*R*/, const Vector_t& /*P*/,
197  const double& /*t*/, Vector_t& /*E*/, Vector_t& /*B*/) {
198  return false;
199 }
200 
202 
203  bool flagNeedUpdate = false;
204 
205  Vector_t rmin, rmax;
206  bunch->get_bounds(rmin, rmax);
207  std::pair<Vector_t, double> boundingSphere;
208  boundingSphere.first = 0.5 * (rmax + rmin);
209  boundingSphere.second = euclidean_norm(rmax - boundingSphere.first);
210 
211  maxr_m = cycl->getMaxR();
212  minr_m = cycl->getMinR();
213  maxz_m = cycl->getMaxZ();
214  minz_m = cycl->getMinZ();
215 
216  size_t tempnum = bunch->getLocalNum();
217  for (unsigned int i = 0; i < tempnum; ++i) {
218  int pflag = checkPoint(bunch->R[i]);
219  if ( (pflag != 0) && (bunch->Bin[i] != -1) )
220  flagNeedUpdate = true;
221  }
222 
223  reduce(&flagNeedUpdate, &flagNeedUpdate + 1, &flagNeedUpdate, OpBitwiseOrAssign());
224 
225  if (flagNeedUpdate && parmatint_m) {
226  dynamic_cast<BeamStrippingPhysics*>(parmatint_m)->setCyclotron(cycl);
227  parmatint_m->apply(bunch, boundingSphere);
228  parmatint_m->print(*gmsg);
229  }
230  return flagNeedUpdate;
231 }
232 
233 void Vacuum::initialise(PartBunchBase<double, 3>* bunch, double& startField, double& endField) {
234 
235  endField = startField + getElementLength();
236 
237  initialise(bunch);
238 
239  print();
240 }
241 
243 
244  RefPartBunch_m = bunch;
245 
247 
248  goOnline(-1e6);
249 
251 
252  if (std::filesystem::exists(pmapfn_m)) {
254  // calculate the radii of initial grid.
256  }
257 }
258 
260  for (size_t i = 0; i < RefPartBunch_m->getLocalNum(); ++i) {
263  }
264 }
265 
267  *gmsg << "* Finalize vacuum " << getName() << endl;
268  if (online_m)
269  goOffline();
270 }
271 
272 void Vacuum::goOnline(const double&) {
273  online_m = true;
274 }
275 
277  *gmsg << level2 << "\n" << parmatint_m->getElement()->getTypeString()
278  << ": " << getName() << " -> Residual gas = "
279  << getResidualGasName() << endl;
280  *gmsg << level2 << parmatint_m->getElement()->getTypeString()
281  << ": " << getName() << " -> Pressure level = "
282  << std::scientific << pressure_m << " [mbar]" << endl;
283 }
284 
286  online_m = false;
287 }
288 
289 void Vacuum::getDimensions(double& zBegin, double& zEnd) const {
290  zBegin = 0.0;
291  zEnd = getElementLength();
292 }
293 
295  return ElementType::VACUUM;
296 }
297 
299 
300  const double x = R(0);
301  const double y = R(1);
302  double pressure = 0.0;
303 
304  if (pmapfn_m.empty()) {
305  pressure = getPressure();
306  } else {
307  const double rad = std::sqrt(x * x + y * y);
308  const double xir = (rad - PP_m.rmin_m) / PP_m.delr_m;
309 
310  // ir: the number of path whose radius is less than the 4 points of cell which surround the particle.
311  const int ir = (int)xir;
312  // wr1: the relative distance to the inner path radius
313  const double wr1 = xir - (double)ir;
314  // wr2: the relative distance to the outer path radius
315  const double wr2 = 1.0 - wr1;
316 
317  const double tempv = std::atan(y / x);
318  double tet = tempv;
319  if ((x < 0) && (y >= 0)) tet = Physics::pi + tempv;
320  else if ((x < 0) && (y <= 0)) tet = Physics::pi + tempv;
321  else if ((x > 0) && (y <= 0)) tet = Physics::two_pi + tempv;
322  else if ((x == 0) && (y > 0)) tet = Physics::pi / 2.0;
323  else if ((x == 0) && (y < 0)) tet = 1.5 * Physics::pi;
324 
325  // the actual angle of particle
326  tet = tet * Units::rad2deg;
327 
328  // the corresponding angle on the field map
329  // Note: this does not work if the start point of field map does not equal zero.
330  double xit = tet / PP_m.dtet_m;
331  int it = (int) xit;
332  const double wt1 = xit - (double)it;
333  const double wt2 = 1.0 - wt1;
334  // it : the number of point on the inner path whose angle is less than the particle' corresponding angle.
335  // include zero degree point
336  it++;
337  double epsilon = 0.06;
338  if (tet > 360 - epsilon && tet < 360 + epsilon) it = 0;
339 
340  int r1t1, r2t1, r1t2, r2t2;
341  // r1t1 : the index of the "min angle, min radius" point in the 2D field array.
342  // considering the array start with index of zero, minus 1.
343 
344  r1t1 = idx(ir, it);
345  r2t1 = idx(ir + 1, it);
346  r1t2 = idx(ir, it + 1);
347  r2t2 = idx(ir + 1, it + 1);
348 
349  if ((it >= 0) && (ir >= 0) && (it < PField_m.ntetS_m) && (ir < PField_m.nrad_m)) {
350  pressure = (PField_m.pfld_m[r1t1] * wr2 * wt2 +
351  PField_m.pfld_m[r2t1] * wr1 * wt2 +
352  PField_m.pfld_m[r1t2] * wr2 * wt1 +
353  PField_m.pfld_m[r2t2] * wr1 * wt1);
354  if (pressure <= 0.0) {
355  *gmsg << level4 << getName() << ": Pressure data from file zero." << endl;
356  *gmsg << level4 << getName() << ": Take constant value through Vacuum::getPressure" << endl;
357  pressure = getPressure();
358  }
359  } else if (ir >= PField_m.nrad_m) {
360  *gmsg << level4 << getName() << ": Particle out of maximum radial position of pressure field map." << endl;
361  *gmsg << level4 << getName() << ": Take constant value through Vacuum::getPressure" << endl;
362  pressure = getPressure();
363  } else {
364  throw GeneralClassicException("Vacuum::checkPressure",
365  "Pressure data not found");
366  }
367  }
368  return pressure;
369 }
370 
371 // Calculates radius of initial grid (dimensions in [m]!)
372 void Vacuum::initR(double rmin_m, double dr, int nrad_m) {
373  PP_m.rarr_m.resize(nrad_m);
374  for (int i = 0; i < nrad_m; i++) {
375  PP_m.rarr_m[i] = rmin_m + i * dr;
376  }
377  PP_m.delr_m = dr;
378 }
379 
380 // Read pressure map from external file.
382 
383  *gmsg << "* " << endl;
384  *gmsg << "* Reading pressure field map " << endl;
385 
387  FILE* f = nullptr;
388  if ((f = std::fopen(pmapfn_m.c_str(), "r")) == nullptr) {
389  throw GeneralClassicException("Vacuum::getPressureFromFile",
390  "failed to open file '" + pmapfn_m +
391  "', please check if it exists");
392  }
393 
394  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%lf", &PP_m.rmin_m));
395  *gmsg << "* --- Minimal radius of measured pressure map: " << PP_m.rmin_m << " [mm]" << endl;
396 
397  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%lf", &PP_m.delr_m));
398  //if the value is negative, the actual value is its reciprocal.
399  if (PP_m.delr_m < 0.0) PP_m.delr_m = 1.0 / (-PP_m.delr_m);
400  *gmsg << "* --- Stepsize in radial direction: " << PP_m.delr_m << " [mm]" << endl;
401 
402  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%lf", &PP_m.tetmin_m));
403  *gmsg << "* --- Minimal angle of measured pressure map: " << PP_m.tetmin_m << " [deg]" << endl;
404 
405  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%lf", &PP_m.dtet_m));
406  //if the value is negative, the actual value is its reciprocal.
407  if (PP_m.dtet_m < 0.0) PP_m.dtet_m = 1.0 / (-PP_m.dtet_m);
408  *gmsg << "* --- Stepsize in azimuthal direction: " << PP_m.dtet_m << " [deg]" << endl;
409 
410  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%d", &PField_m.ntet_m));
411  *gmsg << "* --- Grid points along azimuth (ntet_m): " << PField_m.ntet_m << endl;
412 
413  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%d", &PField_m.nrad_m));
414  *gmsg << "* --- Grid points along radius (nrad_m): " << PField_m.nrad_m << endl;
415  *gmsg << "* --- Maximum radial position: " << PP_m.rmin_m + (PField_m.nrad_m-1)*PP_m.delr_m << " [mm]" << endl;
418 
420  *gmsg << "* --- Adding a guard cell along azimuth" << endl;
421 
423  PField_m.pfld_m.resize(PField_m.ntot_m);
424  *gmsg << "* --- Total stored grid point number ((ntet_m+1) * nrad_m) : " << PField_m.ntot_m << endl;
425  *gmsg << "* --- Escale factor: " << PP_m.Pfact_m << endl;
426 
427  for (int i = 0; i < PField_m.nrad_m; i++) {
428  for (int k = 0; k < PField_m.ntet_m; k++) {
429  CHECK_VAC_FSCANF_EOF(std::fscanf(f, "%16lE", &(PField_m.pfld_m[idx(i, k)])));
430  PField_m.pfld_m[idx(i, k)] *= PP_m.Pfact_m;
431  }
432  }
433 
434  std::fclose(f);
435 }
436 
437 #undef CHECK_VAC_FSCANF_EOF
virtual ~Vacuum()
Definition: Vacuum.cpp:92
static OpalData * getInstance()
Definition: OpalData.cpp:196
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
virtual void goOffline() override
Definition: Vacuum.cpp:285
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the so that any problems introduced by others will not reflect on the original authors reputations any free program is threatened constantly by software patents We wish to avoid the danger that redistributors of a free program will individually obtain patent in effect making the program proprietary To prevent we have made it clear that any patent must be licensed for everyone s free use or not licensed at all The precise terms and conditions for distribution and modification follow GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR DISTRIBUTION AND MODIFICATION This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License The refers to any such program or and a work based on the Program means either the Program or any derivative work under copyright a work containing the Program or a portion of it
Definition: LICENSE:43
T rad(T x)
Convert degrees to radians.
Definition: matheval.hpp:79
constexpr double two_pi
The value of .
Definition: Physics.h:33
ResidualGas
Definition: Vacuum.h:55
virtual bool checkVacuum(PartBunchBase< double, 3 > *bunch, Cyclotron *cycl)
Definition: Vacuum.cpp:201
virtual void visitVacuum(const Vacuum &)=0
Apply the algorithm to a vacuum space.
double maxr_m
mm
Definition: Vacuum.h:149
virtual void print(Inform &os)=0
double maxz_m
mm
Definition: Vacuum.h:151
void initR(double rmin, double dr, int nrad)
Definition: Vacuum.cpp:372
int ntot_m
Definition: Vacuum.h:41
double tetmin_m
Definition: Vacuum.h:47
void updateParticleAttributes()
Definition: Vacuum.cpp:259
ParticleMatterInteractionHandler * parmatint_m
Definition: Vacuum.h:154
void get_bounds(Vector_t &rmin, Vector_t &rmax) const
void getPressureFromFile()
Definition: Vacuum.cpp:381
ParticleAttrib< double > M
double minr_m
size limits took from cyclotron
Definition: Vacuum.h:148
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
double delr_m
Definition: Vacuum.h:46
double getTemperature() const
Definition: Vacuum.cpp:162
std::string getTypeString() const
Definition: ElementBase.h:579
Definition: Vacuum.h:61
virtual const std::string & getName() const
Get element name.
int idx(int irad, int ktet)
Definition: Vacuum.h:127
double getQ() const
Access to reference data.
constexpr double pi
The value of .
Definition: Physics.h:30
std::string pmapfn_m
mbar
Definition: Vacuum.h:141
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: Vacuum.cpp:233
double getM() const
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
ResidualGas gas_m
parameters for Vacuum
Definition: Vacuum.h:139
void setPressure(double pressure)
Definition: Vacuum.cpp:124
std::string getPressureMapFN() const
Definition: Vacuum.cpp:141
double rmin_m
Definition: Vacuum.h:46
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
double pscale_m
stores the filename of the pressure map
Definition: Vacuum.h:142
bool stop_m
K.
Definition: Vacuum.h:144
double Pfact_m
Definition: Vacuum.h:52
virtual void accept(BeamlineVisitor &) const override
Apply visitor to Vacuum.
Definition: Vacuum.cpp:98
int ntetS_m
Definition: Vacuum.h:40
double checkPressure(const Vector_t &R)
Definition: Vacuum.cpp:298
bool online_m
Definition: Component.h:192
double getPScale() const
Definition: Vacuum.cpp:149
constexpr double mm2m
Definition: Units.h:29
virtual double getMaxZ() const
Definition: Cyclotron.cpp:347
Inform & level4(Inform &inf)
Definition: Inform.cpp:48
size_t getLocalNum() const
PPositions PP_m
Definition: Vacuum.h:164
Definition: Inform.h:42
double minz_m
mm
Definition: Vacuum.h:150
ElementType
Definition: ElementBase.h:88
void setPressureMapFN(std::string pmapfn)
Definition: Vacuum.cpp:137
ParticleAttrib< double > Q
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:415
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Definition: Vacuum.cpp:192
virtual ElementType getType() const override
Get element type std::string.
Definition: Vacuum.cpp:294
virtual void apply(PartBunchBase< double, 3 > *bunch, const std::pair< Vector_t, double > &boundingSphere)=0
void setTemperature(double temperature)
Definition: Vacuum.cpp:158
constexpr double q_e
The elementary charge in As.
Definition: Physics.h:69
void print()
Definition: Vacuum.cpp:276
int ntet_m
Definition: Vacuum.h:39
bool checkPoint(const Vector_t &R)
Definition: Vacuum.cpp:179
double temperature_m
a scale factor for the P-field
Definition: Vacuum.h:143
double dtet_m
Definition: Vacuum.h:47
virtual double getMaxR() const
Definition: Cyclotron.cpp:326
void setPScale(double ps)
Definition: Vacuum.cpp:145
constexpr double rad2deg
Definition: Units.h:146
PFieldData PField_m
Definition: Vacuum.h:161
const std::string name
virtual void getDimensions(double &zBegin, double &zEnd) const override
Definition: Vacuum.cpp:289
ParticlePos_t & R
virtual double getMinR() const
Definition: Cyclotron.cpp:317
virtual ParticleMatterInteractionHandler * getParticleMatterInteraction() const
Definition: ElementBase.h:483
constexpr double eV2GeV
Definition: Units.h:71
virtual void finalise() override
Definition: Vacuum.cpp:266
double pressure_m
Type of gas for residual vacuum.
Definition: Vacuum.h:140
static const boost::bimap< ResidualGas, std::string > bmResidualGasString_s
Definition: Vacuum.h:156
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
ParticleAttrib< int > Bin
std::vector< double > rarr_m
Definition: Vacuum.h:50
std::vector< double > pfld_m
Definition: Vacuum.h:38
Interface for a single beam element.
Definition: Component.h:50
ResidualGas getResidualGas() const
Definition: Vacuum.cpp:111
std::string getResidualGasName()
Definition: Vacuum.cpp:115
Logical error exception.
Definition: LogicalError.h:33
virtual bool applyToReferenceParticle(const Vector_t &R, const Vector_t &P, const double &t, Vector_t &E, Vector_t &B) override
Definition: Vacuum.cpp:196
int nrad_m
Definition: Vacuum.h:39
void setStop(bool stopflag)
Definition: Vacuum.cpp:171
void setResidualGas(std::string gas)
Definition: Vacuum.cpp:102
double getPressure() const
Definition: Vacuum.cpp:128
Vacuum()
Definition: Vacuum.cpp:55
Inform * gmsg
Definition: Main.cpp:70
#define CHECK_VAC_FSCANF_EOF(arg)
Definition: Vacuum.cpp:42
bool getStop() const
Definition: Vacuum.cpp:175
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
Definition: GlobalComm.hpp:55
virtual double getMinZ() const
Definition: Cyclotron.cpp:339
virtual void goOnline(const double &kineticEnergy) override
Definition: Vacuum.cpp:272