3// The very base class for beam line representation objects. A beam line
4// is modelled as a composite structure having a single root object
5// (the top level beam line), which contains both ``single'' leaf-type
6// elements (Components), as well as sub-lines (composites).
8// Interface for basic beam line object.
9// This class defines the abstract interface for all objects which can be
10// contained in a beam line. ElementBase forms the base class for two distinct
11// but related hierarchies of objects:
14// A set of concrete accelerator element classes, which compose the standard
15// accelerator component library (SACL).
18// Instances of the concrete classes for single elements are by default
19// sharable. Instances of beam lines and integrators are by
20// default non-sharable, but they may be made sharable by a call to
21// [b]makeSharable()[/b].
23// An ElementBase object can return two lengths, which may be different:
26// The arc length along the geometry.
28// The design length, often measured along a straight line.
30// Class ElementBase contains a map of name versus value for user-defined
31// attributes (see file AbsBeamline/AttributeSet.hh). The map is primarily
32// intended for processes that require algorithm-specific data in the
35// The class ElementBase has as base class the abstract class RCObject.
36// Virtual derivation is used to make multiple inheritance possible for
37// derived concrete classes. ElementBase implements three copy modes:
40// Copy by reference: Call RCObject::addReference() and use [b]this[/b].
42// Copy structure: use ElementBase::copyStructure().
43// During copying of the structure, all sharable items are re-used, while
44// all non-sharable ones are cloned.
46// Copy by cloning: use ElementBase::clone().
47// This returns a full deep copy.
50// Copyright (c) 200x - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
53// This file is part of OPAL.
55// OPAL is free software: you can redistribute it and/or modify
56// it under the terms of the GNU General Public License as published by
57// the Free Software Foundation, either version 3 of the License, or
58// (at your option) any later version.
60// You should have received a copy of the GNU General Public License
61// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
63#ifndef CLASSIC_ElementBase_HH
64#define CLASSIC_ElementBase_HH
66#include "AbsBeamline/AttributeSet.h"
67#include "Algorithms/CoordinateSystemTrafo.h"
68#include "Algorithms/Quaternion.hpp"
69#include "BeamlineGeometry/Euclid3D.h"
70#include "BeamlineGeometry/Geometry.h"
71#include "MemoryManagement/RCObject.h"
72#include "Structure/BoundingBox.h"
73#include "Utilities/GeneralClassicException.h"
75#include <boost/optional.hpp>
82class BoundaryGeometry;
85class ParticleMatterInteractionHandler;
88enum class ElementType : unsigned short {
107enum class ApertureType : unsigned short {
114class ElementBase : public RCObject {
116 /// Constructor with given name.
117 explicit ElementBase(const std::string& name);
120 ElementBase(const ElementBase&);
121 virtual ~ElementBase();
123 /// Get element name.
124 virtual const std::string& getName() const;
126 /// Set element name.
127 virtual void setName(const std::string& name);
129 /// Get element type std::string.
130 virtual ElementType getType() const = 0;
132 std::string getTypeString() const;
133 static std::string getTypeString(ElementType type);
136 // Return the element geometry.
137 // Version for non-constant object.
138 virtual BGeometryBase& getGeometry() = 0;
141 // Return the element geometry
142 // Version for constant object.
143 virtual const BGeometryBase& getGeometry() const = 0;
146 // Return the entire arc length measured along the design orbit
147 virtual double getArcLength() const;
149 /// Get design length.
150 // Return the design length defined by the geometry.
151 // This may be the arc length or the straight length.
152 virtual double getElementLength() const;
154 /// Set design length.
155 // Set the design length defined by the geometry.
156 // This may be the arc length or the straight length.
157 virtual void setElementLength(double length);
159 virtual void getElementDimensions(double& begin, double& end) const {
161 end = getElementLength();
164 /// Get origin position.
165 // Return the arc length from the entrance to the origin of the element
167 virtual double getOrigin() const;
169 /// Get entrance position.
170 // Return the arc length from the origin to the entrance of the element
172 virtual double getEntrance() const;
174 /// Get exit position.
175 // Return the arc length from the origin to the exit of the element
177 virtual double getExit() const;
180 // Return the transform of the local coordinate system from the
181 // position [b]fromS[/b] to the position [b]toS[/b].
182 virtual Euclid3D getTransform(double fromS, double toS) const;
185 // Equivalent to getTransform(0.0, s).
186 // Return the transform of the local coordinate system from the
187 // origin and [b]s[/b].
188 virtual Euclid3D getTransform(double s) const;
191 // Equivalent to getTransform(getEntrance(), getExit()).
192 // Return the transform of the local coordinate system from the
193 // entrance to the exit of the element.
194 virtual Euclid3D getTotalTransform() const;
197 // Equivalent to getTransform(0.0, getEntrance()).
198 // Return the transform of the local coordinate system from the
199 // origin to the entrance of the element.
200 virtual Euclid3D getEntranceFrame() const;
203 // Equivalent to getTransform(0.0, getExit()).
204 // Return the transform of the local coordinate system from the
205 // origin to the exit of the element.
206 virtual Euclid3D getExitFrame() const;
209 // Returns the entrance patch (transformation) which is used to transform
210 // the global geometry to the local geometry for a misaligned element
211 // at its entrance. The default behaviour returns identity transformation.
212 // This function should be overridden by derived concrete classes which
213 // model complex geometries.
214 virtual Euclid3D getEntrancePatch() const;
217 // Returns the entrance patch (transformation) which is used to transform
218 // the local geometry to the global geometry for a misaligned element
219 // at its exit. The default behaviour returns identity transformation.
220 // This function should be overridden by derived concrete classes which
221 // model complex geometries.
222 virtual Euclid3D getExitPatch() const;
224 /// Get attribute value.
225 // If the attribute does not exist, return zero.
226 virtual double getAttribute(const std::string& aKey) const;
228 /// Test for existence of an attribute.
229 // If the attribute exists, return true, otherwise false.
230 virtual bool hasAttribute(const std::string& aKey) const;
232 /// Remove an existing attribute.
233 virtual void removeAttribute(const std::string& aKey);
235 /// Set value of an attribute.
236 virtual void setAttribute(const std::string& aKey, double val);
238 /// Construct a read/write channel.
239 // This method constructs a Channel permitting read/write access to
240 // the attribute [b]aKey[/b] and returns it.
241 // If the attribute does not exist, it returns nullptr.
242 virtual Channel* getChannel(const std::string& aKey, bool create = false);
244 /// Construct a read-only channel.
245 // This method constructs a Channel permitting read-only access to
246 // the attribute [b]aKey[/b] and returns it.
247 // If the attribute does not exist, it returns nullptr.
248 virtual const ConstChannel* getConstChannel(const std::string& aKey) const;
251 // This method must be overridden by derived classes. It should call the
252 // method of the visitor corresponding to the element class.
253 // If any error occurs, this method throws an exception.
254 virtual void accept(BeamlineVisitor& visitor) const = 0;
257 // Return an identical deep copy of the element.
258 virtual ElementBase* clone() const = 0;
260 /// Make a structural copy.
261 // Return a fresh copy of any beam line structure is made,
262 // but sharable elements remain shared.
263 virtual ElementBase* copyStructure();
265 /// Test if the element can be shared.
266 bool isSharable() const;
268 /// Set sharable flag.
269 // The whole structure depending on [b]this[/b] is marked as sharable.
270 // After this call a [b]copyStructure()[/b] call reuses the element.
271 virtual void makeSharable();
274 // This method stores all attributes contained in the AttributeSet to
275 // "*this". The return value [b]true[/b] indicates success.
276 bool update(const AttributeSet&);
278 ///@{ Access to ELEMEDGE attribute
279 void setElementPosition(double elemedge);
280 double getElementPosition() const;
281 bool isElementPositionSet() const;
283 /// attach a boundary geometry field to the element
284 virtual void setBoundaryGeometry(BoundaryGeometry* geo);
286 /// return the attached boundary geometrt object if there is any
287 virtual BoundaryGeometry* getBoundaryGeometry() const;
289 virtual bool hasBoundaryGeometry() const;
291 /// attach a wake field to the element
292 virtual void setWake(WakeFunction* wf);
294 /// return the attached wake object if there is any
295 virtual WakeFunction* getWake() const;
297 virtual bool hasWake() const;
299 virtual void setParticleMatterInteraction(ParticleMatterInteractionHandler* spys);
301 virtual ParticleMatterInteractionHandler* getParticleMatterInteraction() const;
303 virtual bool hasParticleMatterInteraction() const;
305 void setCSTrafoGlobal2Local(const CoordinateSystemTrafo& ori);
306 CoordinateSystemTrafo getCSTrafoGlobal2Local() const;
307 void releasePosition();
309 bool isPositioned() const;
311 virtual CoordinateSystemTrafo getEdgeToBegin() const;
312 virtual CoordinateSystemTrafo getEdgeToEnd() const;
314 void setAperture(const ApertureType& type, const std::vector<double>& args);
315 std::pair<ApertureType, std::vector<double> > getAperture() const;
317 virtual bool isInside(const Vector_t<double, 3>& r) const;
319 void setMisalignment(const CoordinateSystemTrafo& cst);
321 void getMisalignment(double& x, double& y, double& s) const;
322 CoordinateSystemTrafo getMisalignment() const;
324 void setActionRange(const std::queue<std::pair<double, double> >& range);
325 void setCurrentSCoordinate(double s);
327 /// Set rotation about z axis in bend frame.
328 void setRotationAboutZ(double rotation);
329 double getRotationAboutZ() const;
331 virtual BoundingBox getBoundingBoxInLabCoords() const;
333 virtual int getRequiredNumberOfTimeSteps() const;
335 /// Set output filename
336 void setOutputFN(std::string fn);
337 /// Get output filename
338 std::string getOutputFN() const;
340 void setFlagDeleteOnTransverseExit(bool = true);
341 bool getFlagDeleteOnTransverseExit() const;
344 bool isInsideTransverse(const Vector_t<double, 3>& r) const;
347 // If this flag is true, the element is always shared.
348 mutable bool shareFlag;
350 CoordinateSystemTrafo csTrafoGlobal2Local_m;
351 CoordinateSystemTrafo misalignment_m;
353 std::pair<ApertureType, std::vector<double> > aperture_m;
355 double elementEdge_m;
357 double rotationZAxis_m;
361 void operator=(const ElementBase&);
363 // The element's name
364 std::string elementID;
366 static const std::map<ElementType, std::string> elementTypeToString_s;
368 // The user-defined set of attributes.
369 AttributeSet userAttribs;
371 WakeFunction* wake_m;
373 BoundaryGeometry* bgeometry_m;
375 ParticleMatterInteractionHandler* parmatint_m;
377 bool positionIsFixed;
378 ///@{ ELEMEDGE attribute
379 double elementPosition_m;
382 std::queue<std::pair<double, double> > actionRange_m;
384 std::string outputfn_m; /**< The name of the outputfile*/
386 bool deleteOnTransverseExit_m = true;
390// ------------------------------------------------------------------------
392inline double ElementBase::getArcLength() const {
393 return getGeometry().getArcLength();
396inline double ElementBase::getElementLength() const {
397 return getGeometry().getElementLength();
400inline void ElementBase::setElementLength(double length) {
401 getGeometry().setElementLength(length);
404inline double ElementBase::getOrigin() const {
405 return getGeometry().getOrigin();
408inline double ElementBase::getEntrance() const {
409 return getGeometry().getEntrance();
412inline double ElementBase::getExit() const {
413 return getGeometry().getExit();
416inline Euclid3D ElementBase::getTransform(double fromS, double toS) const {
417 return getGeometry().getTransform(fromS, toS);
420inline Euclid3D ElementBase::getTotalTransform() const {
421 return getGeometry().getTotalTransform();
424inline Euclid3D ElementBase::getTransform(double s) const {
425 return getGeometry().getTransform(s);
428inline Euclid3D ElementBase::getEntranceFrame() const {
429 return getGeometry().getEntranceFrame();
432inline Euclid3D ElementBase::getExitFrame() const {
433 return getGeometry().getExitFrame();
436inline Euclid3D ElementBase::getEntrancePatch() const {
437 return getGeometry().getEntrancePatch();
440inline Euclid3D ElementBase::getExitPatch() const {
441 return getGeometry().getExitPatch();
444inline bool ElementBase::isSharable() const {
448inline WakeFunction* ElementBase::getWake() const {
452inline bool ElementBase::hasWake() const {
453 return wake_m != nullptr;
456inline BoundaryGeometry* ElementBase::getBoundaryGeometry() const {
460inline bool ElementBase::hasBoundaryGeometry() const {
461 return bgeometry_m != nullptr;
464inline ParticleMatterInteractionHandler* ElementBase::getParticleMatterInteraction() const {
468inline bool ElementBase::hasParticleMatterInteraction() const {
469 return parmatint_m != nullptr;
472inline void ElementBase::setCSTrafoGlobal2Local(const CoordinateSystemTrafo& trafo) {
476 csTrafoGlobal2Local_m = trafo;
479inline CoordinateSystemTrafo ElementBase::getCSTrafoGlobal2Local() const {
480 return csTrafoGlobal2Local_m;
483inline CoordinateSystemTrafo ElementBase::getEdgeToBegin() const {
484 CoordinateSystemTrafo ret(Vector_t<double, 3>({0, 0, 0}), Quaternion(1, 0, 0, 0));
488inline CoordinateSystemTrafo ElementBase::getEdgeToEnd() const {
489 CoordinateSystemTrafo ret(
490 Vector_t<double, 3>({0, 0, getElementLength()}), Quaternion(1, 0, 0, 0));
495inline void ElementBase::setAperture(const ApertureType& type, const std::vector<double>& args) {
496 aperture_m.first = type;
497 aperture_m.second = args;
500inline std::pair<ApertureType, std::vector<double> > ElementBase::getAperture() const {
504inline bool ElementBase::isInside(const Vector_t<double, 3>& r) const {
505 const double length = getElementLength();
506 return r(2) >= 0.0 && r(2) < length && isInsideTransverse(r);
509inline void ElementBase::setMisalignment(const CoordinateSystemTrafo& cst) {
510 misalignment_m = cst;
513inline CoordinateSystemTrafo ElementBase::getMisalignment() const {
514 return misalignment_m;
517inline void ElementBase::releasePosition() {
518 positionIsFixed = false;
521inline void ElementBase::fixPosition() {
522 positionIsFixed = true;
525inline bool ElementBase::isPositioned() const {
526 return positionIsFixed;
529inline void ElementBase::setActionRange(const std::queue<std::pair<double, double> >& range) {
530 actionRange_m = range;
532 if (!actionRange_m.empty())
533 elementEdge_m = actionRange_m.front().first;
536inline void ElementBase::setRotationAboutZ(double rotation) {
537 rotationZAxis_m = rotation;
540inline double ElementBase::getRotationAboutZ() const {
541 return rotationZAxis_m;
544inline std::string ElementBase::getTypeString() const {
545 return getTypeString(getType());
548inline void ElementBase::setElementPosition(double elemedge) {
549 elementPosition_m = elemedge;
550 elemedgeSet_m = true;
553inline double ElementBase::getElementPosition() const {
555 return elementPosition_m;
557 throw GeneralClassicException(
558 "ElementBase::getElementPosition()",
559 std::string("ELEMEDGE for \"") + getName() + "\" not set");
562inline bool ElementBase::isElementPositionSet() const {
563 return elemedgeSet_m;
566inline int ElementBase::getRequiredNumberOfTimeSteps() const {
570inline void ElementBase::setFlagDeleteOnTransverseExit(bool flag) {
571 deleteOnTransverseExit_m = flag;
574inline bool ElementBase::getFlagDeleteOnTransverseExit() const {
575 return deleteOnTransverseExit_m;
578#endif // CLASSIC_ElementBase_HH