OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
OpalScalingFFAMagnet.cpp
Go to the documentation of this file.
1//
2// Class OpalScalingFFAMagnet
3// The class provides the user interface for the SCALINGFFAMAGNET object.
4//
5// Copyright (c) 2017 - 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
23#include "Physics/Units.h"
25
27 OpalElement(SIZE, "SCALINGFFAMAGNET",
28 "The \"ScalingFFAMagnet\" element defines a FFA scaling magnet with zero or non-zero spiral angle.") {
29
31 ("B0", "The nominal dipole field of the magnet [T].");
32
34 ("R0", "Radial scale [m].");
35
37 ("FIELD_INDEX", "The scaling magnet field index.");
38
40 ("TAN_DELTA", "Tangent of the spiral angle; set to 0 to make a radial sector magnet.");
41
43 ("MAX_Y_POWER", "The maximum power in y that will be considered in the field expansion.");
44
46 ("END_FIELD_MODEL",
47 "Names the end field model of the magnet, giving the field magnitude along a line of "
48 "constant radius. If blank, uses the 'END_LENGTH' and 'CENTRE_LENGTH' "
49 "parameters and a tanh model. If 'END_FIELD_MODEL' is not blank, Opal will seek "
50 "an END_FIELD_MODEL corresponding to the name defined in this string.");
51
53 ("END_LENGTH", "The end length of the spiral FFA [m].");
54
56 ("HEIGHT",
57 "Full height of the magnet. Particles moving more than height/2. "
58 "off the midplane (either above or below) are out of the aperture [m].");
59
61 ("CENTRE_LENGTH", "The centre length of the spiral FFA [m].");
62
64 ("RADIAL_NEG_EXTENT",
65 "Particles are considered outside the tracking region if "
66 "radius is greater than R0-RADIAL_NEG_EXTENT [m].", 1);
67
69 ("RADIAL_POS_EXTENT",
70 "Particles are considered outside the tracking region if "
71 "radius is greater than R0+RADIAL_POS_EXTENT [m].", 1);
72
74 ("MAGNET_START",
75 "Determines the position of the central portion of the magnet field "
76 "relative to the element start (default is 2*end_length) [m].");
77
79 ("MAGNET_END",
80 "Offset to the end of the magnet, i.e. placement of the next element."
81 "Default is centre_length + 4*end_length.");
82
84 ("AZIMUTHAL_EXTENT",
85 "The field will be assumed zero if particles are more than AZIMUTHAL_EXTENT "
86 "from the magnet centre (psi=0). Default is CENTRE_LENGTH/2.+5.*END_LENGTH [m].");
87
89
90 ScalingFFAMagnet* magnet = new ScalingFFAMagnet("ScalingFFAMagnet");
91 magnet->setEndField(new endfieldmodel::Tanh(1., 1., 1));
92 setElement(magnet);
93}
94
96 OpalScalingFFAMagnet* parent):
97 OpalElement(name, parent) {
99 magnet->setEndField(new endfieldmodel::Tanh(1., 1., 1));
100 setElement(magnet);
101}
102
105
107 return new OpalScalingFFAMagnet(name, this);
108}
109
111 ScalingFFAMagnet* magnet = dynamic_cast<ScalingFFAMagnet*>(getElement());
112 // get centre length and end length in metres
114 double end_length = Attributes::getReal(itsAttr[END_LENGTH]);
115 double centre_length = Attributes::getReal(itsAttr[CENTRE_LENGTH])/2.;
116 endField->setLambda(end_length);
117 // x0 is the distance between B=0.5*B0 and B=B0 i.e. half the centre length
118 endField->setX0(centre_length);
119 std::shared_ptr<endfieldmodel::EndFieldModel> efm(endField);
120 std::string endName = "__opal_internal__" + getOpalName();
122 magnet->setEndFieldName(endName);
123}
124
126 if (!itsAttr[END_FIELD_MODEL]) {
127 return;
128 }
130 ScalingFFAMagnet* magnet = dynamic_cast<ScalingFFAMagnet*>(getElement());
131 magnet->setEndFieldName(name);
132}
133
135 ScalingFFAMagnet* magnet = dynamic_cast<ScalingFFAMagnet*>(getElement());
136
137 // use L = r0*theta; we define the magnet into length for UI but into angles
138 // internally; and use m as external default unit
139 double r0Abs = std::abs(Attributes::getReal(itsAttr[R0]));
140 double r0Signed = Attributes::getReal(itsAttr[R0]);
141 magnet->setR0(r0Signed);
143
144 // dimensionless quantities
147 int maxOrder = std::floor(Attributes::getReal(itsAttr[MAX_Y_POWER]));
148 magnet->setMaxOrder(maxOrder);
149
152 } else {
154 }
155 // internally OpalScalingFFAMagnet uses radians, so we scale all lengths to
156 // radians.
157 magnet->getEndField()->rescale(1/r0Abs);
158
159 // get rmin and rmax bounding box edge
161 throw OpalException("OpalScalingFFAMagnet::update()",
162 "RADIAL_NEG_EXTENT needs to be defined");
163 }
164 double rmin = r0Abs - Attributes::getReal(itsAttr[RADIAL_NEG_EXTENT]);
165
167 throw OpalException("OpalScalingFFAMagnet::update()",
168 "RADIAL_POS_EXTENT needs to be defined");
169 }
170 double rmax = r0Abs + Attributes::getReal(itsAttr[RADIAL_POS_EXTENT]);
171 magnet->setRMin(rmin);
172 magnet->setRMax(rmax);
173
174 Vector_t centre(r0Signed, 0, 0);
175 magnet->setCentre(centre);
176
177 // we store maximum vertical displacement (which is half the height)
178 double height = Attributes::getReal(itsAttr[HEIGHT]);
179 magnet->setVerticalExtent(height/2.);
180 // end of the magnet marks the point at which the next element starts
181 if (itsAttr[MAGNET_END]) {
183 throw OpalException("OpalScalingFFAMagnet::update()",
184 "MAGNET_END must be > 0.0");
185 }
186 double phi_end = Attributes::getReal(itsAttr[MAGNET_END]) / r0Abs;
187 magnet->setPhiEnd(phi_end);
188 } else {
189 magnet->setPhiEnd(-1); // flag for setupEndField
190 }
191
192 // get start of the magnet element in radians
193 // setPhiStart sets the position of the 0 point of the endFieldModel, which
194 // is typically the magnet centre
195 if (itsAttr[MAGNET_START]) {
197 throw OpalException("OpalScalingFFAMagnet::update()",
198 "MAGNET_START must be > 0.0");
199 }
200 double phi_start = Attributes::getReal(itsAttr[MAGNET_START]) / r0Abs;
201 magnet->setPhiStart(phi_start);
202 } else {
203 magnet->setPhiStart(-1); // flag for setupEndField
204 }
205 // get azimuthal extent in radians; this is just the bounding box
208 throw OpalException("OpalScalingFFAMagnet::update()",
209 "AZIMUTHAL_EXTENT must be > 0.0");
210 }
212 } else {
213 magnet->setAzimuthalExtent(-1); // flag for setupEndField
214 }
215 magnet->initialise();
216 setElement(magnet);
217}
const std::string name
double getReal(const Attribute &attr)
Return real value.
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
std::string getString(const Attribute &attr)
Get string value.
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
constexpr double T2kG
Definition Units.h:56
ElementBase * getElement() const
Return the embedded CLASSIC element.
Definition Element.h:120
void setElement(ElementBase *)
Assign new CLASSIC element.
Definition Element.h:125
const std::string & getOpalName() const
Return object name.
Definition Object.cpp:310
std::vector< Attribute > itsAttr
The object attributes.
Definition Object.h:216
virtual void rescale(double scaleFactor)=0
static void setEndFieldModel(std::string name, std::shared_ptr< EndFieldModel > efm)
void setX0(double x0)
Definition Tanh.h:110
void setLambda(double lambda)
Definition Tanh.h:107
void setAzimuthalExtent(double azimuthalExtent)
void setRMin(double rMin)
void setCentre(Vector_t centre)
void setR0(double r0)
void setVerticalExtent(double verticalExtent)
void setTanDelta(double tanDelta)
void setDipoleConstant(double Bz)
void setPhiStart(double phiStart)
void setEndField(endfieldmodel::EndFieldModel *endField)
void setMaxOrder(size_t maxOrder)
void setFieldIndex(double k)
void setRMax(double rMax)
void setEndFieldName(std::string name)
void setPhiEnd(double phiEnd)
endfieldmodel::EndFieldModel * getEndField() const
void initialise(PartBunchBase< double, 3 > *bunch, double &startField, double &endField) override
OpalElement(int size, const char *name, const char *help)
Exemplar constructor.
void registerOwnership() const
virtual OpalScalingFFAMagnet * clone(const std::string &name)
The base class for all OPAL exceptions.
Vektor< double, 3 > Vector_t