OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
RingSection.cpp
Go to the documentation of this file.
1 //
2 // Class RingSection
3 // Defines the component placement handler in ring geometry.
4 //
5 // Copyright (c) 2012 - 2023, Chris Rogers, STFC Rutherford Appleton Laboratory, Didcot, UK
6 // All rights reserved
7 //
8 // This file is part of OPAL.
9 //
10 // OPAL is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17 //
18 #include "Utilities/RingSection.h"
19 
20 #include "AbsBeamline/Offset.h"
21 #include "Physics/Physics.h"
23 
24 
26  component_m(nullptr),
27  componentPosition_m(0.), componentOrientation_m(0.),
28  startPosition_m(0.), startOrientation_m(0.),
29  endPosition_m(0.), endOrientation_m(0.) {
30 }
31 
33  component_m(nullptr),
34  componentPosition_m(0.), componentOrientation_m(0.),
35  startPosition_m(0.), startOrientation_m(0.),
36  endPosition_m(0.), endOrientation_m(0.) {
37  *this = rhs;
38 }
39 
41  //if (component_m != nullptr)
42  // delete component_m;
43 }
44 
45 // Assignment operator
47  if (&rhs != this) {
48  component_m = dynamic_cast<Component*>(rhs.component_m->clone());
49  if (component_m == nullptr) {
50  throw GeneralClassicException("RingSection::operator=",
51  "Failed to copy RingSection");
52  }
59  }
60  return *this;
61 }
62 
64  Vector_t posTransformed = pos - startPosition_m;
65  // check that pos-startPosition_m is in front of startOrientation_m
66  double normProd = posTransformed(0) * startOrientation_m(0) +
67  posTransformed(1) * startOrientation_m(1) +
68  posTransformed(2) * startOrientation_m(2);
69  // check that pos and startPosition_m are on the same side of the ring
70  double posProd = pos(0) * startPosition_m(0) +
71  pos(1) * startPosition_m(1) +
72  pos(2) * startPosition_m(2);
73  return normProd >= 0. && posProd >= 0.;
74 }
75 
76 bool RingSection::isPastEndPlane(const Vector_t& pos) const {
77  Vector_t posTransformed = pos - endPosition_m;
78  double normProd = posTransformed(0) * endOrientation_m(0) +
79  posTransformed(1) * endOrientation_m(1)+
80  posTransformed(2) * endOrientation_m(2);
81  // check that pos and endPosition_m are on the same side of the ring
82  double posProd = pos(0) * endPosition_m(0) +
83  pos(1) * endPosition_m(1) +
84  pos(2) * endPosition_m(2);
85  return normProd > 0. && posProd > 0.;
86 }
87 
89  const Vector_t& /*centroid*/, const double& t,
90  Vector_t& E, Vector_t& B) const {
91  // transform position into local coordinate system
92  Vector_t pos_local = pos-componentPosition_m;
93  rotate(pos_local);
94  rotateToTCoordinates(pos_local);
95  bool outOfBounds = component_m->apply(pos_local, Vector_t(0.0), t, E, B);
96  if (outOfBounds) {
97  return true;
98  }
99  // rotate fields back to global coordinate system
102  rotate_back(E);
103  rotate_back(B);
104  return false;
105 }
106 
110 }
111 
112 std::vector<Vector_t> RingSection::getVirtualBoundingBox() const {
113  Vector_t startParallel(getStartNormal()(1), -getStartNormal()(0), 0);
114  Vector_t endParallel(getEndNormal()(1), -getEndNormal()(0), 0);
115  normalise(startParallel);
116  normalise(endParallel);
117  double startRadius = 0.99 * std::sqrt(getStartPosition()(0) * getStartPosition()(0) +
118  getStartPosition()(1) * getStartPosition()(1));
119  double endRadius = 0.99 * std::sqrt(getEndPosition()(0) * getEndPosition()(0) +
120  getEndPosition()(1) * getEndPosition()(1));
121  std::vector<Vector_t> bb;
122  bb.push_back(getStartPosition() - startParallel * startRadius);
123  bb.push_back(getStartPosition() + startParallel * startRadius);
124  bb.push_back(getEndPosition() - endParallel * endRadius);
125  bb.push_back(getEndPosition() + endParallel * endRadius);
126  return bb;
127 }
128 
129 // double phi = atan2(r(1), r(0))+Physics::pi;
130 bool RingSection::doesOverlap(double phiStart, double phiEnd) const {
131  RingSection phiVirtualORS;
132  phiVirtualORS.setStartPosition(Vector_t(std::sin(phiStart),
133  std::cos(phiStart),
134  0.));
135  phiVirtualORS.setStartNormal(Vector_t(std::cos(phiStart),
136  -std::sin(phiStart),
137  0.));
138  phiVirtualORS.setEndPosition(Vector_t(std::sin(phiEnd),
139  std::cos(phiEnd),
140  0.));
141  phiVirtualORS.setEndNormal(Vector_t(std::cos(phiEnd),
142  -std::sin(phiEnd),
143  0.));
144  std::vector<Vector_t> virtualBB = getVirtualBoundingBox();
145  // at least one of the bounding box coordinates is in the defined sector
146  // std::cerr << "RingSection::doesOverlap " << phiStart << " " << phiEnd << " "
147  // << phiVirtualORS.getStartPosition() << " " << phiVirtualORS.getStartNormal() << " "
148  // << phiVirtualORS.getEndPosition() << " " << phiVirtualORS.getEndNormal() << " " << std::endl
149  // << " Component " << this << " " << getStartPosition() << " " << getStartNormal() << " "
150  // << getEndPosition() << " " << getEndNormal() << " " << std::endl;
151  for (size_t i = 0; i < virtualBB.size(); ++i) {
152  // std::cerr << " VBB " << i << " " << virtualBB[i] << std::endl;
153  if (phiVirtualORS.isOnOrPastStartPlane(virtualBB[i]) &&
154  !phiVirtualORS.isPastEndPlane(virtualBB[i]))
155  return true;
156  }
157  // the bounding box coordinates span the defined sector and the sector
158  // sits inside the bb
159  bool hasBefore = false; // some elements in bb are before phiVirtualORS
160  bool hasAfter = false; // some elements in bb are after phiVirtualORS
161  for (size_t i = 0; i < virtualBB.size(); ++i) {
162  hasBefore = hasBefore ||
163  !phiVirtualORS.isOnOrPastStartPlane(virtualBB[i]);
164  hasAfter = hasAfter ||
165  phiVirtualORS.isPastEndPlane(virtualBB[i]);
166  // std::cerr << " " << hasBefore << " " << hasAfter << std::endl;
167  }
168  if (hasBefore && hasAfter)
169  return true;
170  // std::cerr << "DOES NOT OVERLAP" << std::endl;
171  return false;
172 }
173 
174 
175 void RingSection::rotate(Vector_t& vector) const {
176  const Vector_t temp(vector);
177  vector(0) = +cos2_m * temp(0) + sin2_m * temp(1);
178  vector(1) = +sin2_m * temp(0) - cos2_m * temp(1);
179 }
180 
181 void RingSection::rotate_back(Vector_t& vector) const {
182  const Vector_t temp(vector);
183  vector(0) = +cos2_m * temp(0) + sin2_m * temp(1);
184  vector(1) = +sin2_m * temp(0) - cos2_m * temp(1);
185 }
186 
188  Offset* offsetCast = dynamic_cast<Offset*>(component_m);
189  if (offsetCast == nullptr) {
190  return; // nothing to do, it wasn't an offset at all
191  }
193 }
194 
void rotateToTCoordinates(Vector_t &vec) const
Definition: RingSection.h:231
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
void rotate_back(Vector_t &vector) const
void setEndPosition(Vector_t pos)
Definition: RingSection.h:146
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
Vector_t & normalise(Vector_t &vector) const
Definition: RingSection.h:220
Definition: Offset.h:53
bool isPastEndPlane(const Vector_t &pos) const
Definition: RingSection.cpp:76
RingSection & operator=(const RingSection &sec)
Definition: RingSection.cpp:46
std::vector< Vector_t > getVirtualBoundingBox() const
bool isOnOrPastStartPlane(const Vector_t &pos) const
Definition: RingSection.cpp:63
void updateGeometry(Vector_t startPosition, Vector_t startDirection)
Definition: Offset.cpp:178
double sin2_m
Definition: RingSection.h:201
void setEndNormal(Vector_t orientation)
Definition: RingSection.h:216
Vector_t getStartPosition() const
Definition: RingSection.h:137
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B)
Definition: Component.cpp:99
bool getFieldValue(const Vector_t &pos, const Vector_t &centroid, const double &t, Vector_t &E, Vector_t &B) const
Definition: RingSection.cpp:88
void setStartNormal(Vector_t orientation)
Definition: RingSection.h:212
Vector_t getStartNormal() const
Definition: RingSection.h:143
Component placement handler in ring geometry.
Definition: RingSection.h:58
void rotateToCyclCoordinates(Vector_t &vec) const
Definition: RingSection.h:235
void handleOffset()
Vector_t startPosition_m
Definition: RingSection.h:194
Component * component_m
Definition: RingSection.h:189
Vector_t getEndNormal() const
Definition: RingSection.h:155
void rotate(Vector_t &vector) const
double cos2_m
Definition: RingSection.h:202
void setStartPosition(Vector_t pos)
Definition: RingSection.h:134
bool doesOverlap(double phiStart, double phiEnd) const
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
virtual ElementBase * clone() const =0
Return clone.
Vector_t componentOrientation_m
Definition: RingSection.h:192
Vector_t startOrientation_m
Definition: RingSection.h:195
Vector_t componentPosition_m
Definition: RingSection.h:191
void updateComponentOrientation()
Interface for a single beam element.
Definition: Component.h:50
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Vector_t getEndPosition() const
Definition: RingSection.h:149
Vector_t endPosition_m
Definition: RingSection.h:197
Vector_t endOrientation_m
Definition: RingSection.h:198