OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Sequence.cpp
Go to the documentation of this file.
1 //
2 // Class Sequence
3 // The SEQUENCE definition.
4 // A Sequence contains a CLASSIC TBeamline<SequenceMember> which represents
5 // the sequence of elements in the line and their positions. The sequence
6 // definition is parsed in collaboration with a SequenceParser.
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/Sequence.h"
24 #include "Attributes/Attributes.h"
25 #include "BeamlineCore/DriftRep.h"
26 #include "Beamlines/Beamline.h"
27 #include "Elements/OpalDrift.h"
28 
29 #include "Lines/Replacer.h"
30 #include "Lines/SequenceParser.h"
31 #include "Lines/SequenceTemplate.h"
33 #include "Utilities/Options.h"
34 
35 #include <cmath>
36 #include <iostream>
37 #include <sstream>
38 #include <vector>
39 
40 // The attributes of class Sequence.
41 namespace {
42  enum {
43  TYPE, // The design type.
44  LENGTH, // The total sequence length.
45  REFER, // The reference position for members.
46  REFPOS, // The reference position for the sequence.
47  SIZE
48  };
49 }
50 
51 
53  BeamSequence(SIZE, "SEQUENCE",
54  "The \"SEQUENCE\" statement initiates parsing of an "
55  "element sequence.\n"
56  "\t<label>: SEQUENCE,L=<length>,REFER=<reference>\n"
57  "\t\t...\n"
58  "\t\t<object>: <class>,AT=<real>{,<attribute>=<value>}\n"
59  "\t\t<object>: <class>,DRIFT=<real>{,<attribute>=<value>}\n"
60  "\t\t...\n"
61  "\tEND;") {
63  ("TYPE", "The design type");
65  ("L", "Total length of sequence in m");
66 
68  ("REFER",
69  "Reference position for members:\n"
70  "\tENTRY | EXIT | CENTRE (default is CENTRE)", "CENTRE");
72  ("REFPOS",
73  "Element giving reference position for this sequence"
74  "\t(if given, this position is used instead of the centre, when the"
75  "\tsequence is nested in another sequence with \"REFER=CENTRE\")");
76 
77  setElement(new TLine("SEQUENCE"));
78 
80 }
81 
82 
83 Sequence::Sequence(const std::string &name, Sequence *parent):
84  BeamSequence(name, parent)
85  // Do not copy parent's line, it will be filled in at parse time,
86  // In case of a clone within a sequence, it is filled by the method
87  // SequenceParser::parseMember().
88 {
89  setElement(new TLine(name));
90 }
91 
92 
94 {}
95 
96 
97 Sequence *Sequence::clone(const std::string &name) {
98  return new Sequence(name, this);
99 }
100 
101 
102 Sequence *Sequence::copy(const std::string &name) {
103  TLine *oldLine = fetchLine();
104  TLine *newLine = new TLine(name);
105 
106  for(TLine::iterator i = oldLine->begin(); i != oldLine->end(); ++i) {
107  SequenceMember member(*i);
108 
109  if(i->itsType == SequenceMember::GENERATED) {
110  member.setElement(member.getElement()->clone());
111  } else {
112  member.setElement(member.getElement()->copyStructure());
113  }
114 
115  newLine->push_back(member);
116  }
117 
118  Sequence *newSeq = dynamic_cast<Sequence *>(clone(name));
119  newSeq->storeLine(*newLine);
120  return newSeq;
121 }
122 
124 Sequence::findNamedPosition(TLine &line, const std::string &name) const {
125  TLine::iterator first = line.begin();
126  TLine::iterator last = line.end();
127 
128  for(TLine::iterator iter = first; iter != last; ++iter) {
129  if(iter->itsType != SequenceMember::GENERATED) {
130  if(iter->getElement()->getName() == name) {
131  TLine::iterator test = iter;
132 
133  while(++test != line.end()) {
134  if(test->getElement()->getName() == name) {
135  throw OpalException("Sequence::findNamedPosition()", "Element \"" +
136  name + "\" is not unique in sequence.");
137  }
138  }
139 
140  return iter;
141  }
142  }
143  }
144 
145  throw OpalException("Sequence::findNamedPosition()",
146  "Element \"" + name + "\" not found in sequence.");
147 }
148 
149 
150 double Sequence::getLength() const {
151  return Attributes::getReal(itsAttr[LENGTH]);
152 }
153 
154 
156  if(itsRefPoint.empty()) {
157  return Element::getEntrance(ref);
158  } else {
159  TLine *line = fetchLine();
161  return (- iter->itsPosition);
162  }
163 }
164 
165 
167  if(itsRefPoint.empty()) {
168  return Element::getExit(ref);
169  } else {
170  TLine *line = fetchLine();
172  return (getLength() - iter->itsPosition);
173  }
174 }
175 
176 
178  std::string ref = Attributes::getString(itsAttr[REFER]);
179  ReferenceType code = IS_CENTRE;
180 
181  if(ref == "ENTRY") {
182  code = IS_ENTRY;
183  } else if(ref == "EXIT") {
184  code = IS_EXIT;
185  }
186 
187  return code;
188 }
189 
190 
192 (const std::string &name, TokenStream &is, Statement &statement) {
193  SequenceTemplate *macro = new SequenceTemplate(name, this);
194 
195  try {
196  macro->parseTemplate(is, statement);
197  return macro;
198  } catch(...) {
199  delete macro;
200  macro = 0;
201  throw;
202  }
203 }
204 
205 
206 void Sequence::parse(Statement &statement) {
207  // Look for "REFER" and "L" attributes.
208  Object::parse(statement);
209 
210  // Set up to parse members.
211  SequenceParser parser(this);
212  parser.run();
213  if(itsAttr[REFPOS]) itsRefPoint = Attributes::getString(itsAttr[REFPOS]);
214 }
215 
216 
217 
218 void Sequence::print(std::ostream &os) const {
219  TLine *line = fetchLine();
220  std::streamsize old_prec = os.precision(12);
221 
222  if(isShared()) os << "SHARED ";
223  os << getOpalName() << ":SEQUENCE";
224 
225  for(const Attribute& i : itsAttr) {
226  if(i) {
227  os << ',' << i.getName()
228  << (i.isExpression() ? ":=" : "=") << i;
229  }
230  }
231 
232  os << ";" << std::endl;
233 
234  for(TLine::const_iterator iter = line->begin();
235  iter != line->end(); ++iter) {
236  const SequenceMember &member = *iter;
237 
238  if(member.itsType != SequenceMember::GENERATED) {
239  const std::string &name = member.getElement()->getName();
240  if(name[0] != '#') {
241  // Name of current element.
242  os << " ";
243  if(member.getReflectionFlag()) os << '-';
244  os << name;
245 
246  // Position of current element.
247  os << ",AT=" << member.itsPosition;
248  os << ';' << std::endl;
249  }
250  }
251  }
252 
253  os << "ENDSEQUENCE;" << std::endl;
254 
255  os.precision(old_prec);
256 }
257 
258 
259 void Sequence::replace(Object *oldObject, Object *newObject) {
260  Element *oldElement = dynamic_cast<Element *>(oldObject);
261  Element *newElement = dynamic_cast<Element *>(newObject);
262 
263  if(oldElement != 0 && newElement != 0) {
264  Replacer rep(*fetchLine(),
265  oldElement->getOpalName(),
266  newElement->getElement());
267  rep.execute();
268  }
269 }
270 
271 
273  TLine *line = fetchLine();
274  if(! line->empty()) updateList(this, line);
275 }
276 
277 
279  return dynamic_cast<TLine *>(getElement());
280 }
281 
282 
283 void Sequence::storeLine(TLine &newLine) {
284  // Remove any old line and assign new one.
285  TLine *line = fetchLine();
286  line->erase(line->begin(), line->end());
287  line->swap(newLine);
288 
289  // Store the reference code.
290  itsCode = getReference();
291 
292  // Clear all occurrence counts.
294 
295  // Set occurrence counts.
296  for(TLine::iterator i = line->begin(); i != line->end(); ++i) {
297  if(i->itsType != SequenceMember::GENERATED) {
298  const std::string &name = i->getElement()->getName();
299  Element *elem = Element::find(name);
300  // ada 4.5 2000 to speed up matching, add a pointer to
301  // opal elements in order to avoid serching the opal elements
302  i->OpalElement = elem;
303  i->setCounter(elem->increment());
304  }
305  }
306 
307  // Fill in the drift spaces.
308  // update();
309 }
310 
311 
312 void Sequence::addEndMarkers(TLine &line) const {
313  SequenceMember member;
314  member.setElement(Element::find("#S")->getElement());
315  member.itsPosition = 0.0;
318  line.push_front(member);
319  member.setElement(Element::find("#E")->getElement());
320  member.itsPosition = getLength();
321  line.push_back(member);
322 }
323 
324 
326  // It is assumed that the elements preceding and following the drift exist.
327  TLine::iterator prev(drift);
328  --prev;
329  const std::string prev_name = prev->getElement()->getName();
330 
331  // ada 4.5 2000 to speed up matching, add a pointer to
332  // opal elements in order to avoid serching the opal elements
333  // Element *prev_elem = Element::find(prev_name);
334  Pointer<Element> prev_elem = prev->OpalElement;
335  double prev_exit = prev->itsPosition + prev_elem->getExit(itsCode);
336 
337  TLine::iterator next(drift);
338  ++next;
339  const std::string next_name = next->getElement()->getName();
340 
341  // ada 4.5 2000 to speed up matching, add a pointer to
342  // opal elements in order to avoid serching the opal elements
343  // Element *next_elem = Element::find(next_name);
344  Pointer<Element> next_elem = next->OpalElement;
345  double next_entry = next->itsPosition + next_elem->getEntrance(itsCode);
346 
347  double driftLength = next_entry - prev_exit;
348 
349  static double tolerance = 1.0e-8;
350  if(std::abs(driftLength) < tolerance) {
351  driftLength = 0.0;
352  } else if(driftLength < 0.0) {
353  driftLength = 0.0;
354  std::ostringstream os;
355  os << "Inconsistent positions in sequence \"" << getOpalName() + "\";\n"
356  << "previous element: \"" << prev_name + "\" at = "
357  << prev->itsPosition << ",\n"
358  << "following element: \"" << next_name + "\" at = "
359  << next->itsPosition << "." << std::ends;
360  throw OpalException("Sequence::findDriftLength()", os.str());
361  // ada 15-6-2000 move driftLength = 0.0; bevore throw
362  }
363 
364  return driftLength;
365 }
366 
367 
369  TLine::iterator i = line.begin();
370  while(true) {
371  ++i;
372  if(i == line.end()) break;
373  SequenceMember member;
374  DriftRep *drift = new DriftRep();
375  drift->setName("[DRIFT]");
376  member.setElement(drift);
378  line.insert(i, member);
379  }
380 }
381 
382 
384  TLine::iterator iter = line->begin();
385  TLine::iterator last = line->end();
386 
387  while(true) {
388  // Recursive call for nested beam non-shared sequence.
389  if(iter == last) break;
390  ElementBase *base = iter->getElement();
391  if(! base->isSharable()) {
392  TLine *sub_line = dynamic_cast<TLine *>(base);
393  if(sub_line != 0) {
394  const std::string &sub_name = sub_line->getName();
395  Sequence *sub_seq = dynamic_cast<Sequence *>(OpalData::getInstance()->find(sub_name));
396  updateList(sub_seq, sub_line);
397  }
398  }
399  ++iter;
400 
401  // Fill in drift length.
402  if(iter == last) break;
403  double driftLength = seq->findDriftLength(iter);
404  iter->setLength(driftLength);
405  ++iter;
406  }
407 }
@ SIZE
Definition: IndexMap.cpp:174
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
const std::string name
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
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:343
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
The base class for all OPAL beam lines and sequences.
Definition: BeamSequence.h:32
virtual double getEntrance(ReferenceType) const
Return arc length from origin to entrance (negative !).
Definition: Element.cpp:71
static Element * find(const std::string &name)
Find named Element.
Definition: Element.cpp:45
ReferenceType
Reference for element positioning.
Definition: Element.h:44
@ IS_EXIT
Definition: Element.h:47
@ IS_ENTRY
Definition: Element.h:45
@ IS_CENTRE
Definition: Element.h:46
ElementBase * getElement() const
Return the embedded CLASSIC element.
Definition: Element.h:120
void setElement(ElementBase *)
Assign new CLASSIC element.
Definition: Element.h:125
virtual double getExit(ReferenceType) const
Return arc length from origin to exit (positive !).
Definition: Element.cpp:86
The base class for all OPAL objects.
Definition: Object.h:48
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition: Object.cpp:191
const std::string & getOpalName() const
Return object name.
Definition: Object.cpp:281
int increment()
Increment and return the occurrence counter.
Definition: Object.cpp:317
std::vector< Attribute > itsAttr
The object attributes.
Definition: Object.h:216
virtual void parse(Statement &)
Parse the object.
Definition: Object.cpp:97
virtual bool isShared() const
Shared flag.
Definition: Object.cpp:244
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 void setName(const std::string &name)
Set element name.
virtual const std::string & getName() const
Get element name.
virtual ElementBase * clone() const =0
Return clone.
virtual ElementBase * copyStructure()
Make a structural copy.
bool isSharable() const
Test if the element can be shared.
Definition: ElementBase.h:480
virtual void execute()
Apply the algorithm to the top-level beamline.
ElementBase * getElement() const
Get the element pointer.
Definition: ElmPtr.h:58
void setElement(ElementBase *)
Set the element pointer.
Definition: ElmPtr.h:63
bool getReflectionFlag() const
Get reflection flag.
Interface for statements.
Definition: Statement.h:38
Abstract interface for a stream of input tokens.
Definition: TokenStream.h:33
Replace all references to named element by a new version.
Definition: Replacer.h:32
virtual double getLength() const
Return sequence length.
Definition: Sequence.cpp:150
TBeamline< SequenceMember > TLine
The type of a sequence line.
Definition: Sequence.h:42
virtual void print(std::ostream &) const
Print sequence.
Definition: Sequence.cpp:218
std::string itsRefPoint
Definition: Sequence.h:127
ReferenceType itsCode
Definition: Sequence.h:124
virtual Object * makeTemplate(const std::string &, TokenStream &, Statement &)
Make a sequence template.
Definition: Sequence.cpp:192
void insertDrifts(TLine &line)
Definition: Sequence.cpp:368
Sequence()
Exemplar constructor.
Definition: Sequence.cpp:52
virtual double getExit(ReferenceType) const
Return the arc length from origin to exit.
Definition: Sequence.cpp:166
virtual double getEntrance(ReferenceType) const
Return the arc length from origin to entrance.
Definition: Sequence.cpp:155
virtual void update()
Update the embedded CLASSIC beam line.
Definition: Sequence.cpp:272
TLine::iterator findNamedPosition(TLine &, const std::string &) const
Definition: Sequence.cpp:124
virtual TLine * fetchLine() const
Return the embedded CLASSIC beam line.
Definition: Sequence.cpp:278
virtual Sequence * clone(const std::string &name)
Make clone.
Definition: Sequence.cpp:97
void storeLine(TLine &line)
Store sequence line.
Definition: Sequence.cpp:283
virtual void replace(Object *oldObject, Object *newObject)
Replace references to elements.
Definition: Sequence.cpp:259
virtual Sequence * copy(const std::string &name)
Make copy of the sequence line.
Definition: Sequence.cpp:102
void addEndMarkers(TLine &line) const
Definition: Sequence.cpp:312
virtual void parse(Statement &)
Parse sequence.
Definition: Sequence.cpp:206
ReferenceType getReference() const
Return the reference type flag.
Definition: Sequence.cpp:177
virtual ~Sequence()
Definition: Sequence.cpp:93
friend class SequenceTemplate
Definition: Sequence.h:37
double findDriftLength(TLine::iterator drift) const
Definition: Sequence.cpp:325
static void updateList(Sequence *, TLine *)
Definition: Sequence.cpp:383
A member of a SEQUENCE.
MemberType itsType
Type word.
double itsPosition
The position attribute ("AT" or "DRIFT").
PositionType itsFlag
Flag word.
The parser for SEQUENCE members.
void parseTemplate(TokenStream &, Statement &)
Parse the sequence template.
virtual void run() const
Read current stream.
Definition: OpalParser.cpp:602
The base class for all OPAL exceptions.
Definition: OpalException.h:28
int precision() const
Definition: Inform.h:112