OPAL (Object Oriented Parallel Accelerator Library) 2022.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"
33
34#include <boost/assign.hpp>
35#include <boost/filesystem.hpp>
36
37#include <cmath>
38#include <cstdio>
39#include <fstream>
40#include <iostream>
41
42#define CHECK_VAC_FSCANF_EOF(arg) if (arg == EOF)\
43throw GeneralClassicException("Vacuum::getPressureFromFile",\
44 "fscanf returned EOF at " #arg);
45
46extern Inform *gmsg;
47
48const 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
60Vacuum::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
76Vacuum::Vacuum(const std::string& 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
98void Vacuum::accept(BeamlineVisitor& visitor) const {
99 visitor.visitVacuum(*this);
100}
101
102void 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
124void Vacuum::setPressure(double pressure) {
125 pressure_m = pressure;
126}
127
128double 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
137void Vacuum::setPressureMapFN(std::string p) {
138 pmapfn_m = p;
139}
140
141std::string Vacuum::getPressureMapFN() const {
142 return pmapfn_m;
143}
144
145void Vacuum::setPScale(double ps) {
146 pscale_m = ps;
147}
148
149double 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
158void Vacuum::setTemperature(double temperature) {
159 temperature_m = temperature;
160}
161
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
171void Vacuum::setStop(bool stopflag) {
172 stop_m = stopflag;
173}
174
175bool 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
192bool Vacuum::apply(const size_t& /*i*/, const double& /*t*/, Vector_t& /*E*/, Vector_t& /*B*/) {
193 return false;
194}
195
196bool 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);
229 }
230 return flagNeedUpdate;
231}
232
233void 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 (boost::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
272void 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;
281 << ": " << getName() << " -> Pressure level = "
282 << std::scientific << pressure_m << " [mbar]" << endl;
283}
284
286 online_m = false;
287}
288
289void 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]!)
372void 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
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
#define CHECK_VAC_FSCANF_EOF(arg)
Definition: Vacuum.cpp:42
Inform * gmsg
Definition: Main.cpp:61
ResidualGas
Definition: Vacuum.h:55
ElementType
Definition: ElementBase.h:88
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 & level2(Inform &inf)
Definition: Inform.cpp:46
Inform & level4(Inform &inf)
Definition: Inform.cpp:48
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
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:69
constexpr double pi
The value of.
Definition: Physics.h:30
constexpr double mm2m
Definition: Units.h:29
constexpr double eV2GeV
Definition: Units.h:71
constexpr double rad2deg
Definition: Units.h:146
T rad(T x)
Convert degrees to radians.
Definition: matheval.hpp:78
ParticlePos_t & R
ParticleAttrib< int > Bin
void get_bounds(Vector_t &rmin, Vector_t &rmax) const
double getQ() const
Access to reference data.
size_t getLocalNum() const
ParticleAttrib< double > M
ParticleAttrib< double > Q
double getM() const
static OpalData * getInstance()
Definition: OpalData.cpp:196
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:192
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
virtual double getMaxR() const
Definition: Cyclotron.cpp:325
virtual double getMaxZ() const
Definition: Cyclotron.cpp:345
virtual double getMinZ() const
Definition: Cyclotron.cpp:335
virtual double getMinR() const
Definition: Cyclotron.cpp:321
virtual const std::string & getName() const
Get element name.
virtual ParticleMatterInteractionHandler * getParticleMatterInteraction() const
Definition: ElementBase.h:482
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:414
std::string getTypeString() const
Definition: ElementBase.h:578
std::vector< double > pfld_m
Definition: Vacuum.h:38
int nrad_m
Definition: Vacuum.h:39
int ntet_m
Definition: Vacuum.h:39
int ntot_m
Definition: Vacuum.h:41
int ntetS_m
Definition: Vacuum.h:40
double tetmin_m
Definition: Vacuum.h:47
double dtet_m
Definition: Vacuum.h:47
double delr_m
Definition: Vacuum.h:46
double Pfact_m
Definition: Vacuum.h:52
double rmin_m
Definition: Vacuum.h:46
std::vector< double > rarr_m
Definition: Vacuum.h:50
Definition: Vacuum.h:61
double minr_m
Flag if particles should be stripped or stopped.
Definition: Vacuum.h:148
double pressure_m
Type of gas for residual vacuum.
Definition: Vacuum.h:140
void setPScale(double ps)
Definition: Vacuum.cpp:145
bool stop_m
K.
Definition: Vacuum.h:144
double pscale_m
stores the filename of the pressure map
Definition: Vacuum.h:142
virtual void goOffline() override
Definition: Vacuum.cpp:285
static const boost::bimap< ResidualGas, std::string > bmResidualGasString_s
Definition: Vacuum.h:156
double getPressure() const
Definition: Vacuum.cpp:128
std::string getPressureMapFN() const
Definition: Vacuum.cpp:141
virtual void getDimensions(double &zBegin, double &zEnd) const override
Definition: Vacuum.cpp:289
void initR(double rmin, double dr, int nrad)
Definition: Vacuum.cpp:372
void setTemperature(double temperature)
Definition: Vacuum.cpp:158
virtual ~Vacuum()
Definition: Vacuum.cpp:92
virtual void goOnline(const double &kineticEnergy) override
Definition: Vacuum.cpp:272
double minz_m
mm
Definition: Vacuum.h:150
int idx(int irad, int ktet)
Definition: Vacuum.h:127
double temperature_m
a scale factor for the P-field
Definition: Vacuum.h:143
virtual ElementType getType() const override
Get element type std::string.
Definition: Vacuum.cpp:294
ResidualGas getResidualGas() const
Definition: Vacuum.cpp:111
double getPScale() const
Definition: Vacuum.cpp:149
void getPressureFromFile()
Definition: Vacuum.cpp:381
void setPressureMapFN(std::string pmapfn)
Definition: Vacuum.cpp:137
double checkPressure(const Vector_t &R)
Definition: Vacuum.cpp:298
virtual void finalise() override
Definition: Vacuum.cpp:266
void print()
Definition: Vacuum.cpp:276
virtual void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: Vacuum.cpp:233
virtual void accept(BeamlineVisitor &) const override
Apply visitor to Vacuum.
Definition: Vacuum.cpp:98
void setPressure(double pressure)
Definition: Vacuum.cpp:124
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
void updateParticleAttributes()
Definition: Vacuum.cpp:259
virtual bool checkVacuum(PartBunchBase< double, 3 > *bunch, Cyclotron *cycl)
Definition: Vacuum.cpp:201
ParticleMatterInteractionHandler * parmatint_m
mm
Definition: Vacuum.h:154
std::string pmapfn_m
mbar
Definition: Vacuum.h:141
double getTemperature() const
Definition: Vacuum.cpp:162
void setResidualGas(std::string gas)
Definition: Vacuum.cpp:102
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B) override
Definition: Vacuum.cpp:192
PFieldData PField_m
Definition: Vacuum.h:161
std::string getResidualGasName()
Definition: Vacuum.cpp:115
double maxr_m
mm
Definition: Vacuum.h:149
Vacuum()
Definition: Vacuum.cpp:55
bool checkPoint(const Vector_t &R)
Definition: Vacuum.cpp:179
bool getStop() const
Definition: Vacuum.cpp:175
double maxz_m
mm
Definition: Vacuum.h:151
PPositions PP_m
Definition: Vacuum.h:164
ResidualGas gas_m
parameters for Vacuum
Definition: Vacuum.h:139
void setStop(bool stopflag)
Definition: Vacuum.cpp:171
virtual void print(Inform &os)=0
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