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