OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
Line.cpp
Go to the documentation of this file.
1//
2// Class Line
3// The LINE definition.
4// A Line contains a CLASSIC 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"
27#include "Beamlines/Beamline.h"
30#include "Expressions/SBinary.h"
33#include "Lines/LineTemplate.h"
34#include "Lines/Replacer.h"
35#include "Parser/Statement.h"
36#include "Utilities/Options.h"
38#include <algorithm>
39#include <iostream>
40
41using namespace Expressions;
42
43// The attributes of class Line.
44namespace {
45 enum {
46 TYPE, // The type attribute.
47 LENGTH, // The line length.
48 ORIGIN, // The location of the particle source
49 ORIENTATION, // The orientation of the particle source
50 X,
51 Y,
52 Z,
53 THETA,
54 PHI,
55 PSI,
56 SIZE
57 };
58
59 // Auxiliary function for adding two element lengths.
60 double AttAdd(double a, double b)
61 { return a + b; }
62}
63
64
66 BeamSequence(SIZE, "LINE",
67 "The \"LINE\" statement defines a beamline list.\n"
68 "\t<name> : line = (<list>)") {
70 ("TYPE", "Design type");
71
73 ("L", "Total length of line in m");
74 itsAttr[LENGTH].setReadOnly(true);
75
77 ("ORIGIN", "The location of the particle source");
78
80 ("ORIENTATION", "The Tait-Bryan angles for the orientation of the particle source");
81
83 ("X", "The x-coordinate of the location of the particle source", 0);
84
86 ("Y", "The y-coordinate of the location of the particle source", 0);
87
89 ("Z", "The z-coordinate of the location of the particle source", 0);
90
92 ("THETA", "The rotation about the y-axis of the particle source", 0);
93
95 ("PHI", "The rotation about the x-axis of the particle source", 0);
96
98 ("PSI", "The rotation about the z-axis of the particle source", 0);
99
100 setElement(new FlaggedBeamline("LINE"));
101
103}
104
105
106Line::Line(const std::string &name, Line *parent):
107 // Do not copy list members; they will be filled at parse time.
108 BeamSequence(name, parent) {
110}
111
112
114{}
115
116
117Line *Line::clone(const std::string &name) {
118 return new Line(name, this);
119}
120
121
122Line *Line::copy(const std::string &name) {
123 Line *clone = new Line(name, this);
124 FlaggedBeamline *oldLine = fetchLine();
125 FlaggedBeamline *newLine = clone->fetchLine();
126 std::copy(oldLine->begin(), oldLine->end(), std::back_inserter(*newLine));
127 return &*clone;
128}
129
130double Line::getLength() const {
131 return Attributes::getReal(itsAttr[LENGTH]);
132}
133
134
136(const std::string &name, TokenStream &is, Statement &statement) {
137 LineTemplate *macro = new LineTemplate(name, this);
138
139 try {
140 macro->parseTemplate(is, statement);
141 return macro;
142 } catch(...) {
143 delete macro;
144 macro = 0;
145 throw;
146 }
147}
148
149
151 static const TFunction2<double, double> plus = { "+", 4, AttAdd };
152
153 // Check for delimiters.
154 parseDelimiter(stat, '=');
155 parseDelimiter(stat, '(');
156
157 // Clear all reference counts.
159
160 // Parse the line list.
161 parseList(stat);
162
163 // Insert the begin and end markers.
164 FlaggedBeamline *line = fetchLine();
165 ElementBase *markS = Element::find("#S")->getElement();
166 FlaggedElmPtr first(markS, false);
167 line->push_front(first);
168
169 ElementBase *markE = Element::find("#E")->getElement();
170 FlaggedElmPtr last(markE, false);
171 line->push_back(last);
172
173 // Construct expression for length, and fill in occurrence counters.
175 for(FlaggedBeamline::iterator i = line->begin(); i != line->end(); ++i) {
176 // Accumulate length.
178 new SRefExpr<double>(i->getElement()->getName(), "L");
179 if(expr.isValid() && temp.isValid()) {
180 expr = SBinary<double, double>::make(plus, expr, temp);
181 } else {
182 expr = temp;
183 }
184
185 // Do the required instantiations.
186 ElementBase *base = i->getElement();
187 i->setElement(base->copyStructure());
188 Element *elem = Element::find(base->getName());
189 i->setCounter(elem->increment());
190 }
191 if(expr.isValid()) itsAttr[LENGTH].set(new SAutomatic<double>(expr));
192
193 while(stat.delimiter(',')) {
194 std::string name = Expressions::parseString(stat, "Attribute name expected.");
196
197 if (attr != 0) {
198 if(stat.delimiter('=')) {
199 attr->parse(stat, true);
200 } else if(stat.delimiter(":=")) {
201 attr->parse(stat, false);
202 } else {
203 attr->setDefault();
204 }
205 }
206 }
207
208 if (itsAttr[ORIGIN] || itsAttr[ORIENTATION]) {
209 std::vector<double> origin = Attributes::getRealArray(itsAttr[ORIGIN]);
210 if (origin.size() == 3) {
211 line->setOrigin3D(Vector_t(origin[0],
212 origin[1],
213 origin[2]));
214 } else {
215 line->setOrigin3D(Vector_t(0.0));
216 if (itsAttr[ORIGIN]) {
217 throw OpalException("Line::parse","Parameter origin is array of 3 values (x, y, z);\n" +
218 std::to_string(origin.size()) + " values provided");
219 }
220 }
221
222 std::vector<double> direction = Attributes::getRealArray(itsAttr[ORIENTATION]);
223 if (direction.size() == 3) {
224 const double &theta = direction[0];
225 const double &phi = direction[1];
226 const double &psi = direction[2];
227
228 Quaternion rotTheta(cos(0.5 * theta), 0, -sin(0.5 * theta), 0);
229 Quaternion rotPhi(cos(0.5 * phi), -sin(0.5 * phi), 0, 0);
230 Quaternion rotPsi(cos(0.5 * psi), 0, 0, -sin(0.5 * psi));
231 line->setInitialDirection(rotPsi * rotPhi * rotTheta);
232 } else {
233 line->setInitialDirection(Quaternion(1, 0, 0, 0));
234 if (itsAttr[ORIENTATION]) {
235 throw OpalException("Line::parse","Parameter orientation is array of 3 values (theta, phi, psi);\n" +
236 std::to_string(direction.size()) + " values provided");
237 }
238 }
239
240 line->setRelativeFlag(true);
241 } else {
242 const Vector_t origin(Attributes::getReal(itsAttr[X]),
245
246 const double theta = Attributes::getReal(itsAttr[THETA]);
247 const double phi = Attributes::getReal(itsAttr[PHI]);
248 const double psi = Attributes::getReal(itsAttr[PSI]);
249
250 Quaternion rotTheta(cos(0.5 * theta), 0, -sin(0.5 * theta), 0);
251 Quaternion rotPhi(cos(0.5 * phi), -sin(0.5 * phi), 0, 0);
252 Quaternion rotPsi(cos(0.5 * psi), 0, 0, -sin(0.5 * psi));
253
254 line->setOrigin3D(origin);
255 line->setInitialDirection(rotPsi * rotPhi * rotTheta);
256
257 line->setRelativeFlag(!itsAttr[X].defaultUsed() ||
258 !itsAttr[Y].defaultUsed() ||
259 !itsAttr[Z].defaultUsed() ||
260 !itsAttr[THETA].defaultUsed() ||
261 !itsAttr[PHI].defaultUsed() ||
262 !itsAttr[PSI].defaultUsed());
263 }
264}
265
266
267void Line::print(std::ostream &os) const {
268 os << getOpalName() << ":LINE=(";
269 const FlaggedBeamline *line = fetchLine();
270 bool seen = false;
271
272 for(FlaggedBeamline::const_iterator i = line->begin();
273 i != line->end(); ++i) {
274 const std::string name = i->getElement()->getName();
275 if(name[0] != '#') {
276 if(seen) os << ',';
277 if(i->getReflectionFlag()) os << '-';
278 os << name;
279 seen = true;
280 }
281 }
282
283 os << ')';
284 os << ';';
285 os << std::endl;
286}
287
288
290 return dynamic_cast<FlaggedBeamline *>(getElement());
291}
292
293
295 FlaggedBeamline *line = fetchLine();
296
297 do {
298 // Reversed member ?
299 bool rev = stat.delimiter('-');
300
301 // Repetition count.
302 int repeat = 1;
303 if(stat.integer(repeat)) parseDelimiter(stat, '*');
304
305 // List member.
306 if(stat.delimiter('(')) {
307 // Anonymous sub-line is expanded immediately.
308 Line nestedLine;
309 nestedLine.parseList(stat);
310 FlaggedBeamline *subLine = nestedLine.fetchLine();
311
312 while(repeat-- > 0) {
313 if(rev) {
314 for(FlaggedBeamline::reverse_iterator i = subLine->rbegin();
315 i != subLine->rend(); ++i) {
316 FlaggedElmPtr fep(*i);
317 fep.setReflectionFlag(false);
318 line->push_back(fep);
319 }
320 } else {
321 for(FlaggedBeamline::iterator i = subLine->begin();
322 i != subLine->end(); ++i) {
323 FlaggedElmPtr fep(*i);
324 line->push_back(fep);
325 }
326 }
327 }
328 } else {
329 // Identifier.
330 std::string name = parseString(stat, "Line member expected.");
332
333 if(! obj.isValid()) {
334 throw ParseError("Line::parseList()",
335 "Element \"" + name + "\" is undefined.");
336 }
337
338 if(stat.delimiter('(')) {
339 // Line or sequence macro.
340 // This instance will always be an anonymous object.
341 obj = obj->makeInstance(name, stat, 0);
342 }
343
344 if(Element *elem = dynamic_cast<Element *>(&*obj)) {
345 while(repeat-- > 0) {
346 ElementBase *base = elem->getElement();
347 FlaggedElmPtr member(base, rev);
348 line->push_back(member);
349 }
350 } else {
351 throw ParseError("Line::parseList()",
352 "Object \"" + name + "\" cannot be a line member.");
353 }
354 }
355 } while(stat.delimiter(','));
356
357 parseDelimiter(stat, ')');
358}
359
360
361void Line::replace(Object *oldObject, Object *newObject) {
362 Element *oldElement = dynamic_cast<Element *>(oldObject);
363 Element *newElement = dynamic_cast<Element *>(newObject);
364
365 if(oldElement != 0 && newElement != 0) {
366 Replacer rep(*fetchLine(),
367 oldElement->getOpalName(),
368 newElement->getElement());
369 rep.execute();
370 }
371}
TBeamline< FlaggedElmPtr > FlaggedBeamline
A beam line with flagged elements.
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
@ SIZE
Definition: IndexMap.cpp:174
#define X(arg)
Definition: fftpack.cpp:112
std::complex< double > a
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
const std::string name
Representation objects and parsers for attribute expressions.
Definition: Expressions.h:64
std::string parseString(Statement &, const char msg[])
Parse string value.
void parseDelimiter(Statement &stat, char delim)
Test for one-character delimiter.
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:252
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
Definition: Attributes.cpp:240
Attribute makeRealArray(const std::string &name, const std::string &help)
Create real array attribute.
Definition: Attributes.cpp:289
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
Definition: Attributes.cpp:294
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
Definition: Attributes.cpp:332
std::string::iterator iterator
Definition: MSLang.h:16
A representation of an Object attribute.
Definition: Attribute.h:52
void setDefault()
Assign default value.
Definition: Attribute.cpp:145
void parse(Statement &stat, bool eval)
Parse attribute.
Definition: Attribute.cpp:127
The base class for all OPAL beam lines and sequences.
Definition: BeamSequence.h:32
static Element * find(const std::string &name)
Find named Element.
Definition: Element.cpp:45
ElementBase * getElement() const
Return the embedded CLASSIC element.
Definition: Element.h:120
void setElement(ElementBase *)
Assign new CLASSIC element.
Definition: Element.h:125
The base class for all OPAL objects.
Definition: Object.h:48
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition: Object.cpp:191
virtual Object * makeInstance(const std::string &name, Statement &, const Parser *)
Macro handler function.
Definition: Object.cpp:91
const std::string & getOpalName() const
Return object name.
Definition: Object.cpp:310
int increment()
Increment and return the occurrence counter.
Definition: Object.cpp:346
virtual Attribute * findAttribute(const std::string &name)
Find an attribute by name.
Definition: Object.cpp:64
std::vector< Attribute > itsAttr
The object attributes.
Definition: Object.h:216
void apply(const ObjectFunction &)
Apply a function to all objects.
Definition: OpalData.cpp:469
Object * find(const std::string &name)
Find entry.
Definition: OpalData.cpp:566
static OpalData * getInstance()
Definition: OpalData.cpp:196
Clear Reference.
Definition: OpalData.h:149
virtual const std::string & getName() const
Get element name.
virtual ElementBase * copyStructure()
Make a structural copy.
virtual void execute()
Apply the algorithm to the top-level beamline.
A section of a beam line.
Definition: FlaggedElmPtr.h:36
void setReflectionFlag(bool flag) const
Set reflection flag.
void setRelativeFlag(bool flag)
Definition: TBeamline.h:448
void setOrigin3D(const Vector_t &ori)
Definition: TBeamline.h:428
void setInitialDirection(const Quaternion &rot)
Definition: TBeamline.h:438
bool isValid() const
Test for validity.
Definition: OwnPtr.h:144
Reference-counted pointer.
Definition: Pointer.h:38
bool isValid() const
Test for validity.
Definition: Pointer.h:172
Interface for statements.
Definition: Statement.h:38
bool integer(int &value)
Return signed integer.
Definition: Statement.cpp:79
bool delimiter(char c)
Test for delimiter.
Definition: Statement.cpp:101
Abstract interface for a stream of input tokens.
Definition: TokenStream.h:33
Parse exception.
Definition: ParseError.h:32
Object attribute with an `‘automatic’' scalar value.
Definition: SAutomatic.h:38
A scalar expression with two scalar operands.
Definition: SBinary.h:39
An expression defined as a reference to a scalar.
Definition: SRefExpr.h:41
A function of two U's returning a T.
Definition: TFunction2.h:31
Definition: Line.h:32
virtual void replace(Object *oldObject, Object *newObject)
Replace references.
Definition: Line.cpp:361
friend class LineTemplate
Definition: Line.h:34
virtual void parse(Statement &stat)
Parse the line object.
Definition: Line.cpp:150
virtual FlaggedBeamline * fetchLine() const
Return the embedded CLASSIC beam line.
Definition: Line.cpp:289
virtual void print(std::ostream &stream) const
Print the line.
Definition: Line.cpp:267
virtual Line * copy(const std::string &name)
Make complete copy.
Definition: Line.cpp:122
virtual double getLength() const
Return line length.
Definition: Line.cpp:130
virtual ~Line()
Definition: Line.cpp:113
virtual Object * makeTemplate(const std::string &name, TokenStream &is, Statement &stat)
Make a line template.
Definition: Line.cpp:136
void parseList(Statement &)
Definition: Line.cpp:294
Line()
Exemplar constructor.
Definition: Line.cpp:65
virtual Line * clone(const std::string &name)
Make clone.
Definition: Line.cpp:117
void parseTemplate(TokenStream &is, Statement &stat)
Parse the line template.
Replace all references to named element by a new version.
Definition: Replacer.h:32
The base class for all OPAL exceptions.
Definition: OpalException.h:28
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6