OPAL (Object Oriented Parallel Accelerator Library) 2024.2
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//
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
76bool 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
112std::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) +
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;
130bool 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
175void 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
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
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
Interface for a single beam element.
Definition: Component.h:50
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B)
Definition: Component.cpp:99
virtual ElementBase * clone() const =0
Return clone.
@Class Offset
Definition: Offset.h:53
void updateGeometry(Vector_t startPosition, Vector_t startDirection)
Convert to a local coordinate system for global offsets.
Definition: Offset.cpp:178
Component placement handler in ring geometry.
Definition: RingSection.h:58
Vector_t componentOrientation_m
Definition: RingSection.h:192
void setStartNormal(Vector_t orientation)
Set the normal vector to the section start plane.
Definition: RingSection.h:212
RingSection & operator=(const RingSection &sec)
Definition: RingSection.cpp:46
void rotate(Vector_t &vector) const
void handleOffset()
Check whether component_m is a global offset and handle.
void setStartPosition(Vector_t pos)
Set a position on the plane of the section start.
Definition: RingSection.h:134
Vector_t getStartNormal() const
Get the normal vector to the section start plane.
Definition: RingSection.h:143
Vector_t startPosition_m
Definition: RingSection.h:194
bool getFieldValue(const Vector_t &pos, const Vector_t &centroid, const double &t, Vector_t &E, Vector_t &B) const
Return field value in global coordinate system.
Definition: RingSection.cpp:88
void rotateToCyclCoordinates(Vector_t &vec) const
Definition: RingSection.h:235
Vector_t endOrientation_m
Definition: RingSection.h:198
void rotate_back(Vector_t &vector) const
Vector_t startOrientation_m
Definition: RingSection.h:195
bool isOnOrPastStartPlane(const Vector_t &pos) const
Return true if pos is on or past start plane.
Definition: RingSection.cpp:63
Vector_t componentPosition_m
Definition: RingSection.h:191
double sin2_m
Definition: RingSection.h:201
Component * component_m
Definition: RingSection.h:189
bool doesOverlap(double phiStart, double phiEnd) const
Return true if the phi range overlaps bounding box elements.
Vector_t getEndPosition() const
Get a position on the section end plane.
Definition: RingSection.h:149
double cos2_m
Definition: RingSection.h:202
void updateComponentOrientation()
Vector_t getStartPosition() const
Get a position on the plane of the section start.
Definition: RingSection.h:137
void setEndPosition(Vector_t pos)
Set a position on the section end plane.
Definition: RingSection.h:146
Vector_t getEndNormal() const
Get the normal vector to the section end plane.
Definition: RingSection.h:155
void setEndNormal(Vector_t orientation)
Set the normal vector to the section end plane
Definition: RingSection.h:216
Vector_t endPosition_m
Definition: RingSection.h:197
Vector_t & normalise(Vector_t &vector) const
Definition: RingSection.h:220
std::vector< Vector_t > getVirtualBoundingBox() const
Get the "Virtual" bounding box for the RingSection.
void rotateToTCoordinates(Vector_t &vec) const
Definition: RingSection.h:231
bool isPastEndPlane(const Vector_t &pos) const
Return true if pos is past end plane.
Definition: RingSection.cpp:76
RingSection()
Construct a ring section - positions, orientations etc default to 0.
Definition: RingSection.cpp:25
~RingSection()
Destructor - does nothing.
Definition: RingSection.cpp:40
Vektor< double, 3 > Vector_t