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