OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
Offset.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014, Chris Rogers
3 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * 1. Redistributions of source code must retain the above copyright notice,
7 * this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright notice,
9 * this list of conditions and the following disclaimer in the documentation
10 * and/or other materials provided with the distribution.
11 * 3. Neither the name of STFC nor the names of its contributors may be used to
12 * endorse or promote products derived from this software without specific
13 * prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "AbsBeamline/Offset.h"
29
30#include <cmath>
31
35#include "Physics/Physics.h"
36
37const double Offset::lengthUnits_m = 1e3;
38double Offset::float_tolerance = 1e-12;
39
40Offset::Offset(const std::string& name)
41 : Component(name), _is_local(false), geometry_m(nullptr) {
43}
44
46 : Offset("")
47{}
48
49Offset::Offset(std::string name, const Offset& rhs)
50 : Component(name), _is_local(false), geometry_m(nullptr) {
51 *this = rhs;
53}
54
56 : Component(rhs.getName()), _is_local(false), geometry_m(nullptr) {
57 *this = rhs;
58}
59
61 delete geometry_m;
62}
63
65 if (&rhs == this) {
66 return *this;
67 }
68 setName(rhs.getName());
71 _is_local = rhs._is_local;
72
73 if (geometry_m != nullptr)
74 delete geometry_m;
75 if (rhs.geometry_m == nullptr) {
76 geometry_m = nullptr;
77 } else {
79 }
80 setAperture(rhs.getAperture().first, rhs.getAperture().second);
81 return *this;
82}
83
84void Offset::accept(BeamlineVisitor & visitor) const {
85 visitor.visitOffset(*this);
86}
87
89 throw GeneralClassicException("Offset::getField()",
90 "No field defined for Offset");
91}
92
93const EMField &Offset::getField() const {
94 throw GeneralClassicException("Offset::getField() const",
95 "No field defined for Offset");
96}
97
98void Offset::initialise(PartBunchBase<double, 3> *bunch, double &/*startField*/, double &/*endField*/) {
99 RefPartBunch_m = bunch;
100}
101
103 RefPartBunch_m = nullptr;
104}
105
107 return new Offset(*this);
108}
109
111 _end_position = position;
112}
113
115 return _end_position;
116}
117
119 _end_direction = direction;
120}
121
123 return _end_direction;
124}
125
126void Offset::setIsLocal(bool isLocal) {
127 _is_local = isLocal;
128}
129
130bool Offset::getIsLocal() const {
131 return _is_local;
132}
133
135 return *geometry_m;
136}
137
139 return *geometry_m;
140}
141
142// std::ostream& operator<<(std::ostream& out, const Vector_t& vec) {
143// out << "(" << vec(0) << ", " << vec(1) << ", " << vec(2) << ")";
144// return out;
145// }
146
148 if (std::abs(vec1(2)) > 1e-9 || std::abs(vec2(2)) > 1e-9)
149 throw GeneralClassicException("Offset::getTheta(...)",
150 "Rotations out of midplane are not implemented");
151 // probably not the most efficient, but only called at set up
152 double theta = std::atan2(vec2(1), vec2(0))-std::atan2(vec1(1), vec1(0));
153 if (theta < -Physics::pi)
154 theta += 2.*Physics::pi; // force into domain -pi < theta < pi
155 return theta;
156}
157
159 double s = std::sin(theta);
160 double c = std::cos(theta);
161 return Vector_t(+vec(0)*c-vec(1)*s,
162 +vec(0)*s+vec(1)*c,
163 0.);
164}
165
167 if (!_is_local)
168 throw GeneralClassicException("Offset::updateGeometry(...)",
169 "Global offset needs a local coordinate system");
170 Vector_t translation = getEndPosition();
171 double length = std::sqrt(translation(0)*translation(0)+
172 translation(1)*translation(1)+
173 translation(2)*translation(2));
174 double theta_in = getTheta(Vector_t(1., 0., 0.), translation);
175 double theta_out = getTheta(Vector_t(1., 0., 0.), getEndDirection());
176 Euclid3D euclid3D(-std::sin(theta_in)*length, 0., std::cos(theta_in)*length,
177 0., -theta_out, 0.);
178 if (geometry_m != nullptr)
179 delete geometry_m;
180 geometry_m = new Euclid3DGeometry(euclid3D);
181}
182
183void Offset::updateGeometry(Vector_t /*startPosition*/, Vector_t startDirection) {
184 if (!_is_local) {
185 Vector_t translationGlobal = _end_position;
186 double theta_g2l = getTheta(startDirection, Vector_t(1, 0, 0));
187 _end_position = rotate(translationGlobal, theta_g2l);
189 _is_local = true;
190 }
192}
193
195 return geometry_m != nullptr;
196}
197
198bool operator==(const Offset& off1, const Offset& off2) {
199 const double tol = Offset::float_tolerance;
200 if (off1.getName() != off2.getName() ||
201 off1.getIsLocal() != off2.getIsLocal()) {
202 return false;
203 }
204 for (int i = 0; i < 3; ++i) {
205 if ( (std::abs(off1.getEndPosition()(i)-off2.getEndPosition()(i)) > tol) ||
206 (std::abs(off1.getEndDirection()(i)-off2.getEndDirection()(i)) > tol))
207 return false;
208 }
209 if ( (!off1.isGeometryAllocated() && off2.isGeometryAllocated()) ||
210 (!off2.isGeometryAllocated() && off1.isGeometryAllocated()))
211 return false;
212 Euclid3D transform1 = off1.getGeometry().getTotalTransform();
213 Euclid3D transform2 = off2.getGeometry().getTotalTransform();
214 Vector3D dTranslation = transform1.getVector() - transform2.getVector();
215 Vector3D dRotation = transform1.getRotation().getAxis() -
216 transform2.getRotation().getAxis();
217 for (size_t i = 0; i < 3; ++i)
218 if (std::abs(dTranslation(i)) > tol || std::abs(dRotation(i)) > tol)
219 return false;
220 return true;
221}
222
223bool operator!=(const Offset& off1, const Offset& off2) {
224 return !(off1 == off2);
225}
226
227std::ostream& operator<<(std::ostream& out, const Offset& off) {
228 out << "Offset " << off.getName() << " local " << off.getIsLocal()
229 << " end pos: " << off.getEndPosition()
230 << " end dir: " << off.getEndDirection() << std::endl;
231 return out;
232}
233
234bool Offset::bends() const {
235 if (geometry_m == nullptr) {
236 throw GeneralClassicException("Offset::bends",
237 "Try to determine if Offset bends when geometry_m not allocated");
238 }
240 for (size_t i = 0; i < 3; ++i)
241 if (std::abs(rotation.getAxis()(i)) > float_tolerance) {
242 return true;
243 }
245 if (std::abs(vector(0)) > float_tolerance || std::abs(vector(1)) > float_tolerance) {
246 return true;
247 }
248 return false;
249}
250
251
253 double phi_in,
254 double phi_out,
255 double displacement) {
256 Offset off(name);
257 displacement *= lengthUnits_m;
258 off.setEndPosition(Vector_t(std::cos(phi_in)*displacement,
259 std::sin(phi_in)*displacement,
260 0.));
261 off.setEndDirection(Vector_t(std::cos(phi_in+phi_out), std::sin(phi_in+phi_out), 0.));
262 off.setIsLocal(true);
263 off.updateGeometry();
264 return off;
265}
266
268 double radius_out,
269 double phi_out,
270 double theta_out) {
271 Offset off(name);
272 radius_out *= lengthUnits_m;
273 off.setEndPosition(Vector_t(std::cos(phi_out)*radius_out,
274 std::sin(phi_out)*radius_out,
275 0.));
276 off.setEndDirection(Vector_t(std::sin(phi_out+theta_out),
277 std::cos(phi_out+theta_out),
278 0.));
279 off.setIsLocal(false);
280 return off;
281}
282
284 Vector_t end_position,
285 Vector_t end_direction) {
286 Offset off(name);
287 end_position *= lengthUnits_m;
288 off.setEndPosition(end_position);
289 off.setEndDirection(end_direction);
290 off.setIsLocal(true);
291 off.updateGeometry();
292 return off;
293}
294
296 Vector_t end_position,
297 Vector_t end_direction) {
298 Offset off(name);
299 end_position *= lengthUnits_m;
300 off.setEndPosition(end_position);
301 off.setEndDirection(end_direction);
302 off.setIsLocal(false);
303 return off;
304}
305
bool operator!=(const Offset &off1, const Offset &off2)
Definition: Offset.cpp:223
bool operator==(const Offset &off1, const Offset &off2)
Definition: Offset.cpp:198
std::ostream & operator<<(std::ostream &out, const Offset &off)
Definition: Offset.cpp:227
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
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
const std::string name
constexpr double e
The value of.
Definition: Physics.h:39
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
constexpr double pi
The value of.
Definition: Physics.h:30
virtual void visitOffset(const Offset &)=0
Apply the algorithm to an offset (placement).
Interface for a single beam element.
Definition: Component.h:50
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
virtual void setName(const std::string &name)
Set element name.
virtual const std::string & getName() const
Get element name.
void setAperture(const ApertureType &type, const std::vector< double > &args)
Definition: ElementBase.h:518
std::pair< ApertureType, std::vector< double > > getAperture() const
Definition: ElementBase.h:524
Definition: Offset.h:66
void updateGeometry()
Definition: Offset.cpp:166
static Vector_t rotate(Vector_t vec, double theta)
Definition: Offset.cpp:158
static double getTheta(Vector_t vec1, Vector_t vec2)
Definition: Offset.cpp:147
void updateGeometry(Vector_t startPosition, Vector_t startDirection)
Definition: Offset.cpp:183
Euclid3DGeometry & getGeometry() override
Get geometry.
Definition: Offset.cpp:134
Offset & operator=(const Offset &)
Definition: Offset.cpp:64
static Offset localCylindricalOffset(std::string name, double theta_in, double theta_out, double displacement)
Definition: Offset.cpp:252
bool isGeometryAllocated() const
Definition: Offset.cpp:194
void finalise() override
Definition: Offset.cpp:102
bool _is_local
Definition: Offset.h:210
Vector_t _end_position
Definition: Offset.h:208
~Offset()
Definition: Offset.cpp:60
static const double lengthUnits_m
Definition: Offset.h:213
void setEndPosition(Vector_t position)
Definition: Offset.cpp:110
Vector_t getEndPosition() const
Definition: Offset.cpp:114
EMField & getField() override
Not implemented - throws GeneralClassicException.
Definition: Offset.cpp:88
Offset()
Definition: Offset.cpp:45
void setEndDirection(Vector_t direction)
Definition: Offset.cpp:118
static double float_tolerance
Definition: Offset.h:206
static Offset globalCartesianOffset(std::string name, Vector_t end_position, Vector_t end_direction)
Definition: Offset.cpp:295
Vector_t _end_direction
Definition: Offset.h:209
static Offset localCartesianOffset(std::string name, Vector_t end_position, Vector_t end_direction)
Definition: Offset.cpp:283
ElementBase * clone() const override
Definition: Offset.cpp:106
void accept(BeamlineVisitor &) const override
Definition: Offset.cpp:84
static Offset globalCylindricalOffset(std::string name, double radius_out, double phi_out, double theta_out)
Definition: Offset.cpp:267
Euclid3DGeometry * geometry_m
Definition: Offset.h:212
bool getIsLocal() const
Definition: Offset.cpp:130
void setIsLocal(bool isLocal)
Definition: Offset.cpp:126
bool bends() const override
Definition: Offset.cpp:234
void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: Offset.cpp:98
Vector_t getEndDirection() const
Definition: Offset.cpp:122
Displacement and rotation in space.
Definition: Euclid3D.h:68
const Vector3D & getVector() const
Get displacement.
Definition: Euclid3D.cpp:59
const Rotation3D & getRotation() const
Get rotation.
Definition: Euclid3D.cpp:64
virtual Euclid3D getTotalTransform() const
Get total transform from beginning to end.
Rotation in 3-dimensional space.
Definition: Rotation3D.h:46
Vector3D getAxis() const
Get axis vector.
Definition: Rotation3D.cpp:91
A 3-dimension vector.
Definition: Vector3D.h:31
Abstract base class for electromagnetic fields.
Definition: EMField.h:188
Definition: Vec.h:22
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6