OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
IndexMap.cpp
Go to the documentation of this file.
1 //
2 // Class IndexMap
3 //
4 // This class stores and prints the sequence of elements that the referenc particle passes.
5 // Each time the reference particle enters or leaves an element an entry is added to the map.
6 // With help of this map one can determine which element can be found at a given position.
7 //
8 // Copyright (c) 2016, Christof Metzger-Kraus, Helmholtz-Zentrum Berlin, Germany
9 // 2017 - 2020 Christof Metzger-Kraus
10 //
11 // All rights reserved
12 //
13 // This file is part of OPAL.
14 //
15 // OPAL is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
22 //
23 #include <map>
24 #include <limits>
25 #include <iostream>
26 #include <fstream>
27 #include <tuple>
28 
29 #include "Algorithms/IndexMap.h"
31 #include "AbsBeamline/Multipole.h"
32 #include "AbsBeamline/Bend2D.h"
33 #include "Physics/Physics.h"
35 #include "Utilities/Util.h"
36 
37 extern Inform *gmsg;
38 
39 const double IndexMap::oneMinusEpsilon_m = 1.0 - std::numeric_limits<double>::epsilon();
40 namespace {
41  void insertFlags(std::vector<double> &flags, std::shared_ptr<Component> element);
42 }
43 
45  mapRange2Element_m(),
46  mapElement2Range_m(),
47  totalPathLength_m(0.0)
48 { }
49 
50 void IndexMap::print(std::ostream &out) const {
51  if (mapRange2Element_m.empty()) return;
52 
53  out << "* Size of map " << mapRange2Element_m.size() << " sections " << std::endl;
54  out << std::fixed << std::setprecision(6);
55  auto mapIti = mapRange2Element_m.begin();
56  auto mapItf = mapRange2Element_m.end();
57 
58  double totalLength = (*mapRange2Element_m.rbegin()).first.end;
59  unsigned int numDigits = std::floor(std::max(0.0, log(totalLength) / log(10.0))) + 1;
60 
61  for (; mapIti != mapItf; mapIti++) {
62  const key_t key = (*mapIti).first;
63  const value_t val = (*mapIti).second;
64  out << "* Key: ("
65  << std::setw(numDigits + 7) << std::right << key.begin
66  << " - "
67  << std::setw(numDigits + 7) << std::right << key.end
68  << ") number of overlapping elements " << val.size() << "\n";
69 
70  for (auto element: val) {
71  out << "* " << std::setw(25 + 2 * numDigits) << " " << element->getName() << "\n";
72  }
73  }
74 }
75 
77  const double lowerLimit = s - ds;//(ds < s? s - ds: 0);
78  const double upperLimit = std::min(totalPathLength_m, s + ds);
79  value_t elementSet;
80 
81  map_t::reverse_iterator rit = mapRange2Element_m.rbegin();
82  if (rit != mapRange2Element_m.rend() && lowerLimit > (*rit).first.end) {
83  throw OutOfBounds("IndexMap::query", "out of bounds");
84  }
85 
88 
89  for (; it != end; ++ it) {
90  const double low = (*it).first.begin;
91  const double high = (*it).first.end;
92 
93  if (lowerLimit < high && upperLimit >= low) break;
94  }
95 
96  if (it == end) return elementSet;
97 
98  map_t::iterator last = std::next(it);
99  for (; last != end; ++ last) {
100  const double low = (*last).first.begin;
101 
102  if (upperLimit < low) break;
103  }
104 
105  for (; it != last; ++ it) {
106  const value_t &a = (*it).second;
107  elementSet.insert(a.cbegin(), a.cend());
108  }
109 
110  return elementSet;
111 }
112 
113 void IndexMap::add(key_t::first_type initialS, key_t::second_type finalS, const value_t &val) {
114  if (initialS > finalS) {
115  std::swap(initialS, finalS);
116  }
117  key_t key{initialS, finalS * oneMinusEpsilon_m};
118 
119  mapRange2Element_m.insert(std::pair<key_t, value_t>(key, val));
120  totalPathLength_m = (*mapRange2Element_m.rbegin()).first.end;
121 
122  value_t::iterator setIt = val.begin();
123  const value_t::iterator setEnd = val.end();
124 
125  for (; setIt != setEnd; ++ setIt) {
126  if (mapElement2Range_m.find(*setIt) == mapElement2Range_m.end()) {
127  mapElement2Range_m.insert(std::make_pair(*setIt, key));
128  } else {
129  auto itpair = mapElement2Range_m.equal_range(*setIt);
130 
131  bool extendedExisting = false;
132  for (auto it = itpair.first; it != itpair.second; ++ it) {
133  key_t &currentRange = it->second;
134 
135  if (almostEqual(key.begin, currentRange.end / oneMinusEpsilon_m)) {
136  currentRange.end = key.end;
137  extendedExisting = true;
138  break;
139  }
140  }
141  if (!extendedExisting) {
142  mapElement2Range_m.insert(std::make_pair(*setIt, key));
143  }
144  }
145  }
146 }
147 
148 void IndexMap::tidyUp(double zstop) {
149  map_t::reverse_iterator rit = mapRange2Element_m.rbegin();
150 
151  if (rit != mapRange2Element_m.rend() &&
152  (*rit).second.empty() &&
153  zstop > (*rit).first.begin) {
154 
155  key_t key{(*rit).first.begin, zstop};
156  value_t val;
157 
158  mapRange2Element_m.erase(std::next(rit).base());
159  mapRange2Element_m.insert(std::pair<key_t, value_t>(key, val));
160  }
161 }
162 
163 enum elements {
164  DIPOLE = 0,
175 };
176 
177 void IndexMap::saveSDDS(double initialPathLength) const {
178  if (mapRange2Element_m.empty()) return;
179 
180  std::vector<std::tuple<double, std::vector<double>, std::string> > sectors;
181 
182  // add for each sector four rows:
183  // (s_i, 0)
184  // (s_i, 1)
185  // (s_f, 1)
186  // (s_f, 0)
187  // to the file, where
188  // s_i is the start of the range and
189  // s_f is the end of the range.
190  auto mapIti = mapRange2Element_m.begin();
191  auto mapItf = mapRange2Element_m.end();
192  for (; mapIti != mapItf; mapIti++) {
193  const auto &sectorElements = (*mapIti).second;
194  if (sectorElements.empty())
195  continue;
196 
197  const auto &sectorRange = (*mapIti).first;
198 
199  double sectorBegin = sectorRange.begin;
200  double sectorEnd = sectorRange.end;
201 
202  std::vector<std::tuple<double, std::vector<double>, std::string> > currentSector(4);
203  std::get<0>(currentSector[0]) = sectorBegin;
204  std::get<0>(currentSector[1]) = sectorBegin;
205  std::get<0>(currentSector[2]) = sectorEnd;
206  std::get<0>(currentSector[3]) = sectorEnd;
207 
208  for (unsigned short i = 0; i < 4; ++ i) {
209  auto &flags = std::get<1>(currentSector[i]);
210  flags.resize(SIZE, 0);
211  }
212 
213  for (auto element: sectorElements) {
214  auto elementPassages = mapElement2Range_m.equal_range(element);
215  auto passage = elementPassages.first;
216  auto end = elementPassages.second;
217  for (; passage != end; ++ passage) {
218  const auto &elementRange = (*passage).second;
219  double elementBegin = elementRange.begin;
220  double elementEnd = elementRange.end;
221 
222  if (elementBegin <= sectorBegin &&
223  elementEnd >= sectorEnd) {
224  break;
225  }
226  }
227 
228  const auto &elementRange = (*passage).second;
229  if (elementRange.begin < sectorBegin) {
230  ::insertFlags(std::get<1>(currentSector[0]), element);
231  std::get<2>(currentSector[0]) += element->getName() + ", ";
232  }
233 
234  ::insertFlags(std::get<1>(currentSector[1]), element);
235  std::get<2>(currentSector[1]) += element->getName() + ", ";
236 
237  ::insertFlags(std::get<1>(currentSector[2]), element);
238  std::get<2>(currentSector[2]) += element->getName() + ", ";
239 
240  if (elementRange.end > sectorEnd) {
241  ::insertFlags(std::get<1>(currentSector[3]), element);
242  std::get<2>(currentSector[3]) += element->getName() + ", ";
243  }
244  }
245 
246  for (unsigned short i = 0; i < 4; ++ i) {
247  sectors.push_back(currentSector[i]);
248  }
249  }
250 
251  // make the entries of the rf cavities a zigzag line
252  const unsigned int numEntries = sectors.size();
253  auto it = mapElement2Range_m.begin();
254  auto end = mapElement2Range_m.end();
255  for (; it != end; ++ it) {
256  auto element = (*it).first;
257  auto name = element->getName();
258  auto type = element->getType();
259  if (type != ElementType::RFCAVITY &&
261  continue;
262  }
263 
264  auto range = (*it).second;
265 
266  unsigned int i = 0;
267  for (; i < numEntries; ++ i) {
268  if (std::get<0>(sectors[i]) >= range.begin) {
269  break;
270  }
271  }
272 
273  if (i == numEntries) continue;
274 
275  unsigned int j = ++ i;
276  while (std::get<0>(sectors[j]) < range.end) {
277  ++ j;
278  }
279 
280  double length = range.end - range.begin;
281  for (; i <= j; ++ i) {
282  double pos = std::get<0>(sectors[i]);
283  auto &items = std::get<1>(sectors[i]);
284 
285  items[RFCAVITY] = 1.0 - 2 * (pos - range.begin) / length;
286  }
287  }
288 
289  // add row if range of first sector starts after initialPathLength
290  if (!sectors.empty() &&
291  std::get<0>(sectors[0]) > initialPathLength) {
292  auto tmp = sectors;
293  sectors = std::vector<std::tuple<double, std::vector<double>, std::string> >(1);
294  std::get<0>(sectors[0]) = initialPathLength;
295  std::get<1>(sectors[0]).resize(SIZE, 0.0);
296 
297  sectors.insert(sectors.end(), tmp.begin(), tmp.end());
298  }
299 
300  std::string fileName = Util::combineFilePath({
302  OpalData::getInstance()->getInputBasename() + "_ElementPositions.sdds"
303  });
304  ElementPositionWriter writer(fileName);
305 
306  for (auto sector: sectors) {
307  std::string names = std::get<2>(sector);
308  if (!names.empty()) {
309  names = names.substr(0, names.length() - 2);
310  }
311  names = "\"" + names + "\"";
312  writer.addRow(std::get<0>(sector),
313  std::get<1>(sector),
314  names);
315  }
316 }
317 
318 namespace {
319  void insertFlags(std::vector<double> &flags, std::shared_ptr<Component> element) {
320  switch (element->getType()) {
321  case ElementType::RBEND:
322  case ElementType::SBEND:
323  {
324  const Bend2D* bend = static_cast<const Bend2D*>(element.get());
325  if (bend->getRotationAboutZ() > 0.5 * Physics::pi &&
326  bend->getRotationAboutZ() < 1.5 * Physics::pi) {
327  flags[DIPOLE] = -1;
328  } else {
329  flags[DIPOLE] = 1;
330  }
331  }
332  break;
334  {
335  const Multipole* mult = static_cast<const Multipole*>(element.get());
336  switch(mult->getMaxNormalComponentIndex()) {
337  case 1:
338  flags[DIPOLE] = (mult->isFocusing(0)? 1: -1);
339  break;
340  case 2:
341  flags[QUADRUPOLE] = (mult->isFocusing(1)? 1: -1);
342  break;
343  case 3:
344  flags[SEXTUPOLE] = (mult->isFocusing(2)? 1: -1);
345  break;
346  case 4:
347  flags[OCTUPOLE] = (mult->isFocusing(3)? 1: -1);
348  break;
349  case 5:
350  flags[DECAPOLE] = (mult->isFocusing(4)? 1: -1);
351  break;
352  default:
353  flags[MULTIPOLE] = 1;
354  }
355  }
356  break;
358  flags[SOLENOID] = 1;
359  break;
362  flags[RFCAVITY] = 1;
363  break;
365  flags[MONITOR] = 1;
366  break;
367  default:
368  flags[OTHER] = 1;
369  break;
370  }
371 
372  }
373 }
374 
376  double position) const {
377  double minDistance = std::numeric_limits<double>::max();
378  key_t range{0.0, 0.0};
379  const std::pair<invertedMap_t::const_iterator, invertedMap_t::const_iterator> its = mapElement2Range_m.equal_range(element);
380  if (std::distance(its.first, its.second) == 0)
381  throw OpalException("IndexMap::getRange()",
382  "Element \"" + element->getName() + "\" not registered");
383 
384  for (invertedMap_t::const_iterator it = its.first; it != its.second; ++ it) {
385  double distance = std::min(std::abs((*it).second.begin - position),
386  std::abs((*it).second.end - position));
387  if (distance < minDistance) {
388  minDistance = distance;
389  range = (*it).second;
390  }
391  }
392 
393  return range;
394 }
395 
397  map_t::const_iterator it = mapRange2Element_m.begin();
398  const map_t::const_iterator end = mapRange2Element_m.end();
399  value_t touchingElements;
400 
401  for (; it != end; ++ it) {
402  if (almostEqual(it->first.begin, range.begin) ||
403  almostEqual(it->first.end, range.end))
404  touchingElements.insert((it->second).begin(), (it->second).end());
405  }
406 
407  return touchingElements;
408 }
409 
410 bool IndexMap::almostEqual(double x, double y) {
411  return (std::abs(x - y) < std::numeric_limits<double>::epsilon() * std::abs(x + y) * 2 ||
413 }
static OpalData * getInstance()
Definition: OpalData.cpp:196
void print(std::ostream &) const
Definition: IndexMap.cpp:50
map_t mapRange2Element_m
Definition: IndexMap.h:96
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the so that any problems introduced by others will not reflect on the original authors reputations any free program is threatened constantly by software patents We wish to avoid the danger that redistributors of a free program will individually obtain patent in effect making the program proprietary To prevent we have made it clear that any patent must be licensed for everyone s free use or not licensed at all The precise terms and conditions for distribution and modification follow GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR DISTRIBUTION AND MODIFICATION This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License The refers to any such program or and a work based on the Program means either the Program or any derivative work under copyright a work containing the Program or a portion of it
Definition: LICENSE:43
value_t getTouchingElements(const key_t &range) const
Definition: IndexMap.cpp:396
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
bool isFocusing(unsigned int component) const
Definition: Multipole.cpp:357
std::set< std::shared_ptr< Component > > value_t
Definition: IndexMap.h:47
Definition: Bend2D.h:51
Interface for general multipole.
Definition: Multipole.h:47
constexpr double pi
The value of .
Definition: Physics.h:30
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
double first_type
Definition: IndexMap.h:41
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
key_t getRange(const IndexMap::value_t::value_type &element, double position) const
Definition: IndexMap.cpp:375
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
std::string::iterator iterator
Definition: MSLang.h:15
value_t query(key_t::first_type s, key_t::second_type ds)
Definition: IndexMap.cpp:76
alter the names
Definition: LICENSE:330
double totalPathLength_m
Definition: IndexMap.h:99
void tidyUp(double zstop)
Definition: IndexMap.cpp:148
The base class for all OPAL exceptions.
Definition: OpalException.h:28
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Definition: OpalData.cpp:666
elements
Definition: IndexMap.cpp:163
Definition: Inform.h:42
invertedMap_t mapElement2Range_m
Definition: IndexMap.h:97
second_type end
Definition: IndexMap.h:44
static const double oneMinusEpsilon_m
Definition: IndexMap.h:102
double getRotationAboutZ() const
Definition: ElementBase.h:574
void saveSDDS(double startS) const
Definition: IndexMap.cpp:177
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
const std::string name
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition: Util.cpp:197
first_type begin
Definition: IndexMap.h:43
T * value_type(const SliceIterator< T > &)
std::string getInputBasename()
get input file name without extension
Definition: OpalData.cpp:674
IndexMap()
Definition: IndexMap.cpp:44
static bool almostEqual(double, double)
Definition: IndexMap.cpp:410
size_t getMaxNormalComponentIndex() const
Definition: Multipole.h:157
double second_type
Definition: IndexMap.h:42
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
SDDS1 &description type
Definition: test.stat:4
void add(key_t::first_type initialStep, key_t::second_type finalStep, const value_t &val)
Definition: IndexMap.cpp:113
Inform * gmsg
Definition: Main.cpp:70
end
Definition: multipole_t.tex:9