OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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"
26 #include "Attributes/Attributes.h"
27 #include "Beamlines/Beamline.h"
29 #include "Expressions/SAutomatic.h"
30 #include "Expressions/SBinary.h"
31 #include "Expressions/SRefExpr.h"
32 #include "Expressions/TFunction2.h"
33 #include "Lines/LineTemplate.h"
34 #include "Lines/Replacer.h"
35 #include "Parser/Statement.h"
36 #include "Utilities/Options.h"
37 #include "Utilities/ParseError.h"
38 #include <algorithm>
39 #include <iostream>
40 
41 using namespace Expressions;
42 
43 // The attributes of class Line.
44 namespace {
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 
79  itsAttr[ORIENTATION] = Attributes::makeRealArray
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 
106 Line::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 
117 Line *Line::clone(const std::string &name) {
118  return new Line(name, this);
119 }
120 
121 
122 Line *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 
130 double 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 
150 void Line::parse(Statement &stat) {
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.
174  PtrToScalar<double> expr;
175  for(FlaggedBeamline::iterator i = line->begin(); i != line->end(); ++i) {
176  // Accumulate length.
177  PtrToScalar<double> temp =
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.");
195  Attribute *attr = findAttribute(name);
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 
267 void 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 
361 void 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 }
@ SIZE
Definition: IndexMap.cpp:174
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
TBeamline< FlaggedElmPtr > FlaggedBeamline
A beam line with flagged elements.
#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:281
int increment()
Increment and return the occurrence counter.
Definition: Object.cpp:317
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:468
Object * find(const std::string &name)
Find entry.
Definition: OpalData.cpp:565
static OpalData * getInstance()
Definition: OpalData.cpp:195
Clear Reference.
Definition: OpalData.h:145
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:446
void setOrigin3D(const Vector_t &ori)
Definition: TBeamline.h:426
void setInitialDirection(const Quaternion &rot)
Definition: TBeamline.h:436
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