33 placementAssembly_m(),
35 compatibilityPlacementCompiled_m(false) {}
39 placementAssembly_m(),
41 compatibilityPlacementCompiled_m(false),
42 coordTransformationTo_m(origin, rotation) {}
47 std::set<std::shared_ptr<Component>> elementSet;
49 const FieldList::iterator end =
elements_m.end();
50 for (; it != end; ++it) {
51 std::shared_ptr<Component> element = (*it).getElement();
54 if (element->isInside(r)) {
55 elementSet.insert(element);
63 std::set<std::shared_ptr<Component>> elementSet;
65 elementSet.insert(item.getElement());
73 unsigned long rtv = 0x00;
81 unsigned long rtv = 0x00;
85 std::set<std::shared_ptr<Component>>::const_iterator it =
elements.begin();
86 const std::set<std::shared_ptr<Component>>::const_iterator end =
elements.end();
88 for (; it != end; ++it) {
96 (*it)->applyToReferenceParticle(localR, localP, t, localE, localB);
113 const double& min,
const double& max,
const double& kineticEnergy,
115 FieldList::iterator fprev;
119 if (!(*flit).isOn() && max > (*flit).getStart() && min < (*flit).getEnd()) {
120 (*flit).setOn(kineticEnergy);
169 if ((*fit).getElement()->getType() == type) {
170 elements_of_requested_type.push_back((*fit));
173 return elements_of_requested_type;
177 if (!element->isPositioned()) {
181 element->releasePosition();
186 element->fixPosition();
204 static unsigned int order = 0;
205 const FieldList::iterator end =
elements_m.end();
207 unsigned int minOrder = order;
209 double endPriorPathLength = 0.0;
213 for (; it != end; ++it) {
214 std::shared_ptr<Component> element = (*it).getElement();
215 if (element->isPositioned()) {
218 (*it).order_m = minOrder;
225 double beginThisPathLength = element->getElementPosition();
231 double arcLength = element->getArcLength();
235 cos(0.5 * rotationAngleAboutZ),
240 effectiveRotationAxis = effectiveRotationAxis /
euclidean_norm(effectiveRotationAxis);
243 cos(0.5 * bendAngle), sin(0.5 * bendAngle) * effectiveRotationAxis);
245 cos(0.25 * bendAngle), sin(0.25 * bendAngle) * effectiveRotationAxis);
247 cos(0.5 * entranceAngle), sin(0.5 * entranceAngle) * effectiveRotationAxis);
250 std::vector<Vector_t<double, 3>> truePath = bendElement->
getDesignPath();
252 cos(0.5 * (0.5 * bendAngle - entranceAngle)),
253 sin(0.5 * (0.5 * bendAngle - entranceAngle)) * effectiveRotationAxis);
256 double distanceEntryHETruePath =
euclidean_norm(truePath.front());
258 rotationAboutZ.
rotate(truePath.back()) - exitHardEdge;
260 double pathLengthTruePath = (*it).getEnd() - (*it).getStart();
261 arcLength = pathLengthTruePath - distanceEntryHETruePath - distanceExitHETruePath;
267 double endThisPathLength = beginThisPathLength + arcLength;
270 beginThis3D, (entryFaceRotation * rotationAboutZ).conjugate());
275 currentCoordTrafo = (fromEndLastToEndThis * currentCoordTrafo);
277 endPriorPathLength = endThisPathLength;
281 double endPriorPathLength = 0.0;
285 for (; it != end; ++it) {
286 std::shared_ptr<Component> element = (*it).getElement();
287 if (element->isPositioned())
continue;
289 (*it).order_m = order++;
291 double beginThisPathLength = element->getElementPosition();
292 double thisLength = element->getElementLength();
296 beginThis3D(2) -= thisLength;
308 cos(0.5 * rotationAngleAboutZ),
313 effectiveRotationAxis = effectiveRotationAxis /
euclidean_norm(effectiveRotationAxis);
316 cos(0.5 * bendAngle), sin(0.5 * bendAngle) * effectiveRotationAxis);
318 cos(0.25 * bendAngle), sin(0.25 * bendAngle) * effectiveRotationAxis);
320 double arcLength = element->getArcLength();
322 std::vector<Vector_t<double, 3>> truePath = bendElement->
getDesignPath();
325 cos(0.5 * (0.5 * bendAngle - entranceAngle)),
326 sin(0.5 * (0.5 * bendAngle - entranceAngle)) * effectiveRotationAxis);
329 double distanceEntryHETruePath =
euclidean_norm(truePath.front());
331 rotationAboutZ.
rotate(truePath.back()) - exitHardEdge;
333 double pathLengthTruePath = (*it).getEnd() - (*it).getStart();
334 arcLength = pathLengthTruePath - distanceEntryHETruePath - distanceExitHETruePath;
341 currentCoordTrafo = fromEndLastToEndThis * currentCoordTrafo;
343 endPriorPathLength = beginThisPathLength + arcLength;
345 double rotationAngleAboutZ = (*it).getElement()->getRotationAboutZ();
347 cos(0.5 * rotationAngleAboutZ),
355 element->fixPosition();
378 && std::filesystem::exists(fileName)) {
379 pos.open(fileName, std::ios_base::app);
385 for (
auto scan = it; scan != end; ++scan) {
386 const std::shared_ptr<Component> scanElement = (*scan).getElement();
399 for (; it != end; ++it) {
400 std::shared_ptr<Component> element = (*it).getElement();
407 mesh.
add(*(element.get()));
411 std::vector<Vector_t<double, 3>> designPath = bendElement->
getDesignPath();
412 unsigned int size = designPath.size();
414 unsigned int minNumSteps = std::max(
415 20u,
static_cast<unsigned int>(std::ceil(
418 unsigned int frequency =
419 std::max(1u,
static_cast<unsigned int>(std::floor((
double)size / minNumSteps)));
421 pos << std::setw(30) << std::left
422 << std::string(
"\"ENTRY EDGE: ") + element->getName() + std::string(
"\"")
423 << std::setw(18) << std::setprecision(10) << entry3D(2) << std::setw(18)
424 << std::setprecision(10) << entry3D(0) << std::setw(18) << std::setprecision(10)
425 << entry3D(1) <<
"\n";
429 pos << std::setw(30) << std::left
430 << std::string(
"\"BEGIN: ") + element->getName() + std::string(
"\"")
431 << std::setw(18) << std::setprecision(10) << position(2) << std::setw(18)
432 << std::setprecision(10) << position(0) << std::setw(18) << std::setprecision(10)
433 << position(1) << std::endl;
435 for (
unsigned int i = frequency; i + 1 < size; i += frequency) {
437 pos << std::setw(30) << std::left
438 << std::string(
"\"MID: ") + element->getName() + std::string(
"\"")
439 << std::setw(18) << std::setprecision(10) << position(2) << std::setw(18)
440 << std::setprecision(10) << position(0) << std::setw(18)
441 << std::setprecision(10) << position(1) << std::endl;
445 pos << std::setw(30) << std::left
446 << std::string(
"\"END: ") + element->getName() + std::string(
"\"") << std::setw(18)
447 << std::setprecision(10) << position(2) << std::setw(18) << std::setprecision(10)
448 << position(0) << std::setw(18) << std::setprecision(10) << position(1)
451 pos << std::setw(30) << std::left
452 << std::string(
"\"EXIT EDGE: ") + element->getName() + std::string(
"\"")
453 << std::setw(18) << std::setprecision(10) << exit3D(2) << std::setw(18)
454 << std::setprecision(10) << exit3D(0) << std::setw(18) << std::setprecision(10)
455 << exit3D(1) << std::endl;
457 pos << std::setw(30) << std::left
458 << std::string(
"\"BEGIN: ") + element->getName() + std::string(
"\"")
459 << std::setw(18) << std::setprecision(10) << entry3D(2) << std::setw(18)
460 << std::setprecision(10) << entry3D(0) << std::setw(18) << std::setprecision(10)
461 << entry3D(1) <<
"\n";
463 pos << std::setw(30) << std::left
464 << std::string(
"\"END: ") + element->getName() + std::string(
"\"") << std::setw(18)
465 << std::setprecision(10) << exit3D(2) << std::setw(18) << std::setprecision(10)
466 << exit3D(0) << std::setw(18) << std::setprecision(10) << exit3D(1) << std::endl;
474 std::string parseInput() {
476 std::string source(
"");
479 const std::string commentFormat(
"");
480 const std::regex empty(
"^[ \t]*$");
481 const std::regex lineEnd(
";");
482 const std::string lineEndFormat(
";\n");
483 const std::regex cppCommentExpr(
"//.*");
484 const std::regex cCommentExpr(
486 bool priorEmpty =
true;
492 std::getline(in, str);
493 str = std::regex_replace(
494 str, cppCommentExpr, commentFormat, std::regex_constants::format_default);
495 str = std::regex_replace(
496 str, empty, commentFormat, std::regex_constants::format_default);
500 }
else if (!priorEmpty) {
501 source +=
"##EMPTY_LINE##";
508 source = std::regex_replace(source, cCommentExpr, commentFormat);
509 source = std::regex_replace(
510 source, lineEnd, lineEndFormat,
511 std::regex_constants::match_default | std::regex_constants::format_default);
517 const std::regex lineCommand(
518 "(LINE[ \t]*=[ \t]*\\([^\\)]*\\))[ \t]*,[^;]*;", std::regex::icase);
519 const std::string firstSubExpression(
"\\1;");
520 source = std::regex_replace(source, lineCommand, firstSubExpression);
525 unsigned int getMinimalSignificantDigits(
double num,
const unsigned int maxDigits) {
527 snprintf(buf, 32,
"%.*f", maxDigits + 1, num);
528 std::string numStr(buf);
529 unsigned int length = numStr.length();
531 unsigned int numDigits = maxDigits;
533 while (i < maxDigits + 1 && numStr[length - i] ==
'0') {
541 std::string round2string(
double num,
const unsigned int maxDigits) {
544 snprintf(buf, 64,
"%.*f", getMinimalSignificantDigits(num, maxDigits), num);
546 return std::string(buf);
556 std::string input = parseInput();
560 std::ofstream pos(fname);
562 for (; it != end; ++it) {
563 std::shared_ptr<Component> element = (*it).getElement();
564 std::string elementName = element->getName();
565 const std::regex replacePSI(
566 "(" + elementName +
"\\s*:[^\\n]*)PSI\\s*=[^,;]*,?", std::regex::icase);
567 input = std::regex_replace(input, replacePSI,
"\\1\\2");
569 const std::regex replaceELEMEDGE(
570 "(" + elementName +
"\\s*:[^\\n]*)ELEMEDGE\\s*=[^,;]*(.)", std::regex::icase);
576 for (
unsigned int d = 0; d < 3; ++d)
580 (std::abs(origin(0)) > 1e-10 ?
"X = " + round2string(origin(0), 10) +
", " :
"");
582 (std::abs(origin(1)) > 1e-10 ?
"Y = " + round2string(origin(1), 10) +
", " :
"");
584 (std::abs(origin(2)) > 1e-10 ?
"Z = " + round2string(origin(2), 10) +
", " :
"");
587 (orient(0) > 1e-10 ?
"THETA = " + round2string(orient(0), 6) +
" * PI / 180, "
590 (orient(1) > 1e-10 ?
"PHI = " + round2string(orient(1), 6) +
" * PI / 180, " :
"");
592 (orient(2) > 1e-10 ?
"PSI = " + round2string(orient(2), 6) +
" * PI / 180, " :
"");
593 std::string coordTrafo = x + y + z + theta + phi + psi;
594 if (coordTrafo.length() > 2) {
595 coordTrafo = coordTrafo.substr(0, coordTrafo.length() - 2);
598 std::string position = (
"\\1" + coordTrafo +
"\\2");
600 input = std::regex_replace(input, replaceELEMEDGE, position);
603 const std::regex empty(
"##EMPTY_LINE##");
604 const std::string emptyFormat(
"\n");
605 input = std::regex_replace(input, empty, emptyFormat);
607 pos << input << std::endl;
613 double designEnergy = 0.0;
614 for (; it != end; ++it) {
615 std::shared_ptr<Component> element = (*it).getElement();
616 (*it).setOn(designEnergy);
617 element->goOnline(designEnergy);
std::list< BeamlineFieldElement > FieldList
ippl::Vector< T, Dim > Vector_t
KOKKOS_INLINE_FUNCTION double euclidean_norm(const Vector_t< T, D > &v)
Beamline component together with its active longitudinal field interval.
static bool SortAsc(const BeamlineFieldElement &fle1, const BeamlineFieldElement &fle2)
Common OPALX interface for analytic horizontal bending magnets.
std::vector< Vector_t< double, 3 > > getDesignPath(std::size_t minSamples=32) const
Sample the local curved reference path of the bend body.
double getChordLength() const
Return the geometric chord between entrance and exit frames.
double getBendAngle() const
double getEntranceAngle() const
Rigid spatial transform between a parent frame and a local frame.
ippl::Vector< double, 3 > getOrigin() const
ippl::Vector< double, 3 > transformFrom(const ippl::Vector< double, 3 > &r) const
Map a point from the local frame back to the parent frame.
ippl::Vector< double, 3 > transformTo(const ippl::Vector< double, 3 > &r) const
Map a point from the parent frame to the local frame.
Quaternion getRotation() const
double getRotationAboutZ() const
void add(const ElementBase &element)
void setDriftReference(double minor, double major)
Set the drift support radius used when meshing drift spaces.
void write(const std::string &fname)
static bool getTransverseSupport(const ElementBase &element, double &minor, double &major)
Extract a transverse support size suitable for placement/export meshes.
FieldList getElementByType(ElementType)
Vector_t< double, 3 > rotateToLocalCS(const std::shared_ptr< Component > &comp, const Vector_t< double, 3 > &r) const
void positionElementRelative(std::shared_ptr< ElementBase >)
void merge(OpalBeamline &rhs)
bool compatibilityPlacementCompiled_m
unsigned long getFieldAt(const unsigned int &, const Vector_t< double, 3 > &, const long &, const double &, Vector_t< double, 3 > &, Vector_t< double, 3 > &)
CoordinateSystemTrafo getNominalExitTransform(const std::shared_ptr< Component > &comp) const
CoordinateSystemTrafo coordTransformationTo_m
CoordinateSystemTrafo getNominalEntryTransform(const std::shared_ptr< Component > &comp) const
PlacedElement getPlacedElement(const std::shared_ptr< Component > &comp) const
Return the placed-element view used by the bridge stage.
void print(Inform &) const
Vector_t< double, 3 > transformToLocalCS(const std::shared_ptr< Component > &comp, const Vector_t< double, 3 > &r) const
void setNominalPlacement(const std::shared_ptr< ElementBase > &element, const CoordinateSystemTrafo &parentToBody)
Update the nominal rigid placement transform of one element.
void switchElements(const double &, const double &, const double &kineticEnergy, const bool &nomonitors=false)
void compileCompatibilityPlacement()
Compile legacy reference-order placement into explicit nominal poses.
void storePlacedElement(const std::shared_ptr< ElementBase > &element)
Refresh the beamline-owned placed-element assembly record.
CoordinateSystemTrafo getCSTrafoLab2Local() const
Vector_t< double, 3 > rotateFromLocalCS(const std::shared_ptr< Component > &comp, const Vector_t< double, 3 > &r) const
PlacementAssembly placementAssembly_m
std::set< std::shared_ptr< Component > > getElements()
void swap(OpalBeamline &rhs)
std::string getInputBasename()
get input file name without extension
OpenMode getOpenMode() const
static OpalData * getInstance()
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Geometric placement record for an element instance.
CoordinateSystemTrafo getNominalBodyTransform() const
Nominal rigid placement transform.
Quaternion storage and rotation algebra used by OPALX geometry code.
Quaternion conjugate() const
Return the quaternion conjugate .
ippl::Vector< double, 3 > rotate(const ippl::Vector< double, 3 > &) const
Rotate a spatial vector by a unit quaternion.
std::string combineFilePath(std::initializer_list< std::string > ilist)
Vector_t< double, 3 > getTaitBryantAngles(Quaternion rotation, const std::string &)