OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
Sequence.cpp
Go to the documentation of this file.
1//
2// Class Sequence
3// The SEQUENCE definition.
4// A Sequence contains an OPALX 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
92
93Sequence* Sequence::clone(const std::string& name) { return new Sequence(name, this); }
94
95Sequence* Sequence::copy(const std::string& name) {
96 TLine* oldLine = fetchLine();
97 TLine* newLine = new TLine(name);
98
99 for (TLine::iterator i = oldLine->begin(); i != oldLine->end(); ++i) {
100 SequenceMember member(*i);
101
102 if (i->itsType == SequenceMember::GENERATED) {
103 member.setElement(member.getElement()->clone());
104 } else {
105 member.setElement(member.getElement()->copyStructure());
106 }
107
108 newLine->push_back(member);
109 }
110
111 Sequence* newSeq = dynamic_cast<Sequence*>(clone(name));
112 newSeq->storeLine(*newLine);
113 return newSeq;
114}
115
116Sequence::TLine::iterator Sequence::findNamedPosition(TLine& line, const std::string& name) const {
117 TLine::iterator first = line.begin();
118 TLine::iterator last = line.end();
119
120 for (TLine::iterator iter = first; iter != last; ++iter) {
121 if (iter->itsType != SequenceMember::GENERATED) {
122 if (iter->getElement()->getName() == name) {
123 TLine::iterator test = iter;
124
125 while (++test != line.end()) {
126 if (test->getElement()->getName() == name) {
127 throw OpalException(
128 "Sequence::findNamedPosition()",
129 "Element \"" + name + "\" is not unique in sequence.");
130 }
131 }
132
133 return iter;
134 }
135 }
136 }
137
138 throw OpalException(
139 "Sequence::findNamedPosition()", "Element \"" + name + "\" not found in sequence.");
140}
141
142double Sequence::getLength() const { return Attributes::getReal(itsAttr[LENGTH]); }
143
145 if (itsRefPoint.empty()) {
146 return Element::getEntrance(ref);
147 } else {
148 TLine* line = fetchLine();
149 TLine::iterator iter = findNamedPosition(*line, itsRefPoint);
150 return (-iter->itsPosition);
151 }
152}
153
155 if (itsRefPoint.empty()) {
156 return Element::getExit(ref);
157 } else {
158 TLine* line = fetchLine();
159 TLine::iterator iter = findNamedPosition(*line, itsRefPoint);
160 return (getLength() - iter->itsPosition);
161 }
162}
163
165 std::string ref = Attributes::getString(itsAttr[REFER]);
167
168 if (ref == "ENTRY") {
169 code = IS_ENTRY;
170 } else if (ref == "EXIT") {
171 code = IS_EXIT;
172 }
173
174 return code;
175}
176
177Object* Sequence::makeTemplate(const std::string& name, TokenStream& is, Statement& statement) {
178 SequenceTemplate* macro = new SequenceTemplate(name, this);
179
180 try {
181 macro->parseTemplate(is, statement);
182 return macro;
183 } catch (...) {
184 delete macro;
185 macro = 0;
186 throw;
187 }
188}
189
190void Sequence::parse(Statement& statement) {
191 // Look for "REFER" and "L" attributes.
192 Object::parse(statement);
193
194 // Set up to parse members.
195 SequenceParser parser(this);
196 parser.run();
197 if (itsAttr[REFPOS]) itsRefPoint = Attributes::getString(itsAttr[REFPOS]);
198}
199
200void Sequence::print(std::ostream& os) const {
201 TLine* line = fetchLine();
202 std::streamsize old_prec = os.precision(12);
203
204 if (isShared()) os << "SHARED ";
205 os << getOpalName() << ":SEQUENCE";
206
207 for (const Attribute& i : itsAttr) {
208 if (i) {
209 os << ',' << i.getName() << (i.isExpression() ? ":=" : "=") << i;
210 }
211 }
212
213 os << ";" << std::endl;
214
215 for (TLine::const_iterator iter = line->begin(); iter != line->end(); ++iter) {
216 const SequenceMember& member = *iter;
217
218 if (member.itsType != SequenceMember::GENERATED) {
219 const std::string& name = member.getElement()->getName();
220 if (name[0] != '#') {
221 // Name of current element.
222 os << " ";
223 if (member.getReflectionFlag()) os << '-';
224 os << name;
225
226 // Position of current element.
227 os << ",AT=" << member.itsPosition;
228 os << ';' << std::endl;
229 }
230 }
231 }
232
233 os << "ENDSEQUENCE;" << std::endl;
234
235 os.precision(old_prec);
236}
237
238void Sequence::replace(Object* oldObject, Object* newObject) {
239 Element* oldElement = dynamic_cast<Element*>(oldObject);
240 Element* newElement = dynamic_cast<Element*>(newObject);
241
242 if (oldElement != 0 && newElement != 0) {
243 Replacer rep(*fetchLine(), oldElement->getOpalName(), newElement->getElement());
244 rep.execute();
245 }
246}
247
249 TLine* line = fetchLine();
250 if (!line->empty()) updateList(this, line);
251}
252
253Sequence::TLine* Sequence::fetchLine() const { return dynamic_cast<TLine*>(getElement()); }
254
256 // Remove any old line and assign new one.
257 TLine* line = fetchLine();
258 line->erase(line->begin(), line->end());
259 line->swap(newLine);
260
261 // Store the reference code.
263
264 // Clear all occurrence counts.
266
267 // Set occurrence counts.
268 for (TLine::iterator i = line->begin(); i != line->end(); ++i) {
269 if (i->itsType != SequenceMember::GENERATED) {
270 const std::string& name = i->getElement()->getName();
271 Element* elem = Element::find(name);
272 // ada 4.5 2000 to speed up matching, add a pointer to
273 // opal elements in order to avoid serching the opal elements
274 i->OpalElement = std::shared_ptr<Element>(elem);
275 i->setCounter(elem->increment());
276 }
277 }
278
279 // Fill in the drift spaces.
280 // update();
281}
282
284 SequenceMember member;
285 member.setElement(Element::find("#S")->getElementPtr());
286 member.itsPosition = 0.0;
289 line.push_front(member);
290 member.setElement(Element::find("#E")->getElementPtr());
291 member.itsPosition = getLength();
292 line.push_back(member);
293}
294
295double Sequence::findDriftLength(TLine::iterator drift) const {
296 // It is assumed that the elements preceding and following the drift exist.
297 TLine::iterator prev(drift);
298 --prev;
299 const std::string prev_name = prev->getElement()->getName();
300
301 // ada 4.5 2000 to speed up matching, add a pointer to
302 // opal elements in order to avoid serching the opal elements
303 // Element *prev_elem = Element::find(prev_name);
304 std::shared_ptr<Element> prev_elem = prev->OpalElement;
305 double prev_exit = prev->itsPosition + prev_elem->getExit(itsCode);
306
307 TLine::iterator next(drift);
308 ++next;
309 const std::string next_name = next->getElement()->getName();
310
311 // ada 4.5 2000 to speed up matching, add a pointer to
312 // opal elements in order to avoid serching the opal elements
313 // Element *next_elem = Element::find(next_name);
314 std::shared_ptr<Element> next_elem = next->OpalElement;
315 double next_entry = next->itsPosition + next_elem->getEntrance(itsCode);
316
317 double driftLength = next_entry - prev_exit;
318
319 static double tolerance = 1.0e-8;
320 if (std::abs(driftLength) < tolerance) {
321 driftLength = 0.0;
322 } else if (driftLength < 0.0) {
323 driftLength = 0.0;
324 std::ostringstream os;
325 os << "Inconsistent positions in sequence \"" << getOpalName() + "\";\n"
326 << "previous element: \"" << prev_name + "\" at = " << prev->itsPosition << ",\n"
327 << "following element: \"" << next_name + "\" at = " << next->itsPosition << "."
328 << std::ends;
329 throw OpalException("Sequence::findDriftLength()", os.str());
330 // ada 15-6-2000 move driftLength = 0.0; bevore throw
331 }
332
333 return driftLength;
334}
335
337 TLine::iterator i = line.begin();
338 while (true) {
339 ++i;
340 if (i == line.end()) break;
341 SequenceMember member;
342 DriftRep* drift = new DriftRep();
343 drift->setName("[DRIFT]");
344 member.setElement(drift);
346 line.insert(i, member);
347 }
348}
349
351 TLine::iterator iter = line->begin();
352 TLine::iterator last = line->end();
353
354 while (true) {
355 // Recursive call for nested beam non-shared sequence.
356 if (iter == last) break;
357 ElementBase* base = iter->getElement();
358 if (!base->isSharable()) {
359 TLine* sub_line = dynamic_cast<TLine*>(base);
360 if (sub_line != 0) {
361 const std::string& sub_name = sub_line->getName();
362 Sequence* sub_seq =
363 dynamic_cast<Sequence*>(OpalData::getInstance()->find(sub_name));
364 updateList(sub_seq, sub_line);
365 }
366 }
367 ++iter;
368
369 // Fill in drift length.
370 if (iter == last) break;
371 double driftLength = seq->findDriftLength(iter);
372 iter->setLength(driftLength);
373 ++iter;
374 }
375}
@ SIZE
Definition IndexMap.cpp:179
A representation of an Object attribute.
Definition Attribute.h:52
The base class for all OPAL beam lines and sequences.
void execute() override
Apply the algorithm to the top-level beamline.
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.
virtual double getEntrance(ReferenceType) const
Return arc length from origin to entrance (negative !).
Definition Element.cpp:54
std::shared_ptr< ElementBase > getElementPtr() const
Return the embedded OPALX element as shared_ptr.
Definition Element.h:121
static Element * find(const std::string &name)
Find named Element.
Definition Element.cpp:39
ReferenceType
Reference for element positioning.
Definition Element.h:43
@ IS_EXIT
Definition Element.h:46
@ IS_ENTRY
Definition Element.h:44
@ IS_CENTRE
Definition Element.h:45
ElementBase * getElement() const
Return the embedded OPALX element.
Definition Element.h:119
void setElement(ElementBase *)
Assign new OPALX element.
Definition Element.h:123
virtual double getExit(ReferenceType) const
Return arc length from origin to exit (positive !).
Definition Element.cpp:67
ElementBase * getElement() const
Get the element pointer.
Definition ElmPtr.h:56
void setElement(ElementBase *)
Set the element pointer.
Definition ElmPtr.h:58
bool getReflectionFlag() const
Get reflection flag.
The base class for all OPAL objects.
Definition Object.h:45
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition Object.cpp:169
const std::string & getOpalName() const
Return object name.
Definition Object.cpp:267
int increment()
Increment and return the occurrence counter.
Definition Object.cpp:287
std::vector< Attribute > itsAttr
The object attributes.
Definition Object.h:210
virtual void parse(Statement &)
Parse the object.
Definition Object.cpp:82
virtual bool isShared() const
Shared flag.
Definition Object.cpp:245
void apply(const ObjectFunction &)
Apply a function to all objects.
Definition OpalData.cpp:381
Object * find(const std::string &name)
Find entry.
Definition OpalData.cpp:477
static OpalData * getInstance()
Definition OpalData.cpp:193
virtual void run() const
Read current stream.
Replace all references to named element by a new version.
Definition Replacer.h:31
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 double getLength() const
Return sequence length.
Definition Sequence.cpp:142
TBeamline< SequenceMember > TLine
The type of a sequence line.
Definition Sequence.h:40
virtual void print(std::ostream &) const
Print sequence.
Definition Sequence.cpp:200
std::string itsRefPoint
Definition Sequence.h:124
ReferenceType itsCode
Definition Sequence.h:121
virtual Object * makeTemplate(const std::string &, TokenStream &, Statement &)
Make a sequence template.
Definition Sequence.cpp:177
void insertDrifts(TLine &line)
Definition Sequence.cpp:336
Sequence()
Exemplar constructor.
Definition Sequence.cpp:52
virtual double getExit(ReferenceType) const
Return the arc length from origin to exit.
Definition Sequence.cpp:154
virtual double getEntrance(ReferenceType) const
Return the arc length from origin to entrance.
Definition Sequence.cpp:144
virtual void update()
Update the embedded OPALX beam line.
Definition Sequence.cpp:248
TLine::iterator findNamedPosition(TLine &, const std::string &) const
Definition Sequence.cpp:116
virtual TLine * fetchLine() const
Return the embedded OPALX beam line.
Definition Sequence.cpp:253
virtual Sequence * clone(const std::string &name)
Make clone.
Definition Sequence.cpp:93
void storeLine(TLine &line)
Store sequence line.
Definition Sequence.cpp:255
virtual void replace(Object *oldObject, Object *newObject)
Replace references to elements.
Definition Sequence.cpp:238
virtual Sequence * copy(const std::string &name)
Make copy of the sequence line.
Definition Sequence.cpp:95
void addEndMarkers(TLine &line) const
Definition Sequence.cpp:283
virtual void parse(Statement &)
Parse sequence.
Definition Sequence.cpp:190
ReferenceType getReference() const
Return the reference type flag.
Definition Sequence.cpp:164
virtual ~Sequence()
Definition Sequence.cpp:91
friend class SequenceTemplate
Definition Sequence.h:36
double findDriftLength(TLine::iterator drift) const
Definition Sequence.cpp:295
static void updateList(Sequence *, TLine *)
Definition Sequence.cpp:350
Interface for statements.
Definition Statement.h:37
Abstract interface for a stream of input tokens.
Definition TokenStream.h:30
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.
Clear Reference.
Definition OpalData.h:136