OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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"
26#include "Beamlines/Beamline.h"
27#include "Elements/OpalDrift.h"
28
29#include "Lines/Replacer.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.
41namespace {
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
83Sequence::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
97Sequence *Sequence::clone(const std::string &name) {
98 return new Sequence(name, this);
99}
100
101
102Sequence *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
124Sequence::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
150double Sequence::getLength() const {
151 return Attributes::getReal(itsAttr[LENGTH]);
152}
153
154
156 if(itsRefPoint.empty()) {
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]);
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
206void 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
218void 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
259void 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
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.
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
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:310
int increment()
Increment and return the occurrence counter.
Definition: Object.cpp:346
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:273
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 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:462
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