OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
Offset.cpp
Go to the documentation of this file.
1 //
2 // Class Offset
3 // Defines the abstract interface for offset of elements.
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 "AbsBeamline/Offset.h"
19 
21 #include "Physics/Physics.h"
23 
24 #include <cmath>
25 
26 double Offset::float_tolerance = 1e-12;
27 
28 Offset::Offset(const std::string& name)
29  : Component(name), _is_local(false), geometry_m(nullptr) {
31 }
32 
34  : Offset("")
35 {}
36 
37 Offset::Offset(const std::string& name, const Offset& rhs)
38  : Component(name), _is_local(false), geometry_m(nullptr) {
39  *this = rhs;
40 }
41 
43  : Component(rhs.getName()), _is_local(false), geometry_m(nullptr) {
44  *this = rhs;
45 }
46 
48  delete geometry_m;
49 }
50 
52  if (&rhs == this) {
53  return *this;
54  }
55  setName(rhs.getName());
58  _is_local = rhs._is_local;
59 
60  if (geometry_m != nullptr)
61  delete geometry_m;
62  if (rhs.geometry_m == nullptr) {
63  geometry_m = nullptr;
64  } else {
66  }
67  setAperture(rhs.getAperture().first, rhs.getAperture().second);
68  return *this;
69 }
70 
71 void Offset::accept(BeamlineVisitor& visitor) const {
72  visitor.visitOffset(*this);
73 }
74 
76  throw GeneralClassicException("Offset::getField()",
77  "No field defined for Offset");
78 }
79 
80 const EMField& Offset::getField() const {
81  throw GeneralClassicException("Offset::getField() const",
82  "No field defined for Offset");
83 }
84 
85 void Offset::initialise(PartBunchBase<double, 3>* bunch, double& /*startField*/, double& /*endField*/) {
86  RefPartBunch_m = bunch;
87 }
88 
90  RefPartBunch_m = nullptr;
91 }
92 
94  return new Offset(*this);
95 }
96 
98  _end_position = position;
99 }
100 
102  return _end_position;
103 }
104 
106  _end_direction = direction;
107 }
108 
110  return _end_direction;
111 }
112 
113 void Offset::setIsLocal(bool isLocal) {
114  _is_local = isLocal;
115 }
116 
117 bool Offset::getIsLocal() const {
118  return _is_local;
119 }
120 
122  return *geometry_m;
123 }
124 
126  return *geometry_m;
127 }
128 
129 // std::ostream& operator<<(std::ostream& out, const Vector_t& vec) {
130 // out << "(" << vec(0) << ", " << vec(1) << ", " << vec(2) << ")";
131 // return out;
132 // }
133 
134 double Offset::getTheta(Vector_t vec1, Vector_t vec2) {
135  if (std::abs(vec1(2)) > 1e-9 || std::abs(vec2(2)) > 1e-9) {
136  throw GeneralClassicException("Offset::getTheta",
137  "Rotations out of midplane are not implemented");
138  }
139 
140  // probably not the most efficient, but only called at set up
141  double theta = std::atan2(vec2(1), vec2(0)) - std::atan2(vec1(1), vec1(0));
142  if (theta < -Physics::pi) {
143  theta += Physics::two_pi; // force into domain -pi < theta < pi
144  }
145  return theta;
146 }
147 
149  double s = std::sin(theta);
150  double c = std::cos(theta);
151  return Vector_t(+vec(0)*c-vec(1)*s,
152  +vec(0)*s+vec(1)*c,
153  0.);
154 }
155 
157  if (!_is_local) {
158  throw GeneralClassicException("Offset::updateGeometry",
159  "Global offset needs a local coordinate system");
160  }
161 
162  Vector_t translation = getEndPosition();
163  double length = std::sqrt(translation(0) * translation(0) +
164  translation(1) * translation(1) +
165  translation(2) * translation(2));
166  double theta_in = getTheta(Vector_t(0., 1., 0.), translation);
167  double theta_out = getTheta(Vector_t(0., 1., 0.), getEndDirection());
168  Euclid3D euclid3D(-std::sin(theta_in) * length, 0., std::cos(theta_in) * length,
169  0., -theta_out, 0.);
170 
171  if (geometry_m != nullptr) {
172  delete geometry_m;
173  }
174 
175  geometry_m = new Euclid3DGeometry(euclid3D);
176 }
177 
178 void Offset::updateGeometry(Vector_t startPosition, Vector_t startDirection) {
179  if (!_is_local) {
180  // thetaIn is the angle between the y axis and startDirection
181  double thetaIn = std::atan2(-startDirection[0], startDirection[1]); // global OPAL-CYCL coords
182  // thetaOut is the angle between the y axis and endDirection
183  double thetaOut = std::atan2(-_end_direction[0], _end_direction[1]); // global OPAL-CYCL coords
184  // thetaRel is the angle between thetaOut and thetaIn
185  double thetaRel = thetaOut-thetaIn;
186  // deltaPosition is the position change in the global coordinate system
187  Vector_t deltaPosition = _end_position-startPosition;
188  // endPosition is the difference between end and startPosition in
189  // startDirection coordinate system
190  _end_position = rotate(deltaPosition, -thetaIn);
191  // end direction is the normal in the coordinate system of startDirection
192  _end_direction = Vector_t(std::sin(-thetaRel), std::cos(-thetaRel), 0);
193  _is_local = true;
194  }
195  updateGeometry();
196 }
197 
199  return geometry_m != nullptr;
200 }
201 
202 bool operator==(const Offset& off1, const Offset& off2) {
203  const double tol = Offset::float_tolerance;
204  if (off1.getName() != off2.getName() ||
205  off1.getIsLocal() != off2.getIsLocal()) {
206  return false;
207  }
208  for (int i = 0; i < 3; ++i) {
209  if ( (std::abs(off1.getEndPosition()(i)-off2.getEndPosition()(i)) > tol) ||
210  (std::abs(off1.getEndDirection()(i)-off2.getEndDirection()(i)) > tol))
211  return false;
212  }
213  if ( (!off1.isGeometryAllocated() && off2.isGeometryAllocated()) ||
214  (!off2.isGeometryAllocated() && off1.isGeometryAllocated()))
215  return false;
216  Euclid3D transform1 = off1.getGeometry().getTotalTransform();
217  Euclid3D transform2 = off2.getGeometry().getTotalTransform();
218  Vector3D dTranslation = transform1.getVector() - transform2.getVector();
219  Vector3D dRotation = transform1.getRotation().getAxis() -
220  transform2.getRotation().getAxis();
221  for (size_t i = 0; i < 3; ++i)
222  if (std::abs(dTranslation(i)) > tol || std::abs(dRotation(i)) > tol)
223  return false;
224  return true;
225 }
226 
227 bool operator!=(const Offset& off1, const Offset& off2) {
228  return !(off1 == off2);
229 }
230 
231 std::ostream& operator<<(std::ostream& out, const Offset& off) {
232  out << "Offset " << off.getName() << " local " << off.getIsLocal()
233  << " end pos: " << off.getEndPosition()
234  << " end dir: " << off.getEndDirection() << std::endl;
235  return out;
236 }
237 
238 bool Offset::bends() const {
239  if (geometry_m == nullptr) {
240  throw GeneralClassicException("Offset::bends",
241  "Try to determine if Offset bends when geometry_m not allocated");
242  }
244  for (size_t i = 0; i < 3; ++i)
245  if (std::abs(rotation.getAxis()(i)) > float_tolerance) {
246  return true;
247  }
249  if (std::abs(vector(0)) > float_tolerance || std::abs(vector(1)) > float_tolerance) {
250  return true;
251  }
252  return false;
253 }
254 
255 
257  double phi_in,
258  double phi_out,
259  double displacement) {
260  Offset off(name);
261  off.setEndPosition(Vector_t(-std::sin(phi_in)*displacement,
262  std::cos(phi_in)*displacement,
263  0.));
264  off.setEndDirection(Vector_t(-std::sin(phi_in+phi_out), std::cos(phi_in+phi_out), 0.));
265  off.setIsLocal(true);
266  off.updateGeometry();
267  return off;
268 }
269 
271  double radius_out,
272  double phi_out,
273  double theta_out) {
274  Offset off(name);
275  off.setEndPosition(Vector_t(std::cos(phi_out)*radius_out,
276  std::sin(phi_out)*radius_out,
277  0.));
278  off.setEndDirection(Vector_t(std::sin(phi_out+theta_out),
279  std::cos(phi_out+theta_out),
280  0.));
281  off.setIsLocal(false);
282  return off;
283 }
284 
286  Vector_t end_position,
287  Vector_t end_direction) {
288  Offset off(name);
289  off.setEndPosition(end_position);
290  off.setEndDirection(end_direction);
291  off.setIsLocal(true);
292  off.updateGeometry();
293  return off;
294 }
295 
297  Vector_t end_position,
298  Vector_t end_direction) {
299  Offset off(name);
300  off.setEndPosition(end_position);
301  off.setEndDirection(end_direction);
302  off.setIsLocal(false);
303  return off;
304 }
Euclid3DGeometry * geometry_m
Definition: Offset.h:209
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
Rotation in 3-dimensional space.
Definition: Rotation3D.h:46
Vector_t getEndDirection() const
Definition: Offset.cpp:109
constexpr double two_pi
The value of .
Definition: Physics.h:33
bool operator!=(const Offset &off1, const Offset &off2)
Definition: Offset.cpp:227
Offset()
Definition: Offset.cpp:33
Euclid3DGeometry & getGeometry() override
Get geometry.
Definition: Offset.cpp:121
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Abstract base class for electromagnetic fields.
Definition: EMField.h:188
std::ostream & operator<<(std::ostream &os, const Attribute &attr)
Definition: Attribute.cpp:169
void finalise() override
Definition: Offset.cpp:89
Offset & operator=(const Offset &)
Definition: Offset.cpp:51
static double float_tolerance
Definition: Offset.h:201
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
virtual Euclid3D getTotalTransform() const
Get total transform from beginning to end.
EMField & getField() override
Not implemented - throws GeneralClassicException.
Definition: Offset.cpp:75
const Rotation3D & getRotation() const
Get rotation.
Definition: Euclid3D.cpp:64
bool operator==(const TwoPolynomial &left, const TwoPolynomial &right)
static Offset localCartesianOffset(const std::string &name, Vector_t end_position, Vector_t end_direction)
Definition: Offset.cpp:285
Definition: Offset.h:53
void setIsLocal(bool isLocal)
Definition: Offset.cpp:113
PartBunchBase< double, 3 > * RefPartBunch_m
Definition: Component.h:191
~Offset()
Definition: Offset.cpp:47
virtual const std::string & getName() const
Get element name.
constexpr double pi
The value of .
Definition: Physics.h:30
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
void updateGeometry(Vector_t startPosition, Vector_t startDirection)
Definition: Offset.cpp:178
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
bool _is_local
Definition: Offset.h:206
static Offset globalCylindricalOffset(const std::string &name, double radius_out, double phi_out, double theta_out)
Definition: Offset.cpp:270
bool isGeometryAllocated() const
Definition: Offset.cpp:198
static double getTheta(Vector_t vec1, Vector_t vec2)
Definition: Offset.cpp:134
void accept(BeamlineVisitor &) const override
Definition: Offset.cpp:71
Definition: Vec.h:21
Vector_t _end_position
Definition: Offset.h:204
static Vector_t rotate(Vector_t vec, double theta)
Definition: Offset.cpp:148
static Offset localCylindricalOffset(const std::string &name, double theta_in, double theta_out, double displacement)
Definition: Offset.cpp:256
bool bends() const override
Definition: Offset.cpp:238
ElementBase * clone() const override
Definition: Offset.cpp:93
bool getIsLocal() const
Definition: Offset.cpp:117
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
std::pair< ApertureType, std::vector< double > > getAperture() const
Definition: ElementBase.h:525
const std::string name
void setEndDirection(Vector_t direction)
Definition: Offset.cpp:105
void updateGeometry()
Definition: Offset.cpp:156
Displacement and rotation in space.
Definition: Euclid3D.h:68
virtual void setName(const std::string &name)
Set element name.
void setEndPosition(Vector_t position)
Definition: Offset.cpp:97
Vector3D getAxis() const
Get axis vector.
Definition: Rotation3D.cpp:91
constexpr double e
The value of .
Definition: Physics.h:39
virtual void visitOffset(const Offset &)=0
Apply the algorithm to an offset (placement).
void setAperture(const ApertureType &type, const std::vector< double > &args)
Definition: ElementBase.h:519
Interface for a single beam element.
Definition: Component.h:50
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
Definition: Offset.cpp:85
Vector_t getEndPosition() const
Definition: Offset.cpp:101
A 3-dimension vector.
Definition: Vector3D.h:31
static Offset globalCartesianOffset(const std::string &name, Vector_t end_position, Vector_t end_direction)
Definition: Offset.cpp:296
Vector_t _end_direction
Definition: Offset.h:205
const Vector3D & getVector() const
Get displacement.
Definition: Euclid3D.cpp:59