OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
OpalLaser.cpp
Go to the documentation of this file.
2
6
7#include <cmath>
8#include <sstream>
9#include <vector>
10
11namespace {
12 double getRequiredPositiveReal(
13 const std::vector<Attribute>& attrs, int index, const std::string& where) {
14 if (!attrs[index]) {
15 throw OpalException(where, "\"" + attrs[index].getName() + "\" must be set.");
16 }
17
18 const double value = Attributes::getReal(attrs[index]);
19 if (value <= 0.0) {
20 throw OpalException(
21 where, "\"" + attrs[index].getName() + "\" must be greater than 0.");
22 }
23
24 return value;
25 }
26
27 Vector_t<double, 3> getVector3(
28 const Attribute& attr, const std::string& where, const std::string& semanticName) {
29 if (!attr) {
30 throw OpalException(where, "\"" + attr.getName() + "\" must be set.");
31 }
32
33 const std::vector<double> values = Attributes::getRealArray(attr);
34 if (values.size() != 3) {
35 std::ostringstream msg;
36 msg << "\"" << attr.getName() << "\" must contain exactly 3 values for " << semanticName
37 << "; got " << values.size() << ".";
38 throw OpalException(where, msg.str());
39 }
40
41 return Vector_t<double, 3>(values[0], values[1], values[2]);
42 }
43} // namespace
44
47 SIZE, "LASER",
48 "The \"LASER\" element defines a passive analytic laser pulse for OPALX.") {
49 itsAttr[WAVELENGTH] = Attributes::makeReal("WAVELENGTH", "Laser wavelength in m.");
50 itsAttr[PULSEENERGY] = Attributes::makeReal("PULSEENERGY", "Total laser pulse energy in J.");
51 itsAttr[PULSELENGTH] = Attributes::makeReal("PULSELENGTH", "Laser pulse duration in s.");
52 itsAttr[WAISTX] = Attributes::makeReal("WAISTX", "Horizontal laser waist in m.");
53 itsAttr[WAISTY] = Attributes::makeReal("WAISTY", "Vertical laser waist in m.");
54 itsAttr[DIR] = Attributes::makeRealArray("DIR", "Laser propagation direction vector.");
56 "STOKES", "Normalized Stokes polarization vector {xi1, xi2, xi3}.");
57
59
60 setElement(new LaserRep("LASER"));
61}
62
63OpalLaser::OpalLaser(const std::string& name, OpalLaser* parent) : OpalElement(name, parent) {
64 setElement(new LaserRep(name));
65}
66
68
69OpalLaser* OpalLaser::clone(const std::string& name) { return new OpalLaser(name, this); }
70
72 constexpr const char* where = "OpalLaser::update()";
73
75
76 auto* laser = dynamic_cast<LaserRep*>(getElement());
77 if (!laser) {
79 return;
80 }
81
82 // OpalData::update() calls update() on every object in the directory,
83 // including the prototype instance whose required attributes are all unset.
84 // Skip propagation silently only when none of the required attributes has
85 // been configured yet (i.e. this is truly the unmodified prototype).
86 //
88 // 1. Register every attribute with a sentinel default in the constructor
89 // (e.g. Attributes::makeReal("WAVELENGTH", "...", 0.0)) so that
90 // Attributes::getReal() always returns a well-defined value, even on
91 // the prototype. OpalSolenoid and OpalCavity are good examples.
92 // 2. In update(), read all attributes unconditionally with
93 // Attributes::getReal() / Attributes::getRealArray() and forward them
94 // to LaserRep without throwing. No prototype guard is needed because
95 // zero/sentinel values are harmless.
96 // 3. Move the "must be positive / must be set" validation into LaserRep,
97 // e.g. in initialise() which is called only when the element is
98 // actually inserted into a tracked beamline. That is the right layer
99 // to enforce physical constraints, and it keeps OpalLaser::update()
100 // consistent with every other OpalElement subclass.
101 const bool anyConfigured = itsAttr[WAVELENGTH] || itsAttr[PULSEENERGY] || itsAttr[PULSELENGTH]
103 if (!anyConfigured) {
105 return;
106 }
107
108 const double wavelength = getRequiredPositiveReal(itsAttr, WAVELENGTH, where);
109 const double pulseEnergy = getRequiredPositiveReal(itsAttr, PULSEENERGY, where);
110 const double pulseLength = getRequiredPositiveReal(itsAttr, PULSELENGTH, where);
111 const double waistX = getRequiredPositiveReal(itsAttr, WAISTX, where);
112 const double waistY = getRequiredPositiveReal(itsAttr, WAISTY, where);
113
114 Vector_t<double, 3> direction = getVector3(itsAttr[DIR], where, "the propagation direction");
115 const double directionNorm = std::sqrt(dot(direction, direction));
116 if (directionNorm <= 0.0) {
117 throw OpalException(where, "\"DIR\" must be a non-zero vector.");
118 }
119 direction /= directionNorm;
120
121 Vector_t<double, 3> stokes(0.0);
122 if (itsAttr[STOKES]) {
123 stokes = getVector3(itsAttr[STOKES], where, "the Stokes vector");
124 const double stokesNorm2 = dot(stokes, stokes);
125 if (stokesNorm2 > 1.0 + 1.0e-12) {
126 throw OpalException(where, "\"STOKES\" must satisfy xi1^2 + xi2^2 + xi3^2 <= 1.");
127 }
128 }
129
130 const double length = itsAttr[LENGTH] ? Attributes::getReal(itsAttr[LENGTH]) : 0.0;
131 if (length < 0.0) {
132 throw OpalException(where, "\"L\" must be greater than or equal to 0.");
133 }
134
135 laser->setElementLength(length);
136 laser->setWavelength(wavelength);
137 laser->setPulseEnergy(pulseEnergy);
138 laser->setPulseLength(pulseLength);
139 laser->setWaistX(waistX);
140 laser->setWaistY(waistY);
141 laser->setDirection(direction);
142 laser->setStokes(stokes);
143
145}
ippl::Vector< T, Dim > Vector_t
@ SIZE
Definition IndexMap.cpp:179
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition Vector3D.cpp:95
A representation of an Object attribute.
Definition Attribute.h:52
const std::string & getName() const
Return the attribute name.
Definition Attribute.cpp:62
ElementBase * getElement() const
Return the embedded OPALX element.
Definition Element.h:119
void setElement(ElementBase *)
Assign new OPALX element.
Definition Element.h:123
std::vector< Attribute > itsAttr
The object attributes.
Definition Object.h:210
virtual void updateUnknown(ElementBase *)
Transmit the `‘unknown’' (not known to OPALX) attributes to OPALX.
virtual void update()
Update the embedded OPALX element.
void registerOwnership() const
@ PULSELENGTH
Definition OpalLaser.h:8
@ WAVELENGTH
Definition OpalLaser.h:8
@ PULSEENERGY
Definition OpalLaser.h:8
void update() override
Update the embedded OPALX element.
Definition OpalLaser.cpp:71
~OpalLaser() override
Definition OpalLaser.cpp:67
OpalLaser * clone(const std::string &name) override
Return a clone.
Definition OpalLaser.cpp:69
double getReal(const Attribute &attr)
Return real value.
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
Attribute makeRealArray(const std::string &name, const std::string &help)
Create real array attribute.
std::vector< double > getRealArray(const Attribute &attr)
Get array value.