OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
IndexMap.cpp
Go to the documentation of this file.
1 #include <map>
2 #include <limits>
3 #include <iostream>
4 #include <fstream>
5 #include <tuple>
6 
7 #include "Algorithms/IndexMap.h"
10 #include "AbsBeamline/Bend2D.h"
11 #include "Physics/Physics.h"
13 
14 extern Inform *gmsg;
15 
16 const double IndexMap::oneMinusEpsilon_m = 1.0 - std::numeric_limits<double>::epsilon();
17 namespace {
18  void insertFlags(std::vector<double> &flags, std::shared_ptr<Component> element);
19 }
20 
22  mapRange2Element_m(),
23  mapElement2Range_m(),
24  totalPathLength_m(0.0)
25 { }
26 
27 void IndexMap::print(std::ostream &out) const {
28  if (mapRange2Element_m.size() == 0) return;
29 
30  out << "Size of map " << mapRange2Element_m.size() << " sections " << std::endl;
31  out << std::fixed << std::setprecision(6);
32  auto mapIti = mapRange2Element_m.begin();
33  auto mapItf = mapRange2Element_m.end();
34 
35  double totalLength = (*mapRange2Element_m.rbegin()).first.second;
36  unsigned int numDigits = std::floor(std::max(0.0, log(totalLength) / log(10.0))) + 1;
37 
38  for (; mapIti != mapItf; mapIti++) {
39  const auto key = (*mapIti).first;
40  const auto val = (*mapIti).second;
41  out << "Key: ("
42  << std::setw(numDigits + 7) << std::right << key.first
43  << " - "
44  << std::setw(numDigits + 7) << std::right << key.second
45  << ") number of overlapping elements " << val.size() << "\n";
46 
47  for (auto element: val) {
48  out << std::setw(25 + 2 * numDigits) << " " << element->getName() << "\n";
49  }
50  }
51 }
52 
53 IndexMap::value_t IndexMap::query(key_t::first_type s, key_t::second_type ds) {
54  const double lowerLimit = s - ds;//(ds < s? s - ds: 0);
55  const double upperLimit = std::min(totalPathLength_m, s + ds);
56  value_t elementSet;
57 
58  map_t::reverse_iterator rit = mapRange2Element_m.rbegin();
59  if (rit != mapRange2Element_m.rend() && lowerLimit > (*rit).first.second) {
60  throw OutOfBounds("IndexMap::query", "out of bounds");
61  }
62 
64  const map_t::iterator end = mapRange2Element_m.end();
65 
66  for (; it != end; ++ it) {
67  const double low = (*it).first.first;
68  const double high = (*it).first.second;
69 
70  if (lowerLimit < high && upperLimit >= low) break;
71  }
72 
73  if (it == end) return elementSet;
74 
75  map_t::iterator last = std::next(it);
76  for (; last != end; ++ last) {
77  const double low = (*last).first.first;
78 
79  if (upperLimit < low) break;
80  }
81 
82  for (; it != last; ++ it) {
83  const value_t &a = (*it).second;
84  elementSet.insert(a.cbegin(), a.cend());
85  }
86 
87  return elementSet;
88 }
89 
90 void IndexMap::add(key_t::first_type initialS, key_t::second_type finalS, const value_t &val) {
91  if (initialS > finalS) {
92  std::swap(initialS, finalS);
93  }
94  key_t key(initialS, finalS * oneMinusEpsilon_m);
95 
96  mapRange2Element_m.insert(std::pair<key_t, value_t>(key, val));
97  totalPathLength_m = (*mapRange2Element_m.rbegin()).first.second;
98 
99  value_t::iterator setIt = val.begin();
100  const value_t::iterator setEnd = val.end();
101 
102  for (; setIt != setEnd; ++ setIt) {
103  if (mapElement2Range_m.find(*setIt) == mapElement2Range_m.end()) {
104  mapElement2Range_m.insert(std::make_pair(*setIt, key));
105  } else {
106  auto itpair = mapElement2Range_m.equal_range(*setIt);
107 
108  bool extendedExisting = false;
109  for (auto it = itpair.first; it != itpair.second; ++ it) {
110  key_t &currentRange = it->second;
111 
112  if (almostEqual(key.first, currentRange.second / oneMinusEpsilon_m)) {
113  currentRange.second = key.second;
114  extendedExisting = true;
115  break;
116  }
117  }
118  if (!extendedExisting) {
119  mapElement2Range_m.insert(std::make_pair(*setIt, key));
120  }
121  }
122  }
123 }
124 
125 void IndexMap::tidyUp(double zstop) {
126  map_t::reverse_iterator rit = mapRange2Element_m.rbegin();
127 
128  if (rit != mapRange2Element_m.rend() &&
129  (*rit).second.size() == 0 &&
130  zstop > (*rit).first.first &&
131  zstop < (*rit).first.second) {
132 
133  key_t key((*rit).first.first, zstop);
134  value_t val;
135 
136  mapRange2Element_m.erase(std::next(rit).base());
137  mapRange2Element_m.insert(std::pair<key_t, value_t>(key, val));
138  }
139 }
140 
141 enum elements {
142  DIPOLE = 0,
153 };
154 
155 void IndexMap::saveSDDS(double initialPathLength) const {
156  if (mapRange2Element_m.size() == 0) return;
157 
158  std::vector<std::tuple<double, std::vector<double>, std::string> > sectors;
159 
160  // add for each sector four rows:
161  // (s_i, 0)
162  // (s_i, 1)
163  // (s_f, 1)
164  // (s_f, 0)
165  // to the file, where
166  // s_i is the start of the range and
167  // s_f is the end of the range.
168  auto mapIti = mapRange2Element_m.begin();
169  auto mapItf = mapRange2Element_m.end();
170  for (; mapIti != mapItf; mapIti++) {
171  const auto &sectorElements = (*mapIti).second;
172  if (sectorElements.size() == 0)
173  continue;
174 
175  const auto &sectorRange = (*mapIti).first;
176 
177  double sectorBegin = sectorRange.first;
178  double sectorEnd = sectorRange.second;
179 
180  std::vector<std::tuple<double, std::vector<double>, std::string> > currentSector(4);
181  std::get<0>(currentSector[0]) = sectorBegin;
182  std::get<0>(currentSector[1]) = sectorBegin;
183  std::get<0>(currentSector[2]) = sectorEnd;
184  std::get<0>(currentSector[3]) = sectorEnd;
185 
186  for (unsigned short i = 0; i < 4; ++ i) {
187  auto &flags = std::get<1>(currentSector[i]);
188  flags.resize(SIZE, 0);
189  }
190 
191  for (auto element: sectorElements) {
192  auto elementPassages = mapElement2Range_m.equal_range(element);
193  auto passage = elementPassages.first;
194  auto end = elementPassages.second;
195  for (; passage != end; ++ passage) {
196  const auto &elementRange = (*passage).second;
197  double elementBegin = elementRange.first;
198  double elementEnd = elementRange.second;
199 
200  if (elementBegin <= sectorBegin &&
201  elementEnd >= sectorEnd) {
202  break;
203  }
204  }
205 
206  const auto &elementRange = (*passage).second;
207  if (elementRange.first < sectorBegin) {
208  ::insertFlags(std::get<1>(currentSector[0]), element);
209  std::get<2>(currentSector[0]) += element->getName() + ", ";
210  }
211 
212  ::insertFlags(std::get<1>(currentSector[1]), element);
213  std::get<2>(currentSector[1]) += element->getName() + ", ";
214 
215  ::insertFlags(std::get<1>(currentSector[2]), element);
216  std::get<2>(currentSector[2]) += element->getName() + ", ";
217 
218  if (elementRange.second > sectorEnd) {
219  ::insertFlags(std::get<1>(currentSector[3]), element);
220  std::get<2>(currentSector[3]) += element->getName() + ", ";
221  }
222  }
223 
224  for (unsigned short i = 0; i < 4; ++ i) {
225  sectors.push_back(currentSector[i]);
226  }
227  }
228 
229  // make the entries of the rf cavities a zigzag line
230  const unsigned int numEntries = sectors.size();
231  auto it = mapElement2Range_m.begin();
232  auto end = mapElement2Range_m.end();
233  for (; it != end; ++ it) {
234  auto element = (*it).first;
235  auto name = element->getName();
236  auto type = element->getType();
237  if (type != ElementBase::RFCAVITY &&
239  continue;
240  }
241 
242  auto range = (*it).second;
243 
244  unsigned int i = 0;
245  for (; i < numEntries; ++ i) {
246  if (std::get<0>(sectors[i]) >= range.first) {
247  break;
248  }
249  }
250 
251  if (i == numEntries) continue;
252 
253  unsigned int j = ++ i;
254  while (std::get<0>(sectors[j]) < range.second) {
255  ++ j;
256  }
257 
258  double length = range.second - range.first;
259  for (; i <= j; ++ i) {
260  double pos = std::get<0>(sectors[i]);
261  auto &items = std::get<1>(sectors[i]);
262 
263  items[RFCAVITY] = 1.0 - 2 * (pos - range.first) / length;
264  }
265  }
266 
267  // add row if range of first sector starts after initialPathLength
268  if (sectors.size() > 0 &&
269  std::get<0>(sectors[0]) > initialPathLength) {
270  auto tmp = sectors;
271  sectors = std::vector<std::tuple<double, std::vector<double>, std::string> >(1);
272  std::get<0>(sectors[0]) = initialPathLength;
273  std::get<1>(sectors[0]).resize(SIZE, 0.0);
274 
275  sectors.insert(sectors.end(), tmp.begin(), tmp.end());
276  }
277 
278  std::string fileName("data/" + OpalData::getInstance()->getInputBasename() + "_ElementPositions.sdds");
279  ElementPositionWriter writer(fileName);
280 
281  for (auto sector: sectors) {
282  std::string names = std::get<2>(sector);
283  if (names != "") {
284  names = names.substr(0, names.length() - 2);
285  }
286  names = "\"" + names + "\"";
287  writer.addRow(std::get<0>(sector),
288  std::get<1>(sector),
289  names);
290  }
291 }
292 
293 namespace {
294  void insertFlags(std::vector<double> &flags, std::shared_ptr<Component> element) {
295  switch (element->getType()) {
296  case ElementBase::RBEND:
297  case ElementBase::SBEND:
298  {
299  const Bend2D* bend = static_cast<const Bend2D*>(element.get());
300  if (bend->getRotationAboutZ() > 0.5 * Physics::pi &&
301  bend->getRotationAboutZ() < 1.5 * Physics::pi) {
302  flags[DIPOLE] = -1;
303  } else {
304  flags[DIPOLE] = 1;
305  }
306  }
307  break;
309  {
310  const Multipole* mult = static_cast<const Multipole*>(element.get());
311  switch(mult->getMaxNormalComponentIndex()) {
312  case 1:
313  flags[DIPOLE] = (mult->isFocusing(0)? 1: -1);
314  break;
315  case 2:
316  flags[QUADRUPOLE] = (mult->isFocusing(1)? 1: -1);
317  break;
318  case 3:
319  flags[SEXTUPOLE] = (mult->isFocusing(2)? 1: -1);
320  break;
321  case 4:
322  flags[OCTUPOLE] = (mult->isFocusing(3)? 1: -1);
323  break;
324  case 5:
325  flags[DECAPOLE] = (mult->isFocusing(4)? 1: -1);
326  break;
327  default:
328  flags[MULTIPOLE] = 1;
329  }
330  }
331  break;
333  flags[SOLENOID] = 1;
334  break;
337  flags[RFCAVITY] = 1;
338  break;
340  flags[MONITOR] = 1;
341  break;
342  default:
343  flags[OTHER] = 1;
344  break;
345  }
346 
347  }
348 }
349 
350 std::pair<double, double> IndexMap::getRange(const IndexMap::value_t::value_type &element,
351  double position) const {
352  double minDistance = std::numeric_limits<double>::max();
353  std::pair<double, double> range(0.0, 0.0);
354  const std::pair<invertedMap_t::const_iterator, invertedMap_t::const_iterator> its = mapElement2Range_m.equal_range(element);
355  if (std::distance(its.first, its.second) == 0)
356  throw OpalException("IndexMap::getRange()",
357  "Element \"" + element->getName() + "\" not registered");
358 
359  for (invertedMap_t::const_iterator it = its.first; it != its.second; ++ it) {
360  double distance = std::min(std::abs((*it).second.first - position),
361  std::abs((*it).second.second - position));
362  if (distance < minDistance) {
363  minDistance = distance;
364  range = (*it).second;
365  }
366  }
367 
368  return range;
369 }
370 
371 IndexMap::value_t IndexMap::getTouchingElements(const std::pair<double, double> &range) {
372  map_t::iterator it = mapRange2Element_m.begin();
373  const map_t::iterator end = mapRange2Element_m.end();
374  IndexMap::value_t touchingElements;
375 
376  for (; it != end; ++ it) {
377  if (almostEqual(it->first.first, range.second) ||
378  almostEqual(it->first.second, range.first))
379  touchingElements.insert((it->second).begin(), (it->second).end());
380  }
381 
382  return touchingElements;
383 }
384 
385 bool IndexMap::almostEqual(double x, double y) {
386  return (std::abs(x - y) < std::numeric_limits<double>::epsilon() * std::abs(x + y) * 2 ||
388 }
std::pair< double, double > key_t
Definition: IndexMap.h:17
elements
Definition: IndexMap.cpp:141
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
value_t query(key_t::first_type s, key_t::second_type ds)
Definition: IndexMap.cpp:53
double totalPathLength_m
Definition: IndexMap.h:71
bool isFocusing(unsigned int component) const
Definition: Multipole.cpp:427
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
The base class for all OPAL exceptions.
Definition: OpalException.h:28
Inform * gmsg
Definition: Main.cpp:21
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
Interface for general multipole.
Definition: Multipole.h:46
static OpalData * getInstance()
Definition: OpalData.cpp:209
void add(key_t::first_type initialStep, key_t::second_type finalStep, const value_t &val)
Definition: IndexMap.cpp:90
constexpr double pi
The value of .
Definition: Physics.h:31
void saveSDDS(double startS) const
Definition: IndexMap.cpp:155
Definition: Bend2D.h:51
IndexMap()
Definition: IndexMap.cpp:21
T * value_type(const SliceIterator< T > &)
void print(std::ostream &) const
Definition: IndexMap.cpp:27
void addRow(double spos, const std::vector< double > &row, const std::string &elements)
map_t mapRange2Element_m
Definition: IndexMap.h:68
std::pair< double, double > getRange(const IndexMap::value_t::value_type &element, double position) const
Definition: IndexMap.cpp:350
double getRotationAboutZ() const
Definition: ElementBase.h:700
const std::string name
static bool almostEqual(double, double)
Definition: IndexMap.cpp:385
std::string::iterator iterator
Definition: MSLang.h:16
invertedMap_t mapElement2Range_m
Definition: IndexMap.h:69
static const double oneMinusEpsilon_m
Definition: IndexMap.h:74
Definition: Inform.h:41
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:95
size_t getMaxNormalComponentIndex() const
Definition: Multipole.h:160
void tidyUp(double zstop)
Definition: IndexMap.cpp:125
IndexMap::value_t getTouchingElements(const std::pair< double, double > &range)
Definition: IndexMap.cpp:371
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:816
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
std::set< std::shared_ptr< Component > > value_t
Definition: IndexMap.h:18