OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
Line.cpp
Go to the documentation of this file.
1//
2// Class Line
3// The LINE definition.
4// A Line contains an OPALX TBeamline<FlaggedElmPtr> which represents the
5// sequence of elements in the line. The line is always flat in the sense
6// that nested anonymous lines are flattened.
7//
8// Copyright (c) 200x - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
9// All rights reserved
10//
11// This file is part of OPAL.
12//
13// OPAL is free software: you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation, either version 3 of the License, or
16// (at your option) any later version.
17//
18// You should have received a copy of the GNU General Public License
19// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
20//
21#include "Lines/Line.h"
22#include <algorithm>
23#include <iostream>
24#include <memory>
30#include "Beamlines/Beamline.h"
33#include "Expressions/SBinary.h"
36#include "Lines/LineTemplate.h"
37#include "Lines/Replacer.h"
39#include "Utilities/Options.h"
41
42using namespace Expressions;
43
44// The attributes of class Line.
45namespace {
46 enum {
47 TYPE, // The type attribute.
48 LENGTH, // The line length.
49 ORIGIN, // The location of the particle source
50 ORIENTATION, // The orientation of the particle source
51 X,
52 Y,
53 Z,
54 THETA,
55 PHI,
56 PSI,
57 SIZE
58 };
59
60 // Auxiliary function for adding two element lengths.
61 double AttAdd(double a, double b) { return a + b; }
62} // namespace
63
66 SIZE, "LINE",
67 "The \"LINE\" statement defines a beamline list.\n"
68 "\t<name> : line = (<list>)") {
69 itsAttr[TYPE] = Attributes::makeString("TYPE", "Design type");
70
71 itsAttr[LENGTH] = Attributes::makeReal("L", "Total length of line in m");
72 itsAttr[LENGTH].setReadOnly(true);
73
74 itsAttr[ORIGIN] = Attributes::makeRealArray("ORIGIN", "The location of the particle source");
75
77 "ORIENTATION", "The Tait-Bryan angles for the orientation of the particle source");
78
79 itsAttr[X] =
80 Attributes::makeReal("X", "The x-coordinate of the location of the particle source", 0);
81
82 itsAttr[Y] =
83 Attributes::makeReal("Y", "The y-coordinate of the location of the particle source", 0);
84
85 itsAttr[Z] =
86 Attributes::makeReal("Z", "The z-coordinate of the location of the particle source", 0);
87
89 "THETA", "The rotation about the y-axis of the particle source", 0);
90
91 itsAttr[PHI] =
92 Attributes::makeReal("PHI", "The rotation about the x-axis of the particle source", 0);
93
94 itsAttr[PSI] =
95 Attributes::makeReal("PSI", "The rotation about the z-axis of the particle source", 0);
96
97 setElement(new FlaggedBeamline("LINE"));
98
100}
101
102Line::Line(const std::string& name, Line* parent)
103 : // Do not copy list members; they will be filled at parse time.
104 BeamSequence(name, parent) {
105 setElement(new FlaggedBeamline(name));
106}
107
109
110Line* Line::clone(const std::string& name) { return new Line(name, this); }
111
112Line* Line::copy(const std::string& name) {
113 Line* clone = new Line(name, this);
114 FlaggedBeamline* oldLine = fetchLine();
115 FlaggedBeamline* newLine = clone->fetchLine();
116 std::copy(oldLine->begin(), oldLine->end(), std::back_inserter(*newLine));
117 return &*clone;
118}
119
120double Line::getLength() const { return Attributes::getReal(itsAttr[LENGTH]); }
121
122Object* Line::makeTemplate(const std::string& name, TokenStream& is, Statement& statement) {
123 LineTemplate* macro = new LineTemplate(name, this);
124
125 try {
126 macro->parseTemplate(is, statement);
127 return macro;
128 } catch (...) {
129 delete macro;
130 macro = 0;
131 throw;
132 }
133}
134
136 static const TFunction2<double, double> plus = {"+", 4, AttAdd};
137
138 // Check for delimiters.
139 parseDelimiter(stat, '=');
140 parseDelimiter(stat, '(');
141
142 // Clear all reference counts.
144
145 // Parse the line list.
146 parseList(stat);
147
148 // Insert the begin and end markers.
149 FlaggedBeamline* line = fetchLine();
150 auto markS = Element::find("#S")->getElementPtr();
151 FlaggedElmPtr first(ElmPtr(markS), false);
152 line->push_front(first);
153
154 auto markE = Element::find("#E")->getElementPtr();
155 FlaggedElmPtr last(ElmPtr(markE), false);
156 line->push_back(last);
157
158 // Construct expression for length, and fill in occurrence counters.
160 for (FlaggedBeamline::iterator i = line->begin(); i != line->end(); ++i) {
161 auto actname = i->getElement()->getName();
162 // Accumulate length.
163 PtrToScalar<double> temp = new SRefExpr<double>(actname, "L");
164 if (expr.isValid() && temp.isValid()) {
165 expr = SBinary<double, double>::make(plus, expr, temp);
166 } else {
167 expr = temp;
168 }
169
170 // Do the required instantiations.
171 ElementBase* base = i->getElement();
172 i->setElement(base->copyStructure());
173 Element* elem = Element::find(actname);
174 i->setCounter(elem->increment());
175 }
176 if (expr.isValid()) itsAttr[LENGTH].set(new SAutomatic<double>(expr));
177
178 while (stat.delimiter(',')) {
179 std::string name = Expressions::parseString(stat, "Attribute name expected.");
180 Attribute* attr = findAttribute(name);
181
182 if (attr != 0) {
183 if (stat.delimiter('=')) {
184 attr->parse(stat, true);
185 } else if (stat.delimiter(":=")) {
186 attr->parse(stat, false);
187 } else {
188 attr->setDefault();
189 }
190 }
191 }
192
193 if (itsAttr[ORIGIN] || itsAttr[ORIENTATION]) {
194 std::vector<double> origin = Attributes::getRealArray(itsAttr[ORIGIN]);
195 if (origin.size() == 3) {
196 line->setOrigin3D(Vector_t<double, 3>(origin[0], origin[1], origin[2]));
197 } else {
199 if (itsAttr[ORIGIN]) {
200 throw OpalException(
201 "Line::parse", "Parameter origin is array of 3 values (x, y, z);\n"
202 + std::to_string(origin.size())
203 + " values provided");
204 }
205 }
206
207 std::vector<double> direction = Attributes::getRealArray(itsAttr[ORIENTATION]);
208 if (direction.size() == 3) {
209 const double& theta = direction[0];
210 const double& phi = direction[1];
211 const double& psi = direction[2];
212
213 Quaternion rotTheta(cos(0.5 * theta), 0, -sin(0.5 * theta), 0);
214 Quaternion rotPhi(cos(0.5 * phi), -sin(0.5 * phi), 0, 0);
215 Quaternion rotPsi(cos(0.5 * psi), 0, 0, -sin(0.5 * psi));
216 line->setInitialDirection(rotPsi * rotPhi * rotTheta);
217 } else {
218 line->setInitialDirection(Quaternion(1, 0, 0, 0));
219 if (itsAttr[ORIENTATION]) {
220 throw OpalException(
221 "Line::parse",
222 "Parameter orientation is array of 3 values (theta, phi, psi);\n"
223 + std::to_string(direction.size()) + " values provided");
224 }
225 }
226
227 line->setRelativeFlag(true);
228 } else {
229 const Vector_t<double, 3> origin(
232
233 const double theta = Attributes::getReal(itsAttr[THETA]);
234 const double phi = Attributes::getReal(itsAttr[PHI]);
235 const double psi = Attributes::getReal(itsAttr[PSI]);
236
237 Quaternion rotTheta(cos(0.5 * theta), 0, -sin(0.5 * theta), 0);
238 Quaternion rotPhi(cos(0.5 * phi), -sin(0.5 * phi), 0, 0);
239 Quaternion rotPsi(cos(0.5 * psi), 0, 0, -sin(0.5 * psi));
240
241 line->setOrigin3D(origin);
242 line->setInitialDirection(rotPsi * rotPhi * rotTheta);
243
244 line->setRelativeFlag(
245 !itsAttr[X].defaultUsed() || !itsAttr[Y].defaultUsed() || !itsAttr[Z].defaultUsed()
246 || !itsAttr[THETA].defaultUsed() || !itsAttr[PHI].defaultUsed()
247 || !itsAttr[PSI].defaultUsed());
248 }
249}
250
251void Line::print(std::ostream& os) const {
252 os << getOpalName() << ":LINE=(";
253 const FlaggedBeamline* line = fetchLine();
254 bool seen = false;
255
256 for (FlaggedBeamline::const_iterator i = line->begin(); i != line->end(); ++i) {
257 const std::string name = i->getElement()->getName();
258 if (name[0] != '#') {
259 if (seen) os << ',';
260 if (i->getReflectionFlag()) os << '-';
261 os << name;
262 seen = true;
263 }
264 }
265
266 os << ')';
267 os << ';';
268 os << std::endl;
269}
270
271FlaggedBeamline* Line::fetchLine() const { return dynamic_cast<FlaggedBeamline*>(getElement()); }
272
274 FlaggedBeamline* line = fetchLine();
275
276 do {
277 // Reversed member ?
278 bool rev = stat.delimiter('-');
279
280 // Repetition count.
281 int repeat = 1;
282 if (stat.integer(repeat)) parseDelimiter(stat, '*');
283
284 // List member.
285 if (stat.delimiter('(')) {
286 // Anonymous sub-line is expanded immediately.
287 Line nestedLine;
288 nestedLine.parseList(stat);
289 FlaggedBeamline* subLine = nestedLine.fetchLine();
290
291 while (repeat-- > 0) {
292 if (rev) {
293 for (FlaggedBeamline::reverse_iterator i = subLine->rbegin();
294 i != subLine->rend(); ++i) {
295 FlaggedElmPtr fep(*i);
296 fep.setReflectionFlag(false);
297 line->push_back(fep);
298 }
299 } else {
300 for (FlaggedBeamline::iterator i = subLine->begin(); i != subLine->end(); ++i) {
301 FlaggedElmPtr fep(*i);
302 line->push_back(fep);
303 }
304 }
305 }
306 } else {
307 // Identifier.
308 std::string name = parseString(stat, "Line member expected.");
309 auto obj = OpalData::getInstance()->find(
310 name); // std::shared_ptr<Object>(OpalData::getInstance()->find(name));
311
312 if (!obj) {
313 throw ParseError("Line::parseList()", "Element \"" + name + "\" is undefined.");
314 } else
315
316 if (stat.delimiter('(')) {
317 // Line or sequence macro.
318 // This instance will always be an anonymous object.
319 obj = obj->makeInstance(
320 name, stat,
321 0); // std::shared_ptr<Object>(obj->makeInstance(name, stat, 0));
322 }
323
324 if (Element* elem = dynamic_cast<Element*>(obj)) {
325 while (repeat-- > 0) {
326 ElementBase* base = elem->getElement();
327 FlaggedElmPtr member(base, rev);
328 line->push_back(member);
329 }
330
331 } else {
332 throw ParseError(
333 "Line::parseList()", "Object \"" + name + "\" cannot be a line member.");
334 }
335 }
336 } while (stat.delimiter(','));
337
338 parseDelimiter(stat, ')');
339}
340
341void Line::replace(Object* oldObject, Object* newObject) {
342 Element* oldElement = dynamic_cast<Element*>(oldObject);
343 Element* newElement = dynamic_cast<Element*>(newObject);
344
345 if (oldElement != 0 && newElement != 0) {
346 Replacer rep(*fetchLine(), oldElement->getOpalName(), newElement->getElement());
347 rep.execute();
348 }
349}
ippl::Vector< T, Dim > Vector_t
TBeamline< FlaggedElmPtr > FlaggedBeamline
A beam line with flagged elements.
@ SIZE
Definition IndexMap.cpp:179
A representation of an Object attribute.
Definition Attribute.h:52
void setDefault()
Assign default value.
Definition Attribute.cpp:91
void parse(Statement &stat, bool eval)
Parse attribute.
Definition Attribute.cpp:76
The base class for all OPAL beam lines and sequences.
void execute() override
Apply the algorithm to the top-level beamline.
virtual ElementBase * copyStructure()
Make a structural copy.
std::shared_ptr< ElementBase > getElementPtr() const
Return the embedded OPALX element as shared_ptr.
Definition Element.h:121
static Element * find(const std::string &name)
Find named Element.
Definition Element.cpp:39
ElementBase * getElement() const
Return the embedded OPALX element.
Definition Element.h:119
void setElement(ElementBase *)
Assign new OPALX element.
Definition Element.h:123
A section of a beam line.
Definition ElmPtr.h:32
A pointer to a scalar expression.
Object attribute with an `‘automatic’' scalar value.
Definition SAutomatic.h:38
static Scalar< T > * make(const TFunction2< T, U > &, PtrToScalar< U > left, PtrToScalar< U > right)
Make a new expression.
Definition SBinary.h:118
An expression defined as a reference to a scalar.
Definition SRefExpr.h:40
A section of a beam line.
void setReflectionFlag(bool flag) const
Set reflection flag.
void parseTemplate(TokenStream &is, Statement &stat)
Parse the line template.
Definition Line.h:30
virtual void replace(Object *oldObject, Object *newObject)
Replace references.
Definition Line.cpp:341
friend class LineTemplate
Definition Line.h:31
virtual void parse(Statement &stat)
Parse the line object.
Definition Line.cpp:135
virtual FlaggedBeamline * fetchLine() const
Return the embedded OPALX beam line.
Definition Line.cpp:271
virtual void print(std::ostream &stream) const
Print the line.
Definition Line.cpp:251
virtual Line * copy(const std::string &name)
Make complete copy.
Definition Line.cpp:112
virtual double getLength() const
Return line length.
Definition Line.cpp:120
virtual ~Line()
Definition Line.cpp:108
virtual Object * makeTemplate(const std::string &name, TokenStream &is, Statement &stat)
Make a line template.
Definition Line.cpp:122
void parseList(Statement &)
Definition Line.cpp:273
Line()
Exemplar constructor.
Definition Line.cpp:64
virtual Line * clone(const std::string &name)
Make clone.
Definition Line.cpp:110
The base class for all OPAL objects.
Definition Object.h:45
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition Object.cpp:169
const std::string & getOpalName() const
Return object name.
Definition Object.cpp:267
int increment()
Increment and return the occurrence counter.
Definition Object.cpp:287
virtual Attribute * findAttribute(const std::string &name)
Find an attribute by name.
Definition Object.cpp:56
std::vector< Attribute > itsAttr
The object attributes.
Definition Object.h:210
void apply(const ObjectFunction &)
Apply a function to all objects.
Definition OpalData.cpp:381
Object * find(const std::string &name)
Find entry.
Definition OpalData.cpp:477
static OpalData * getInstance()
Definition OpalData.cpp:193
Parse exception.
Definition ParseError.h:31
Quaternion storage and rotation algebra used by OPALX geometry code.
Replace all references to named element by a new version.
Definition Replacer.h:31
Interface for statements.
Definition Statement.h:37
bool integer(int &value)
Return signed integer.
Definition Statement.cpp:63
bool delimiter(char c)
Test for delimiter.
Definition Statement.cpp:83
void setRelativeFlag(bool flag)
Definition TBeamline.h:414
void setOrigin3D(const Vector_t< double, 3 > &ori)
Definition TBeamline.h:394
void setInitialDirection(const Quaternion &rot)
Definition TBeamline.h:404
Abstract interface for a stream of input tokens.
Definition TokenStream.h:30
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.
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
Representation objects and parsers for attribute expressions.
std::string parseString(Statement &, const char msg[])
Parse string value.
void parseDelimiter(Statement &stat, char delim)
Test for one-character delimiter.
A function of two U's returning a T.
Definition TFunction2.h:31
Clear Reference.
Definition OpalData.h:136