OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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 
37 const double Offset::lengthUnits_m = 1e3;
38 double Offset::float_tolerance = 1e-12;
39 
40 Offset::Offset(const std::string& name)
41  : Component(name), _is_local(false), geometry_m(NULL) {
43 }
44 
46  : Offset("")
47 {}
48 
49 Offset::Offset(std::string name, const Offset& rhs)
50  : Component(name), _is_local(false), geometry_m(NULL) {
51  *this = rhs;
52  setName(name);
53 }
54 
56  : Component(rhs.getName()), _is_local(false), geometry_m(NULL) {
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 != NULL)
74  delete geometry_m;
75  if (rhs.geometry_m == NULL) {
76  geometry_m = NULL;
77  } else {
79  }
80  setAperture(rhs.getAperture().first, rhs.getAperture().second);
81  return *this;
82 }
83 
84 void Offset::accept(BeamlineVisitor & visitor) const {
85  visitor.visitOffset(*this);
86 }
87 
89  throw GeneralClassicException("Offset::getField()",
90  "No field defined for Offset");
91 }
92 
93 const EMField &Offset::getField() const {
94  throw GeneralClassicException("Offset::getField() const",
95  "No field defined for Offset");
96 }
97 
98 void Offset::initialise(PartBunchBase<double, 3> *bunch, double &/*startField*/, double &/*endField*/) {
99  RefPartBunch_m = bunch;
100 }
101 
103  RefPartBunch_m = NULL;
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 
126 void Offset::setIsLocal(bool isLocal) {
127  _is_local = isLocal;
128 }
129 
130 bool 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 
147 double Offset::getTheta(Vector_t vec1, Vector_t vec2) {
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 != NULL)
179  delete geometry_m;
180  geometry_m = new Euclid3DGeometry(euclid3D);
181 }
182 
183 void 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);
188  _end_direction = rotate(_end_direction, theta_g2l);
189  _is_local = true;
190  }
191  updateGeometry();
192 }
193 
195  return geometry_m != NULL;
196 }
197 
198 bool 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 
223 bool operator!=(const Offset& off1, const Offset& off2) {
224  return !(off1 == off2);
225 }
226 
227 std::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 
234 bool Offset::bends() const {
235  if (geometry_m == NULL) {
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:51
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:194
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:536
std::pair< ElementBase::ApertureType, std::vector< double > > getAperture() const
Definition: ElementBase.h:542
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