OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
OrbitThreader.cpp
Go to the documentation of this file.
3 
4 #include "AbsBeamline/RFCavity.h"
5 #include "AbsBeamline/BendBase.h"
8 
10 #include "BasicActions/Option.h"
11 #include "Utilities/Options.h"
12 
14 #include "Utilities/Util.h"
15 
16 #include <boost/filesystem.hpp>
17 
18 #include <iostream>
19 #include <limits>
20 
21 #define HITMATERIAL 0x80000000
22 #define EOL 0x40000000
23 #define EVERYTHINGFINE 0x00000000
24 extern Inform *gmsg;
25 
27  const Vector_t &r,
28  const Vector_t &p,
29  double s,
30  double maxDiffZBunch,
31  double t,
32  double dt,
33  size_t maxIntegSteps,
34  double zstop,
35  OpalBeamline &bl) :
36  r_m(r),
37  p_m(p),
38  pathLength_m(s),
39  time_m(t),
40  dt_m(dt),
41  maxIntegSteps_m(maxIntegSteps),
42  zstop_m(zstop),
43  itsOpalBeamline_m(bl),
44  errorFlag_m(0),
45  integrator_m(ref),
46  reference_m(ref)
47 {
48  auto opal = OpalData::getInstance();
49  if (Ippl::myNode() == 0 && !opal->isOptimizerRun()) {
50  std::string fileName = "data/" + OpalData::getInstance()->getInputBasename() + "_DesignPath.dat";
51  if (OpalData::getInstance()->getOpenMode() == OpalData::OPENMODE::WRITE ||
52  !boost::filesystem::exists(fileName)) {
53  logger_m.open(fileName);
54  logger_m << "#"
55  << std::setw(17) << "1 - s"
56  << std::setw(18) << "2 - Rx"
57  << std::setw(18) << "3 - Ry"
58  << std::setw(18) << "4 - Rz"
59  << std::setw(18) << "5 - Px"
60  << std::setw(18) << "6 - Py"
61  << std::setw(18) << "7 - Pz"
62  << std::setw(18) << "8 - Efx"
63  << std::setw(18) << "9 - Efy"
64  << std::setw(18) << "10 - Efz"
65  << std::setw(18) << "11 - Bfx"
66  << std::setw(18) << "12 - Bfy"
67  << std::setw(18) << "13 - Bfz"
68  << std::setw(18) << "14 - Ekin"
69  << std::setw(18) << "15 - t"
70  << std::endl;
71  } else {
72  logger_m.open(fileName, std::ios_base::app);
73  }
74 
75  loggingFrequency_m = std::max(1.0, floor(1e-11 / std::abs(dt_m) + 0.5));
76  } else {
78  }
79 
80  distTrackBack_m = std::min(pathLength_m, std::max(0.0, maxDiffZBunch));
81 }
82 
84  double initialPathLength = pathLength_m;
85  double maxDistance = computeMaximalImplicitDrift();
86 
88  std::set<std::string> visitedElements;
89 
90  trackBack(2 * maxDistance);
91 
92  Vector_t nextR = r_m / (Physics::c * dt_m);
93  integrator_m.push(nextR, p_m, dt_m);
94  nextR *= Physics::c * dt_m;
95 
96  setDesignEnergy(allElements, visitedElements);
97 
98  auto elementSet = itsOpalBeamline_m.getElements(nextR);
100  do {
101  if (containsCavity(elementSet)) {
102  autophaseCavities(elementSet, visitedElements);
103  }
104 
105  double initialS = pathLength_m;
106  Vector_t initialR = r_m;
107  Vector_t initialP = p_m;
108  integrate(elementSet, maxIntegSteps_m, 2 * maxDistance);
109 
110  registerElement(elementSet, initialS, initialR, initialP);
111 
112  if (errorFlag_m == HITMATERIAL) {
113  // Shouldn't be reached because reference particle
114  // isn't stopped by collimators
115  pathLength_m += std::copysign(1.0, dt_m);
116  }
117 
118  imap_m.add(initialS, pathLength_m, elementSet);
119 
120  IndexMap::value_t::const_iterator it = elementSet.begin();
121  const IndexMap::value_t::const_iterator end = elementSet.end();
122  for (; it != end; ++ it) {
123  visitedElements.insert((*it)->getName());
124  }
125 
126  setDesignEnergy(allElements, visitedElements);
127 
128  if (errorFlag_m == EVERYTHINGFINE) {
129  nextR = r_m / (Physics::c * dt_m);
130  integrator_m.push(nextR, p_m, dt_m);
131  nextR *= Physics::c * dt_m;
132 
133  elementSet = itsOpalBeamline_m.getElements(nextR);
134  }
135  } while (errorFlag_m != HITMATERIAL &&
136  errorFlag_m != EOL);
137 
139  *gmsg << level1 << "\n" << imap_m << endl;
140  imap_m.saveSDDS(initialPathLength);
141 
143 }
144 
145 void OrbitThreader::integrate(const IndexMap::value_t &activeSet, size_t maxSteps, double maxDrift) {
146  static size_t step = 0;
148  const double oldPathLength = pathLength_m;
149  Vector_t nextR;
150  do {
152 
153  IndexMap::value_t::const_iterator it = activeSet.begin();
154  const IndexMap::value_t::const_iterator end = activeSet.end();
155  Vector_t oldR = r_m;
156 
157  r_m /= Physics::c * dt_m;
158  integrator_m.push(r_m, p_m, dt_m);
159  r_m *= Physics::c * dt_m;
160 
161  Vector_t Ef(0.0), Bf(0.0);
162  std::string names("\t");
163  for (; it != end; ++ it) {
166  Vector_t localE(0.0), localB(0.0);
167 
168  if ((*it)->applyToReferenceParticle(localR, localP, time_m + 0.5 * dt_m, localE, localB)) {
170  return;
171  }
172  names += (*it)->getName() + ", ";
173 
174  Ef += itsOpalBeamline_m.rotateFromLocalCS(*it, localE);
175  Bf += itsOpalBeamline_m.rotateFromLocalCS(*it, localB);
176  }
177 
178  if (pathLength_m > 0.0 &&
179  pathLength_m < zstop_m &&
180  step % loggingFrequency_m == 0 && Ippl::myNode() == 0 &&
181  !OpalData::getInstance()->isOptimizerRun()) {
182  logger_m << std::setw(18) << std::setprecision(8) << pathLength_m + std::copysign(euclidean_norm(r_m - oldR), dt_m)
183  << std::setw(18) << std::setprecision(8) << r_m(0)
184  << std::setw(18) << std::setprecision(8) << r_m(1)
185  << std::setw(18) << std::setprecision(8) << r_m(2)
186  << std::setw(18) << std::setprecision(8) << p_m(0)
187  << std::setw(18) << std::setprecision(8) << p_m(1)
188  << std::setw(18) << std::setprecision(8) << p_m(2)
189  << std::setw(18) << std::setprecision(8) << Ef(0)
190  << std::setw(18) << std::setprecision(8) << Ef(1)
191  << std::setw(18) << std::setprecision(8) << Ef(2)
192  << std::setw(18) << std::setprecision(8) << Bf(0)
193  << std::setw(18) << std::setprecision(8) << Bf(1)
194  << std::setw(18) << std::setprecision(8) << Bf(2)
195  << std::setw(18) << std::setprecision(8) << reference_m.getM() * (sqrt(dot(p_m, p_m) + 1) - 1) * 1e-6
196  << std::setw(18) << std::setprecision(8) << (time_m + 0.5 * dt_m) * 1e9
197  << names
198  << std::endl;
199  }
200 
201  r_m /= Physics::c * dt_m;
202  integrator_m.kick(r_m, p_m, Ef, Bf, dt_m);
203  integrator_m.push(r_m, p_m, dt_m);
204  r_m *= Physics::c * dt_m;
205 
206  pathLength_m += std::copysign(euclidean_norm(r_m - oldR), dt_m);
207  ++ step;
208  time_m += dt_m;
209 
210  nextR = r_m / (Physics::c * dt_m);
211  integrator_m.push(nextR, p_m, dt_m);
212  nextR *= Physics::c * dt_m;
213 
214  if ((activeSet.size() == 0 && std::abs(pathLength_m - oldPathLength) > maxDrift) ||
215  (activeSet.size() > 0 && dt_m * pathLength_m > dt_m * zstop_m) ||
216  (pathLength_m < 0.0 && dt_m < 0.0)) {
217  errorFlag_m = EOL;
218  return;
219  }
220 
221  } while (activeSet == itsOpalBeamline_m.getElements(nextR));
222 }
223 
225  IndexMap::value_t::const_iterator it = activeSet.begin();
226  const IndexMap::value_t::const_iterator end = activeSet.end();
227 
228  for (; it != end; ++ it) {
229  if ((*it)->getType() == ElementBase::TRAVELINGWAVE ||
230  (*it)->getType() == ElementBase::RFCAVITY) {
231  return true;
232  }
233  }
234 
235  return false;
236 }
237 
239  const std::set<std::string> &visitedElements) {
240  if (Options::autoPhase == 0) return;
241 
242  IndexMap::value_t::const_iterator it = activeSet.begin();
243  const IndexMap::value_t::const_iterator end = activeSet.end();
244 
245  for (; it != end; ++ it) {
246  if (((*it)->getType() == ElementBase::TRAVELINGWAVE ||
247  (*it)->getType() == ElementBase::RFCAVITY) &&
248  visitedElements.find((*it)->getName()) == visitedElements.end()) {
249 
252 
253  CavityAutophaser ap(reference_m, *it);
254  ap.getPhaseAtMaxEnergy(initialR,
255  initialP,
256  time_m,
257  dt_m);
258  }
259  }
260 }
261 
262 
264 {
265  IndexMap::value_t::const_iterator it = elementSet.begin();
266  const IndexMap::value_t::const_iterator end = elementSet.end();
267 
268  double designEnergy = 0.0;
269  for (; it != end; ++ it) {
270  if ((*it)->getType() == ElementBase::TRAVELINGWAVE ||
271  (*it)->getType() == ElementBase::RFCAVITY) {
272  const RFCavity *element = static_cast<const RFCavity *>((*it).get());
273  designEnergy = std::max(designEnergy, element->getDesignEnergy());
274  }
275  }
276 
277  return designEnergy;
278 }
279 
280 void OrbitThreader::trackBack(double maxDrift) {
281  dt_m *= -1;
282  double initialPathLength = pathLength_m;
283 
284  Vector_t nextR = r_m / (Physics::c * dt_m);
285  integrator_m.push(nextR, p_m, dt_m);
286  nextR *= Physics::c * dt_m;
287 
288  maxDrift = std::min(maxDrift, distTrackBack_m);
289  while (std::abs(initialPathLength - pathLength_m) < distTrackBack_m) {
290  auto elementSet = itsOpalBeamline_m.getElements(nextR);
291 
292  integrate(elementSet, 1000, maxDrift);
293 
294  nextR = r_m / (Physics::c * dt_m);
295  integrator_m.push(nextR, p_m, dt_m);
296  nextR *= Physics::c * dt_m;
297  }
298 
299  dt_m *= -1;
300 }
301 
303  double start,
304  const Vector_t &R,
305  const Vector_t &P) {
306 
307  IndexMap::value_t::const_iterator it = elementSet.begin();
308  const IndexMap::value_t::const_iterator end = elementSet.end();
309 
310  for (; it != end; ++ it) {
311  bool found = false;
312  std::string name = (*it)->getName();
313  auto prior = elementRegistry_m.equal_range(name);
314 
315  for (auto pit = prior.first; pit != prior.second; ++ pit) {
316  if (std::abs((*pit).second.endField_m - start) < 1e-10) {
317  found = true;
318  (*pit).second.endField_m = pathLength_m;
319  break;
320  }
321  }
322 
323  if (found) continue;
324 
325  Vector_t initialR = itsOpalBeamline_m.transformToLocalCS(*it, R);
326  Vector_t initialP = itsOpalBeamline_m.rotateToLocalCS(*it, P);
327  double elementEdge = start - initialR(2) * euclidean_norm(initialP) / initialP(2);
328 
329  elementPosition ep = {start, pathLength_m, elementEdge};
330  elementRegistry_m.insert(std::make_pair(name, ep));
331  }
332 }
333 
335  std::map<std::string, std::set<elementPosition, elementPositionComp> > tmpRegistry;
336 
337  for (auto it = elementRegistry_m.begin(); it != elementRegistry_m.end(); ++ it) {
338  const std::string &name = (*it).first;
339  elementPosition &ep = (*it).second;
340 
341  auto prior = tmpRegistry.find(name);
342  if (prior == tmpRegistry.end()) {
343  std::set<elementPosition, elementPositionComp> tmpSet;
344  tmpSet.insert(ep);
345  tmpRegistry.insert(std::make_pair(name, tmpSet));
346  continue;
347  }
348 
349  std::set<elementPosition, elementPositionComp> &set = (*prior).second;
350  set.insert(ep);
351  }
352 
354  FieldList::iterator it = allElements.begin();
355  const FieldList::iterator end = allElements.end();
356  for (; it != end; ++ it) {
357  std::string name = (*it).getElement()->getName();
358  auto trit = tmpRegistry.find(name);
359  if (trit == tmpRegistry.end()) continue;
360 
361  std::queue<std::pair<double, double> > range;
362  std::set<elementPosition, elementPositionComp> &set = (*trit).second;
363 
364  for (auto sit = set.begin(); sit != set.end(); ++ sit) {
365  range.push(std::make_pair((*sit).elementEdge_m, (*sit).endField_m));
366  }
367  (*it).getElement()->setActionRange(range);
368  }
369 }
370 
371 void OrbitThreader::setDesignEnergy(FieldList &allElements, const std::set<std::string> &visitedElements) {
372  double kineticEnergyeV = reference_m.getM() * (sqrt(dot(p_m, p_m) + 1.0) - 1.0);
373 
374  FieldList::iterator it = allElements.begin();
375  const FieldList::iterator end = allElements.end();
376  for (; it != end; ++ it) {
377  std::shared_ptr<Component> element = (*it).getElement();
378  if (visitedElements.find(element->getName()) == visitedElements.end() &&
379  !(element->getType() == ElementBase::RFCAVITY ||
380  element->getType() == ElementBase::TRAVELINGWAVE)) {
381 
382  element->setDesignEnergy(kineticEnergyeV);
383  }
384  }
385 }
386 
389  double maxDrift = 0.0;
390 
391  MarkerRep start("#S");
392  CoordinateSystemTrafo toEdge(r_m, getQuaternion(p_m, Vector_t(0, 0, 1)));
393  start.setElementLength(0.0);
394  start.setCSTrafoGlobal2Local(toEdge);
395  std::shared_ptr<Component> startPtr(static_cast<Marker*>(start.clone()));
396  allElements.push_front(ClassicField(startPtr, 0.0, 0.0));
397 
398  FieldList::iterator it = allElements.begin();
399  const FieldList::iterator end = allElements.end();
400 
401  for (; it != end; ++ it) {
402  auto element1 = it->getElement();
403  const auto &toEdge = element1->getCSTrafoGlobal2Local();
404  auto toEnd = element1->getEdgeToEnd() * toEdge;
405  Vector_t end1 = toEnd.transformFrom(Vector_t(0, 0, 0));
406  Vector_t directionEnd = toEnd.rotateFrom(Vector_t(0, 0, 1));
407  if (element1->getType() == ElementBase::RBEND ||
408  element1->getType() == ElementBase::SBEND ||
409  element1->getType() == ElementBase::RBEND3D ) {
410  auto toBegin = element1->getEdgeToBegin() * toEdge;
411 
412  BendBase *bend = static_cast<BendBase*>(element1.get());
413  double angleRelativeToFace = bend->getEntranceAngle() - bend->getBendAngle();
414  directionEnd = toBegin.rotateFrom(Vector_t(sin(angleRelativeToFace), 0, cos(angleRelativeToFace)));
415  }
416 
417  double minDistanceLocal = std::numeric_limits<double>::max();
418  FieldList::iterator it2 = allElements.begin();
419  for (; it2 != end; ++ it2) {
420  if (it == it2) continue;
421 
422  auto element2 = it2->getElement();
423  const auto &toEdge = element2->getCSTrafoGlobal2Local();
424  auto toBegin = element2->getEdgeToBegin() * toEdge;
425  auto toEnd = element2->getEdgeToEnd() * toEdge;
426  Vector_t begin2 = toBegin.transformFrom(Vector_t(0, 0, 0));
427  Vector_t end2 = toEnd.transformFrom(Vector_t(0, 0, 0));
428  Vector_t directionBegin = toBegin.rotateFrom(Vector_t(0, 0, 1));
429  if (element2->getType() == ElementBase::RBEND ||
430  element2->getType() == ElementBase::SBEND ||
431  element2->getType() == ElementBase::RBEND3D ) {
432  BendBase *bend = static_cast<BendBase*>(element2.get());
433  double E1 = bend->getEntranceAngle();
434  directionBegin = toBegin.rotateFrom(Vector_t(sin(E1), 0, cos(E1)));
435  }
436 
437 
438  double distance = euclidean_norm(begin2 - end1);
439  double directionProjection = dot(directionEnd, directionBegin);
440  bool overlapping = dot(begin2 - end1, directionBegin) < 0.0? true: false;
441 
442  if (!overlapping &&
443  directionProjection > 0.999 &&
444  minDistanceLocal > distance) {
445  minDistanceLocal = distance;
446  }
447  }
448 
449  if (maxDrift < minDistanceLocal &&
450  minDistanceLocal != std::numeric_limits<double>::max()) {
451  maxDrift = minDistanceLocal;
452  }
453  }
454 
455  maxDrift = std::min(maxIntegSteps_m * std::abs(dt_m) * Physics::c, maxDrift);
456 
457  return maxDrift;
458 }
const size_t maxIntegSteps_m
the number of time steps to track
Definition: OrbitThreader.h:52
Representation for a marker element.
Definition: MarkerRep.h:32
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
size_t loggingFrequency_m
Definition: OrbitThreader.h:65
constexpr double e
The value of .
Definition: Physics.h:40
void autophaseCavities(const IndexMap::value_t &activeSet, const std::set< std::string > &visitedElements)
double getMaxDesignEnergy(const IndexMap::value_t &elementSet) const
unsigned int errorFlag_m
Definition: OrbitThreader.h:59
Vector_t p_m
momentum of reference particle
Definition: OrbitThreader.h:40
void trackBack(double maxDrift)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
std::list< ClassicField > FieldList
Definition: ClassicField.h:47
void setDesignEnergy(FieldList &allElements, const std::set< std::string > &visitedElements)
Vector_t r_m
position of reference particle in lab coordinates
Definition: OrbitThreader.h:38
IndexMap imap_m
Definition: OrbitThreader.h:57
Particle reference data.
Definition: PartData.h:38
Inform * gmsg
Definition: Main.cpp:21
double getPhaseAtMaxEnergy(const Vector_t &R, const Vector_t &P, double t, double dt)
virtual void setElementLength(double length)
Set design length.
Definition: ElementBase.h:515
static int myNode()
Definition: IpplInfo.cpp:794
Quaternion getQuaternion(Vector_t u, Vector_t ref)
Definition: Quaternion.cpp:34
const PartData & reference_m
Definition: OrbitThreader.h:62
Vector_t rotateFromLocalCS(const std::shared_ptr< Component > &comp, const Vector_t &r) const
Definition: OpalBeamline.h:203
std::multimap< std::string, elementPosition > elementRegistry_m
Definition: OrbitThreader.h:79
void registerElement(const IndexMap::value_t &elementSet, double, const Vector_t &r, const Vector_t &p)
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
double computeMaximalImplicitDrift()
Vector_t transformToLocalCS(const std::shared_ptr< Component > &comp, const Vector_t &r) const
Definition: OpalBeamline.h:185
void processElementRegister()
double distTrackBack_m
Definition: OrbitThreader.h:45
double getBendAngle() const
Definition: BendBase.h:86
OpalBeamline & itsOpalBeamline_m
Definition: OrbitThreader.h:56
static OpalData * getInstance()
Definition: OpalData.cpp:209
BorisPusher integrator_m
Definition: OrbitThreader.h:61
void add(key_t::first_type initialStep, key_t::second_type finalStep, const value_t &val)
Definition: IndexMap.cpp:90
const double zstop_m
final position in path length
Definition: OrbitThreader.h:54
double time_m
the simulated time
Definition: OrbitThreader.h:47
double dt_m
the time step
Definition: OrbitThreader.h:49
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:52
void saveSDDS(double startS) const
Definition: IndexMap.cpp:155
void kick(const Vector_t &R, Vector_t &P, const Vector_t &Ef, const Vector_t &Bf, const double &dt) const
Definition: BorisPusher.h:48
OrbitThreader(const PartData &ref, const Vector_t &r, const Vector_t &p, double s, double maxDiffZBunch, double t, double dT, size_t maxIntegSteps, double zstop, OpalBeamline &bl)
#define EOL
FieldList getElementByType(ElementBase::ElementType)
void setCSTrafoGlobal2Local(const CoordinateSystemTrafo &ori)
Definition: ElementBase.h:595
bool containsCavity(const IndexMap::value_t &activeSet)
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
int autoPhase
Definition: Options.cpp:45
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
#define EVERYTHINGFINE
std::ofstream logger_m
Definition: OrbitThreader.h:64
void integrate(const IndexMap::value_t &activeSet, size_t maxSteps, double maxDrift=10.0)
#define HITMATERIAL
Vector_t rotateToLocalCS(const std::shared_ptr< Component > &comp, const Vector_t &r) const
Definition: OpalBeamline.h:197
std::set< std::shared_ptr< Component > > getElements(const Vector_t &x)
Interface for RF cavity.
Definition: RFCavity.h:37
double getM() const
The constant mass per particle.
Definition: PartData.h:112
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
CoordinateSystemTrafo getCSTrafoLab2Local(const std::shared_ptr< Component > &comp) const
Definition: OpalBeamline.h:209
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
const std::string name
double pathLength_m
position of reference particle in path length
Definition: OrbitThreader.h:42
std::string::iterator iterator
Definition: MSLang.h:16
virtual ElementBase * clone() const
Return clone.
Definition: MarkerRep.cpp:45
double getEntranceAngle() const
Definition: BendBase.h:97
std::string getInputBasename()
get input file name without extension
Definition: OpalData.cpp:717
Definition: Inform.h:41
virtual double getDesignEnergy() const override
Definition: RFCavity.h:352
Inform & level1(Inform &inf)
Definition: Inform.cpp:45
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:95
void push(Vector_t &R, const Vector_t &P, const double &dt) const
Definition: BorisPusher.h:116
void tidyUp(double zstop)
Definition: IndexMap.cpp:125
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