Commit b9382db0 authored by ext-rogers_c's avatar ext-rogers_c
Browse files

Variable frequency RF in OpalRing

parent 53390248
......@@ -44,6 +44,8 @@ classic/5.0/src/AbsBeamline/Monitor.cpp -text
classic/5.0/src/AbsBeamline/Monitor.h -text
classic/5.0/src/AbsBeamline/Multipole.cpp -text
classic/5.0/src/AbsBeamline/Multipole.h -text
classic/5.0/src/AbsBeamline/Offset.cpp -text
classic/5.0/src/AbsBeamline/Offset.h -text
classic/5.0/src/AbsBeamline/ParallelPlate.cpp -text
classic/5.0/src/AbsBeamline/ParallelPlate.h -text
classic/5.0/src/AbsBeamline/Patch.cpp -text
......@@ -71,6 +73,8 @@ classic/5.0/src/AbsBeamline/Stripper.cpp -text
classic/5.0/src/AbsBeamline/Stripper.h -text
classic/5.0/src/AbsBeamline/TravelingWave.cpp -text
classic/5.0/src/AbsBeamline/TravelingWave.h -text
classic/5.0/src/AbsBeamline/VariableRFCavity.cpp -text
classic/5.0/src/AbsBeamline/VariableRFCavity.h -text
classic/5.0/src/Algebra/Array1D.h -text
classic/5.0/src/Algebra/Array2D.h -text
classic/5.0/src/Algebra/CMakeLists.txt -text
......@@ -106,6 +110,8 @@ classic/5.0/src/Algebra/VpsInvMap.h -text
classic/5.0/src/Algebra/VpsMap.h -text
classic/5.0/src/Algorithms/AbstractMapper.cpp -text
classic/5.0/src/Algorithms/AbstractMapper.h -text
classic/5.0/src/Algorithms/AbstractTimeDependence.cpp -text
classic/5.0/src/Algorithms/AbstractTimeDependence.h -text
classic/5.0/src/Algorithms/AbstractTracker.cpp -text
classic/5.0/src/Algorithms/AbstractTracker.h -text
classic/5.0/src/Algorithms/CMakeLists.txt -text
......@@ -136,6 +142,8 @@ classic/5.0/src/Algorithms/PartData.h -text
classic/5.0/src/Algorithms/PartPusher.h -text
classic/5.0/src/Algorithms/Particle.cpp -text
classic/5.0/src/Algorithms/Particle.h -text
classic/5.0/src/Algorithms/PolynomialTimeDependence.cpp -text
classic/5.0/src/Algorithms/PolynomialTimeDependence.h -text
classic/5.0/src/Algorithms/Surveyor.cpp -text
classic/5.0/src/Algorithms/Surveyor.h -text
classic/5.0/src/Algorithms/ThinMapper.cpp -text
......@@ -215,6 +223,8 @@ classic/5.0/src/BeamlineCore/YMonitorRep.h -text
classic/5.0/src/BeamlineGeometry/CMakeLists.txt -text
classic/5.0/src/BeamlineGeometry/Euclid3D.cpp -text
classic/5.0/src/BeamlineGeometry/Euclid3D.h -text
classic/5.0/src/BeamlineGeometry/Euclid3DGeometry.cpp -text
classic/5.0/src/BeamlineGeometry/Euclid3DGeometry.h -text
classic/5.0/src/BeamlineGeometry/Geometry.cpp -text
classic/5.0/src/BeamlineGeometry/Geometry.h -text
classic/5.0/src/BeamlineGeometry/Matrix3D.cpp -text
......@@ -743,12 +753,22 @@ src/Elements/OpalMultipole.cpp -text
src/Elements/OpalMultipole.h -text
src/Elements/OpalOctupole.cpp -text
src/Elements/OpalOctupole.h -text
src/Elements/OpalOffset/OpalGlobalCartesianOffset.cpp -text
src/Elements/OpalOffset/OpalGlobalCartesianOffset.h -text
src/Elements/OpalOffset/OpalGlobalCylindricalOffset.cpp -text
src/Elements/OpalOffset/OpalGlobalCylindricalOffset.h -text
src/Elements/OpalOffset/OpalLocalCartesianOffset.cpp -text
src/Elements/OpalOffset/OpalLocalCartesianOffset.h -text
src/Elements/OpalOffset/OpalLocalCylindricalOffset.cpp -text
src/Elements/OpalOffset/OpalLocalCylindricalOffset.h -text
src/Elements/OpalParallelPlate.cpp -text
src/Elements/OpalParallelPlate.h -text
src/Elements/OpalPatch.cpp -text
src/Elements/OpalPatch.h -text
src/Elements/OpalPepperPot.cpp -text
src/Elements/OpalPepperPot.h -text
src/Elements/OpalPolynomialTimeDependence.cpp -text
src/Elements/OpalPolynomialTimeDependence.h -text
src/Elements/OpalProbe.cpp -text
src/Elements/OpalProbe.h -text
src/Elements/OpalQuadrupole.cpp -text
......@@ -786,6 +806,8 @@ src/Elements/OpalVKicker.cpp -text
src/Elements/OpalVKicker.h -text
src/Elements/OpalVMonitor.cpp -text
src/Elements/OpalVMonitor.h -text
src/Elements/OpalVariableRFCavity.cpp -text
src/Elements/OpalVariableRFCavity.h -text
src/Elements/OpalWire.cpp -text
src/Elements/OpalWire.h -text
src/Elements/OpalYRot.cpp -text
......@@ -1113,3 +1135,18 @@ src/config.h.in -text
src/configure.ac -text
src/opal.cpp -text
src/opal.h -text
src/unit_tests/CMakeLists.txt -text
src/unit_tests/Main.cpp -text
src/unit_tests/Makefile -text
src/unit_tests/classic_src/AbsBeamline/OffsetTest.cpp -text
src/unit_tests/classic_src/AbsBeamline/SBend3DTest.cpp -text
src/unit_tests/classic_src/AbsBeamline/SBend3D_map.field -text
src/unit_tests/classic_src/AbsBeamline/VariableRFCavityTest.cpp -text
src/unit_tests/classic_src/Algorithms/PolynomialTimeDependenceTest.cpp -text
src/unit_tests/gtest/bin/install_gtest.bash -text
src/unit_tests/opal_src/Elements/OpalOffsetTest.cpp -text
src/unit_tests/opal_src/Elements/OpalPolynomialTimeDependenceTest.cpp -text
src/unit_tests/opal_src/Elements/OpalRingTest.cpp -text
src/unit_tests/opal_src/Elements/OpalVariableRFCavityTest.cpp -text
src/unit_tests/opal_src/Utilities/MockComponent.h -text
src/unit_tests/opal_src/Utilities/OpalRingSectionTest.cpp -text
......@@ -46,10 +46,12 @@ class Lambertson;
class Marker;
class Monitor;
class Multipole;
class Offset;
class Patch;
class Probe;
class RBend;
class RFCavity;
class VariableRFCavity;
class TravelingWave;
class RFQuadrupole;
class SBend;
......@@ -62,6 +64,7 @@ class ParallelPlate;
class CyclotronValley;
class Stripper;
class OpalRing;
// Integrators.
class Integrator;
class MapIntegrator;
......@@ -128,6 +131,9 @@ public:
/// Apply the algorithm to a Lambertson septum magnet.
virtual void visitLambertson(const Lambertson &) = 0;
/// Apply the algorithm to an Offset (placement).
virtual void visitOffset(const Offset &) = 0;
/// Apply the algorithm to a marker.
virtual void visitMarker(const Marker &) = 0;
......@@ -149,6 +155,9 @@ public:
/// Apply the algorithm to a RF cavity.
virtual void visitRFCavity(const RFCavity &) = 0;
/// Apply the algorithm to a variable RF cavity.
virtual void visitVariableRFCavity(const VariableRFCavity &) = 0;
/// Apply the algorithm to a RF cavity.
virtual void visitTravelingWave(const TravelingWave &) = 0;
......
......@@ -17,10 +17,12 @@ set (_SRCS
Marker.cpp
Monitor.cpp
Multipole.cpp
Offset.cpp
Patch.cpp
Probe.cpp
RBend.cpp
RFCavity.cpp
VariableRFCavity.cpp
TravelingWave.cpp
RFQuadrupole.cpp
SBend.cpp
......
/*
* Copyright (c) 2014, Chris Rogers
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STFC nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "math.h"
#include "Utilities/OpalException.h"
#include "BeamlineGeometry/Euclid3DGeometry.h"
#include "Algorithms/ParallelCyclotronTracker.h"
#include "Elements/OpalRing.h"
#include "AbsBeamline/Offset.h"
double Offset::float_tolerance = 1e-12;
Offset::Offset(const std::string& name)
: Component(name), _is_local(false), geometry_m(NULL) {
geometry_m = new Euclid3DGeometry(Euclid3D());
}
Offset::Offset()
: Component(), _is_local(false), geometry_m(NULL) {
geometry_m = new Euclid3DGeometry(Euclid3D());
}
Offset::Offset(std::string name, const Offset& rhs)
: Component(name), _is_local(false), geometry_m(NULL) {
*this = rhs;
}
Offset::Offset(const Offset& rhs)
: Component(rhs.getName()), _is_local(false), geometry_m(NULL) {
*this = rhs;
}
Offset::~Offset() {
delete geometry_m;
}
Offset& Offset::operator=(const Offset& rhs) {
if (&rhs == this) {
return *this;
}
setName(rhs.getName());
_end_position = rhs._end_position;
_end_direction = rhs._end_direction;
_is_local = rhs._is_local;
if (geometry_m != NULL)
delete geometry_m;
if (rhs.geometry_m == NULL) {
geometry_m = NULL;
} else {
geometry_m = new Euclid3DGeometry(rhs.geometry_m->getTotalTransform());
}
return *this;
}
void Offset::accept(BeamlineVisitor & visitor) const {
visitor.visitOffset(*this);
}
EMField &Offset::getField() {
throw OpalException("Offset::getField()",
"No field defined for Offset");
}
const EMField &Offset::getField() const {
throw OpalException("Offset::getField() const",
"No field defined for Offset");
}
bool Offset::apply(const size_t &i, const double &t,
Vector_t &E, Vector_t &B) {
return false;
}
bool Offset::apply(const size_t &i, const double &t,
double E[], double B[]) {
return false;
}
bool Offset::apply(const Vector_t &R, const Vector_t &centroid,
const double &t, Vector_t &E, Vector_t &B) {
return false;
}
void Offset::initialise(PartBunch *bunch, double &startField, double &endField,
const double &scaleFactor) {
RefPartBunch_m = bunch;
}
void Offset::finalise() {
RefPartBunch_m = NULL;
}
ElementBase* Offset::clone() const {
return new Offset(*this);
}
void Offset::setEndPosition(Vector_t position) {
_end_position = position;
}
Vector_t Offset::getEndPosition() const {
return _end_position;
}
void Offset::setEndDirection(Vector_t direction) {
_end_direction = direction;
}
Vector_t Offset::getEndDirection() const {
return _end_direction;
}
void Offset::setIsLocal(bool isLocal) {
_is_local = isLocal;
}
bool Offset::getIsLocal() const {
return _is_local;
}
Euclid3DGeometry &Offset::getGeometry() {
return *geometry_m;
}
const Euclid3DGeometry &Offset::getGeometry() const {
return *geometry_m;
}
std::ostream& operator<<(std::ostream& out, const Vector_t& vec) {
out << "(" << vec(0) << ", " << vec(1) << ", " << vec(2) << ")";
return out;
}
double Offset::getTheta(Vector_t vec1, Vector_t vec2) {
if (fabs(vec1(2)) > 1e-9 || fabs(vec2(2)) > 1e-9)
throw OpalException("Offset::getTheta(...)",
"Rotations out of midplane are not implemented");
// probably not the most efficient, but only called at set up
double theta = atan2(vec2(1), vec2(0))-atan2(vec1(1), vec1(0));
if (theta < -Physics::pi)
theta += 2.*Physics::pi; // force into domain -pi < theta < pi
return theta;
}
Vector_t Offset::rotate(Vector_t vec, double theta) {
double s = sin(theta);
double c = cos(theta);
return Vector_t(+vec(0)*c-vec(1)*s,
+vec(0)*s+vec(1)*c,
0.);
}
void Offset::updateGeometry() {
if (!_is_local)
throw OpalException("Offset::updateGeometry(...)",
"Global offset needs a local coordinate system");
Vector_t translation = getEndPosition();
double length = sqrt(translation(0)*translation(0)+
translation(1)*translation(1)+
translation(2)*translation(2));
double theta_in = getTheta(Vector_t(1., 0., 0.), translation);
double theta_out = getTheta(Vector_t(1., 0., 0.), getEndDirection());
Euclid3D euclid3D(-sin(theta_in)*length, 0., cos(theta_in)*length,
0., -theta_out, 0.);
if (geometry_m != NULL)
delete geometry_m;
geometry_m = new Euclid3DGeometry(euclid3D);
}
void Offset::updateGeometry(Vector_t startPosition, Vector_t startDirection) {
if (!_is_local) {
Vector_t translationGlobal = _end_position;
double theta_g2l = getTheta(startDirection, Vector_t(1, 0, 0));
_end_position = rotate(translationGlobal, theta_g2l);
_end_direction = rotate(_end_direction, theta_g2l);
_is_local = true;
}
updateGeometry();
}
bool operator==(const Offset& off1, const Offset& off2) {
const double tol = Offset::float_tolerance;
if (off1.getName() != off2.getName() ||
off1.getIsLocal() != off2.getIsLocal()) {
return false;
}
for (int i = 0; i < 3; ++i) {
if (fabs(off1.getEndPosition()(i)-off2.getEndPosition()(i)) > tol ||
fabs(off1.getEndDirection()(i)-off2.getEndDirection()(i)) > tol)
return false;
}
if (&off1.getGeometry() == NULL && &off2.getGeometry() != NULL ||
&off2.getGeometry() == NULL && &off1.getGeometry() != NULL)
return false;
Euclid3D transform1 = off1.getGeometry().getTotalTransform();
Euclid3D transform2 = off2.getGeometry().getTotalTransform();
Vector3D dTranslation = transform1.getVector() - transform2.getVector();
Vector3D dRotation = transform1.getRotation().getAxis() -
transform2.getRotation().getAxis();
for (size_t i = 0; i < 3; ++i)
if (fabs(dTranslation(i)) > tol || fabs(dRotation(i)) > tol)
return false;
return true;
}
bool operator!=(const Offset& off1, const Offset& off2) {
return !(off1 == off2);
}
std::ostream& operator<<(std::ostream& out, const Offset& off) {
out << "Offset " << off.getName() << " local " << off.getIsLocal()
<< " end pos: " << off.getEndPosition()
<< " end dir: " << off.getEndDirection() << std::endl;
}
bool Offset::bends() const {
if (geometry_m == NULL) {
throw OpalException("Offset::bends",
"Try to determine if Offset bends when geometry_m not allocated");
}
Rotation3D rotation = geometry_m->getTotalTransform().getRotation();
for (size_t i = 0; i < 3; ++i)
if (fabs(rotation.getAxis()(i)) > float_tolerance) {
return true;
}
Vector3D vector = geometry_m->getTotalTransform().getVector();
if (fabs(vector(0)) > float_tolerance || fabs(vector(1)) > float_tolerance) {
return true;
}
return false;
}
Offset Offset::localCylindricalOffset(std::string name,
double phi_in,
double phi_out,
double displacement) {
Offset off(name);
off.setEndPosition(Vector_t(cos(phi_in)*displacement,
sin(phi_in)*displacement,
0.));
off.setEndDirection(Vector_t(cos(phi_in+phi_out), sin(phi_in+phi_out), 0.));
off.setIsLocal(true);
off.updateGeometry();
return off;
}
Offset Offset::globalCylindricalOffset(std::string name,
double radius_out,
double phi_out,
double theta_out) {
Offset off(name);
off.setEndPosition(Vector_t(cos(phi_out)*radius_out,
sin(phi_out)*radius_out,
0.));
off.setEndDirection(Vector_t(sin(phi_out+theta_out),
cos(phi_out+theta_out),
0.));
off.setIsLocal(false);
return off;
}
Offset Offset::localCartesianOffset(std::string name,
Vector_t end_position,
Vector_t end_direction) {
Offset off(name);
off.setEndPosition(end_position);
off.setEndDirection(end_direction);
off.setIsLocal(true);
off.updateGeometry();
return off;
}
Offset Offset::globalCartesianOffset(std::string name,
Vector_t end_position,
Vector_t end_direction) {
Offset off(name);
off.setEndPosition(end_position);
off.setEndDirection(end_direction);
off.setIsLocal(false);
return off;
}
/*
* Copyright (c) 2014, Chris Rogers
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STFC nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CLASSIC_ABSBEAMLINE_Offset_HH
#define CLASSIC_ABSBEAMLINE_Offset_HH
#include "Fields/EMField.h"
#include "BeamlineGeometry/Euclid3DGeometry.h"
#include "AbsBeamline/Component.h"
class Fieldmap;
/** @Class Offset
*
* Enables user to define a placement, either in global coordinates or in the
* coordinate system of the previously placed object
*
* @param _end_position final position of the offset
* @param _end_direction normal vector to entry face
* @param _is_local parameter is True if everything is in the coordinate system
* of the last placed object. It is expected that everything will be in a local
* coordinate system before tracking begins (this is expected by, for example,
* OpalRing). This is expected to be set by the visit function in e.g.
* ParallelCyclotronTracker.
* @param geometry the geometry that OpalRingSection uses to do displacements
* This has to be a pointer because SRotatedGeometry
* does not have an defined assignment op. SRotatedGeometry does not have
* a assignment op because BGeometryBase does not have an assignment op...
* and there is no way (I think) to reassign a previously assigned variable
* in C++ without using =
* @param wrappedGeometry Something to do with the reference handling in
* SRotatedGeometry - looks like it doesn't make a copy but holds a reference,
* so unless I keep that alive in Offset I get memory errors (seg fault)
* @float_tolerance bends() and operator==(...) use float_tolerance when
* evaluating equality between doubles.
*/
class Offset : public Component {
public:
/** Constructor sets everything to 0., makes a default geometry with
* everything set to 0.
*/
explicit Offset(const std::string &name);
/** Default constructor sets everything to 0., makes a default geometry
* with everything set to 0.
*/
Offset();
/** Copy constructor; deep copies geometry_m; all other
* stuff is copied as well
*/
Offset(std::string name, const Offset &);
/** Copy constructor; deep copies geometry_m; all other
* stuff is copied as well
*/
Offset(const Offset &);
/** Assignment operator deep copies geometry and wrappedGeometry; all other
* stuff is copied as well
*/
Offset& operator=(const Offset &);
/** Factory method to make an offset in Cylindrical coordinates local to the
* end of the previous element
* - name name of the offset
* - theta_in angle between the previous element and the displacement
* vector
* - theta_out angle between the displacement vector and the next element
* - displacement length of the displacement vector
*/
static Offset localCylindricalOffset(std::string name,
double theta_in,
double theta_out,
double displacement);
/** Factory method to make an offset in global cylindrical polar coordinates
* - name name of the offset
* - radius_out radius of the end of the offset
* - phi_out azimuthal angle of the end of the offset
* - theta_out angle relative to the tangent of the end of the offset
* Call updateGeometry(Vector_t, Vector_t) using the end of the previous
* element before placement; Offset will convert to the local coordinate
* system.
*/
static Offset globalCylindricalOffset(std::string name,
double radius_out,
double phi_out,
double theta_out);
/** Factory method to make an offset in cartesian coordinates local to the
* end of the previous element
* - name name of the offset
* - end_position position of the end of the offset
* - end_direction direction of the end of the offset
*/
static Offset localCartesianOffset(std::string name,
Vector_t end_position,
Vector_t end_direction);
/** Factory method to make an offset in global cartesian coordinates
* - name name of the offset
* - end_position position of the end of the offset
* - end_direction direction of the end of the offset
* Call updateGeometry(Vector_t, Vector_t) using the end of the previous
* element before placement; Offset will convert to the local coordinate
* system.
*/
static Offset globalCartesianOffset(std::string name,
Vector_t end_position,
Vector_t end_direction);
/** deletes geometry and wrappedGeometry */
~Offset();
/** Apply visitor to Offset.
*
* Sets ring radius
*/
void accept(BeamlineVisitor &) const;
/** Just calls the copy constructor on *this */
ElementBase* clone() const;
/** Return false
*
* No bound checking is performed and no field value is calculated as this
* element does not have an associated field or beam pipe aperture.