OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
Beam.cpp
Go to the documentation of this file.
1 //
2 // Class Beam
3 // The class for the OPAL BEAM command.
4 // A BEAM definition is used by most physics commands to define the
5 // particle charge and the reference momentum, together with some other data.
6 //
7 // Copyright (c) 200x - 2023, Paul Scherrer Institut, Villigen PSI, Switzerland
8 // All rights reserved
9 //
10 // This file is part of OPAL.
11 //
12 // OPAL is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
19 //
20 #include "Structure/Beam.h"
21 
24 #include "Attributes/Attributes.h"
25 #include "Expressions/SAutomatic.h"
26 #include "Expressions/SRefExpr.h"
28 #include "Physics/Physics.h"
29 #include "Physics/Units.h"
31 
32 #include <cmath>
33 #include <iterator>
34 
35 using namespace Expressions;
36 
37 // The attributes of class Beam.
38 namespace {
39  enum {
40  PARTICLE, // The particle name
41  MASS, // The particle rest mass in GeV
42  CHARGE, // The particle charge in proton charges
43  ENERGY, // The particle energy in GeV
44  PC, // The particle momentum in GeV/c
45  GAMMA, // ENERGY / MASS
46  BCURRENT, // Beam current in A
47  BFREQ, // Beam frequency in MHz
48  NPART, // Number of particles per bunch
49  MOMENTUMTOLERANCE, // Fractional tolerance to momentum deviations
50  SIZE
51  };
52 }
53 
54 
56  Definition(SIZE, "BEAM",
57  "The \"BEAM\" statement defines data for the particles "
58  "in a beam."),
59  reference(1.0, Physics::m_p * Units::GeV2eV, 1.0 * Units::GeV2eV) {
60 
62  ("PARTICLE", "Name of particle to be used",
63  {"ELECTRON",
64  "POSITRON",
65  "MUON",
66  "PROTON",
67  "ANTIPROTON",
68  "DEUTERON",
69  "HMINUS",
70  "H2P",
71  "ALPHA",
72  "CARBON",
73  "XENON",
74  "URANIUM"});
75 
77  ("MASS", "Particle rest mass [GeV]");
78 
79  itsAttr[CHARGE] = Attributes::makeReal
80  ("CHARGE", "Particle charge in proton charges");
81 
82  itsAttr[ENERGY] = Attributes::makeReal
83  ("ENERGY", "Particle energy [GeV]");
84 
85  itsAttr[PC] = Attributes::makeReal
86  ("PC", "Particle momentum [GeV/c]");
87 
88  itsAttr[GAMMA] = Attributes::makeReal
89  ("GAMMA", "ENERGY / MASS");
90 
91  itsAttr[BCURRENT] = Attributes::makeReal
92  ("BCURRENT", "Beam current [A] (all bunches)");
93 
94  itsAttr[BFREQ] = Attributes::makeReal
95  ("BFREQ", "Beam frequency [MHz] (all bunches)");
96 
97  itsAttr[NPART] = Attributes::makeReal
98  ("NPART", "Number of particles in bunch");
99 
100  itsAttr[MOMENTUMTOLERANCE] = Attributes::makeReal
101  ("MOMENTUMTOLERANCE",
102  "Fractional tolerance to deviations in the distribution "
103  "compared to the reference data at initialisation (default=1e-2). "
104  "If MOMENTUMTOLERANCE<=0, no tolerance checking is done.", 1e-2);
105 
106  // Set up default beam.
107  Beam* defBeam = clone("UNNAMED_BEAM");
108  defBeam->builtin = true;
109 
110  try {
111  defBeam->update();
112  OpalData::getInstance()->define(defBeam);
113  } catch(...) {
114  delete defBeam;
115  }
116 
118 }
119 
120 
121 Beam::Beam(const std::string& name, Beam* parent):
122  Definition(name, parent),
123  reference(parent->reference)
124 {}
125 
126 
128 {}
129 
130 
131 bool Beam::canReplaceBy(Object* object) {
132  // Can replace only by another BEAM.
133  return dynamic_cast<Beam*>(object) != 0;
134 }
135 
136 
137 Beam* Beam::clone(const std::string& name) {
138  return new Beam(name, this);
139 }
140 
141 
143  update();
144  // Check if energy explicitly has been set with the BEAM command
145  if (!itsAttr[GAMMA] && !(itsAttr[ENERGY]) && !(itsAttr[PC])) {
146  throw OpalException("Beam::execute()",
147  "The energy hasn't been set. "
148  "Set either \"GAMMA\", \"ENERGY\" or \"PC\".");
149  }
150 
151  if ( !(itsAttr[PARTICLE]) && (!itsAttr[MASS] || !(itsAttr[CHARGE])) ) {
152  throw OpalException("Beam::execute()",
153  "The beam particle hasn't been set. "
154  "Set either \"PARTICLE\" or \"MASS\" and \"CHARGE\".");
155  }
156 
157  if (!(itsAttr[NPART])) {
158  throw OpalException("Beam::execute()", "\"NPART\" must be set.");
159  }
160 }
161 
162 
163 Beam* Beam::find(const std::string& name) {
164  Beam* beam = dynamic_cast<Beam*>(OpalData::getInstance()->find(name));
165 
166  if (beam == 0) {
167  throw OpalException("Beam::find()", "Beam \"" + name + "\" not found.");
168  }
169 
170  return beam;
171 }
172 
174  if (Attributes::getReal(itsAttr[NPART]) > 0) {
175  return (size_t)Attributes::getReal(itsAttr[NPART]);
176  } else {
177  throw OpalException("Beam::getNumberOfParticles()",
178  "Wrong number of particles in beam!. \"NPART\" must be positive");
179  }
180 }
181 
182 const PartData& Beam::getReference() const {
183  // Cast away const, to allow logically constant Beam to update.
184  const_cast<Beam*>(this)->update();
185  return reference;
186 }
187 
188 double Beam::getCurrent() const {
189  return Attributes::getReal(itsAttr[BCURRENT]);
190 }
191 
192 double Beam::getCharge() const {
194 }
195 
196 double Beam::getMass() const {
197  return Attributes::getReal(itsAttr[MASS]);
198 }
199 
200 std::string Beam::getParticleName() const {
201  return Attributes::getString(itsAttr[PARTICLE]);
202 }
203 
204 double Beam::getFrequency() const {
205  return Attributes::getReal(itsAttr[BFREQ]);
206 }
207 
209  return std::copysign(1.0, getCharge()) * getCurrent()
212 }
213 
214 double Beam::getMassPerParticle() const {
215  return getMass() * getChargePerParticle() / (getCharge() * Physics::q_e);
216 }
217 
218 void Beam::update() {
219 
220  if (itsAttr[PARTICLE]) {
221  std::string pName = getParticleName();
225  }
226 
227  // Set up particle reference; convert all to eV for CLASSIC.
228  double mass = (itsAttr[MASS] ? getMass() : Physics::m_p) * Units::GeV2eV;
229  double charge = itsAttr[CHARGE] ? getCharge() : 1.0;
230 
231  reference = PartData(charge, mass, 1.0);
232 
233  if (itsAttr[GAMMA]) {
234  double gamma = Attributes::getReal(itsAttr[GAMMA]);
235  if (gamma > 1.0) {
236  reference.setGamma(gamma);
237  } else {
238  throw OpalException("Beam::update()",
239  "\"GAMMA\" should be greater than 1.");
240  }
241  } else if (itsAttr[ENERGY]) {
242  double energy = Attributes::getReal(itsAttr[ENERGY]) * Units::GeV2eV;
243  if (energy > reference.getM()) {
244  reference.setE(energy);
245  } else {
246  throw OpalException("Beam::update()",
247  "\"ENERGY\" should be greater than \"MASS\".");
248  }
249  } else if (itsAttr[PC]) {
250  double pc = Attributes::getReal(itsAttr[PC]) * Units::GeV2eV;
251  if (pc > 0.0) {
252  reference.setP(pc);
253  } else {
254  throw OpalException("Beam::update()",
255  "\"PC\" should be greater than 0.");
256  }
257  }
258 
259  double momentumTol = Attributes::getReal(itsAttr[MOMENTUMTOLERANCE]);
260  reference.setMomentumTolerance(momentumTol);
261 
262  // Set default name.
263  if (getOpalName().empty()) setOpalName("UNNAMED_BEAM");
264 }
265 
266 
267 void Beam::print(std::ostream& os) const {
268  double charge = Attributes::getReal(itsAttr[CHARGE]);
269  os << "* ************* B E A M ************************************************************ " << std::endl;
270  os << "* BEAM " << getOpalName() << '\n'
271  << "* PARTICLE " << Attributes::getString(itsAttr[PARTICLE]) << '\n'
272  << "* REST MASS " << Attributes::getReal(itsAttr[MASS]) << " [GeV]\n"
273  << "* CHARGE " << (charge > 0 ? '+' : '-') << "e * " << std::abs(charge) << " \n"
274  << "* MOMENTUM " << reference.getP() << " [eV/c]\n";
275  if (Attributes::getReal(itsAttr[MOMENTUMTOLERANCE]) > 0) {
276  os << "* MOMENTUM TOLERANCE " << Attributes::getReal(itsAttr[MOMENTUMTOLERANCE]) << '\n';
277  }
278  os << "* CURRENT " << Attributes::getReal(itsAttr[BCURRENT]) << " [A]\n"
279  << "* FREQUENCY " << Attributes::getReal(itsAttr[BFREQ]) << " [MHz]\n"
280  << "* NPART " << Attributes::getReal(itsAttr[NPART]) << '\n';
281  os << "* ********************************************************************************** " << std::endl;
282 }
void setMomentumTolerance(double tolerance)
Set the momentum tolerance.
Definition: PartData.cpp:88
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
Definition: Attributes.cpp:240
static OpalData * getInstance()
Definition: OpalData.cpp:196
bool builtin
Built-in flag.
Definition: Object.h:233
void setOpalName(const std::string &name)
Set object name.
Definition: Object.cpp:331
static ParticleType getParticleType(const std::string &str)
The base class for all OPAL objects.
Definition: Object.h:48
void setReal(Attribute &attr, double val)
Set real value.
Definition: Attributes.cpp:271
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:343
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
double getMassPerParticle() const
Mass per macro particle in GeV/c^2.
Definition: Beam.cpp:214
void define(Object *newObject)
Define a new object.
Definition: OpalData.cpp:489
virtual Beam * clone(const std::string &name)
Make clone.
Definition: Beam.cpp:137
const PartData & getReference() const
Return the embedded CLASSIC PartData.
Definition: Beam.cpp:182
virtual void update()
Update the BEAM data.
Definition: Beam.cpp:218
void setP(double p)
Set reference momentum.
Definition: PartData.cpp:40
size_t getNumberOfParticles() const
Return the number of (macro)particles.
Definition: Beam.cpp:173
double getM() const
The constant mass per particle.
Definition: PartData.h:122
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
virtual ~Beam()
Definition: Beam.cpp:127
std::string getParticleName() const
Return Particle&#39;s name.
Definition: Beam.cpp:200
void print(std::ostream &os) const
Print the object.
Definition: Beam.cpp:267
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition: Object.cpp:191
The base class for all OPAL exceptions.
Definition: OpalException.h:28
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Definition: Attributes.cpp:409
constexpr double q_e
The elementary charge in As.
Definition: Physics.h:69
virtual void execute()
Check the BEAM data.
Definition: Beam.cpp:142
const std::string & getOpalName() const
Return object name.
Definition: Object.cpp:310
static double getParticleCharge(const ParticleType &type)
std::vector< Attribute > itsAttr
The object attributes.
Definition: Object.h:216
void setE(double E)
Set reference energy.
Definition: PartData.cpp:57
double getMass() const
Return Particle&#39;s rest mass in GeV.
Definition: Beam.cpp:196
static Beam * find(const std::string &name)
Find named BEAM.
Definition: Beam.cpp:163
double getChargePerParticle() const
Charge per macro particle in C.
Definition: Beam.cpp:208
const std::string name
constexpr double MHz2Hz
Definition: Units.h:113
ParticleType
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:252
constexpr double m_p
The proton rest mass in GeV.
Definition: Physics.h:90
double getCurrent() const
Return the beam current in A.
Definition: Beam.cpp:188
The base class for all OPAL definitions.
Definition: Definition.h:30
constexpr double GeV2eV
Definition: Units.h:68
Beam()
Exemplar constructor.
Definition: Beam.cpp:55
Object * find(const std::string &name)
Find entry.
Definition: OpalData.cpp:571
constexpr double e
The value of .
Definition: Physics.h:39
static double getParticleMass(const ParticleType &type)
double getP() const
The constant reference momentum per particle.
Definition: PartData.h:126
Definition: Beam.h:31
we sometimes make exceptions for this Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally NO WARRANTY BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE
Definition: LICENSE:260
void setGamma(double gamma)
Set gamma.
Definition: PartData.cpp:79
virtual bool canReplaceBy(Object *object)
Test if replacement is allowed.
Definition: Beam.cpp:131
PartData reference
Definition: Beam.h:93
double getCharge() const
Return the charge number in elementary charge.
Definition: Beam.cpp:192
double getFrequency() const
Return the beam frequency in MHz.
Definition: Beam.cpp:204