// // Class ElementBase // The very base class for beam line representation objects. A beam line // is modelled as a composite structure having a single root object // (the top level beam line), which contains both ``single'' leaf-type // elements (Components), as well as sub-lines (composites). // // Interface for basic beam line object. // This class defines the abstract interface for all objects which can be // contained in a beam line. ElementBase forms the base class for two distinct // but related hierarchies of objects: // [OL] // [LI] // A set of concrete accelerator element classes, which compose the standard // accelerator component library (SACL). // [LI] // [/OL] // Instances of the concrete classes for single elements are by default // sharable. Instances of beam lines and integrators are by // default non-sharable, but they may be made sharable by a call to // [b]makeSharable()[/b]. // [p] // An ElementBase object can return two lengths, which may be different: // [OL] // [LI] // The arc length along the geometry. // [LI] // The design length, often measured along a straight line. // [/OL] // Class ElementBase contains a map of name versus value for user-defined // attributes (see file AbsBeamline/AttributeSet.hh). The map is primarily // intended for processes that require algorithm-specific data in the // accelerator model. // [P] // The class ElementBase has as base class the abstract class RCObject. // Virtual derivation is used to make multiple inheritance possible for // derived concrete classes. ElementBase implements three copy modes: // [OL] // [LI] // Copy by reference: Call RCObject::addReference() and use [b]this[/b]. // [LI] // Copy structure: use ElementBase::copyStructure(). // During copying of the structure, all sharable items are re-used, while // all non-sharable ones are cloned. // [LI] // Copy by cloning: use ElementBase::clone(). // This returns a full deep copy. // [/OL] // // Copyright (c) 200x - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland // All rights reserved // // This file is part of OPAL. // // OPAL is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // You should have received a copy of the GNU General Public License // along with OPAL. If not, see . // #ifndef CLASSIC_ElementBase_HH #define CLASSIC_ElementBase_HH #include "AbsBeamline/AttributeSet.h" #include "BeamlineGeometry/Geometry.h" #include "MemoryManagement/RCObject.h" #include "Algorithms/Vektor.h" #include "Algorithms/Quaternion.h" #include "Algorithms/CoordinateSystemTrafo.h" #include "Utilities/GeneralClassicException.h" #include #include #include class BeamlineVisitor; class BoundaryGeometry; class Channel; class ConstChannel; class ElementImage; class ParticleMatterInteractionHandler; class WakeFunction; class ElementBase: public RCObject { public: /// Constructor with given name. explicit ElementBase(const std::string &name); ElementBase(); ElementBase(const ElementBase &); virtual ~ElementBase(); /// Get element name. virtual const std::string &getName() const; /// Set element name. virtual void setName(const std::string &name); enum ApertureType {RECTANGULAR , ELLIPTICAL , CONIC_RECTANGULAR , CONIC_ELLIPTICAL }; enum ElementType {BEAMBEAM , BEAMLINE , BEAMSTRIPPING , CCOLLIMATOR , CORRECTOR , CYCLOTRON , DEGRADER , DIAGNOSTIC , DRIFT , FLEXIBLECOLLIMATOR , INTEGRATOR , LAMBERTSON , MARKER , MONITOR , MPSPLITINTEGRATOR , MULTIPOLE , MULTIPOLET , OFFSET , PARALLELPLATE , PATCH , PROBE , RBEND , RBEND3D , RFCAVITY , RFQUADRUPOLE , RING , SBEND3D , SBEND , SEPARATOR , SEPTUM , SOLENOID , SOURCE , STRIPPER , TRAVELINGWAVE , VARIABLERFCAVITY , ANY}; /// Get element type std::string. virtual ElementType getType() const = 0; std::string getTypeString() const; static std::string getTypeString(ElementType type); /// Get geometry. // Return the element geometry. // Version for non-constant object. virtual BGeometryBase &getGeometry() = 0; /// Get geometry. // Return the element geometry // Version for constant object. virtual const BGeometryBase &getGeometry() const = 0; /// Get arc length. // Return the entire arc length measured along the design orbit virtual double getArcLength() const; /// Get design length. // Return the design length defined by the geometry. // This may be the arc length or the straight length. virtual double getElementLength() const; /// Set design length. // Set the design length defined by the geometry. // This may be the arc length or the straight length. virtual void setElementLength(double length); virtual void getElementDimensions(double &begin, double &end) const { begin = 0.0; end = getElementLength(); } /// Get origin position. // Return the arc length from the entrance to the origin of the element // (origin >= 0) virtual double getOrigin() const; /// Get entrance position. // Return the arc length from the origin to the entrance of the element // (entrance <= 0) virtual double getEntrance() const; /// Get exit position. // Return the arc length from the origin to the exit of the element // (exit >= 0) virtual double getExit() const; /// Get transform. // Return the transform of the local coordinate system from the // position [b]fromS[/b] to the position [b]toS[/b]. virtual Euclid3D getTransform(double fromS, double toS) const; /// Get transform. // Equivalent to getTransform(0.0, s). // Return the transform of the local coordinate system from the // origin and [b]s[/b]. virtual Euclid3D getTransform(double s) const; /// Get transform. // Equivalent to getTransform(getEntrance(), getExit()). // Return the transform of the local coordinate system from the // entrance to the exit of the element. virtual Euclid3D getTotalTransform() const; /// Get transform. // Equivalent to getTransform(0.0, getEntrance()). // Return the transform of the local coordinate system from the // origin to the entrance of the element. virtual Euclid3D getEntranceFrame() const; /// Get transform. // Equivalent to getTransform(0.0, getExit()). // Return the transform of the local coordinate system from the // origin to the exit of the element. virtual Euclid3D getExitFrame() const; /// Get patch. // Returns the entrance patch (transformation) which is used to transform // the global geometry to the local geometry for a misaligned element // at its entrance. The default behaviour returns identity transformation. // This function should be overridden by derived concrete classes which // model complex geometries. virtual Euclid3D getEntrancePatch() const; /// Get patch. // Returns the entrance patch (transformation) which is used to transform // the local geometry to the global geometry for a misaligned element // at its exit. The default behaviour returns identity transformation. // This function should be overridden by derived concrete classes which // model complex geometries. virtual Euclid3D getExitPatch() const; /// Get attribute value. // If the attribute does not exist, return zero. virtual double getAttribute(const std::string &aKey) const; /// Test for existence of an attribute. // If the attribute exists, return true, otherwise false. virtual bool hasAttribute(const std::string &aKey) const; /// Remove an existing attribute. virtual void removeAttribute(const std::string &aKey); /// Set value of an attribute. virtual void setAttribute(const std::string &aKey, double val); /// Construct a read/write channel. // This method constructs a Channel permitting read/write access to // the attribute [b]aKey[/b] and returns it. // If the attribute does not exist, it returns NULL. virtual Channel *getChannel(const std::string &aKey, bool create = false); /// Construct a read-only channel. // This method constructs a Channel permitting read-only access to // the attribute [b]aKey[/b] and returns it. // If the attribute does not exist, it returns NULL. virtual const ConstChannel *getConstChannel(const std::string &aKey) const; /// Construct an image. // Return the image of the element, containing the name and type std::string // of the element, and a copy of the user-defined attributes. virtual ElementImage *getImage() const; /// Apply visitor. // This method must be overridden by derived classes. It should call the // method of the visitor corresponding to the element class. // If any error occurs, this method throws an exception. virtual void accept(BeamlineVisitor &visitor) const = 0; /// Return clone. // Return an identical deep copy of the element. virtual ElementBase *clone() const = 0; /// Make a structural copy. // Return a fresh copy of any beam line structure is made, // but sharable elements remain shared. virtual ElementBase *copyStructure(); /// Test if the element can be shared. bool isSharable() const; /// Set sharable flag. // The whole structure depending on [b]this[/b] is marked as sharable. // After this call a [b]copyStructure()[/b] call reuses the element. virtual void makeSharable(); /// Update element. // This method stores all attributes contained in the AttributeSet to // "*this". The return value [b]true[/b] indicates success. bool update(const AttributeSet &); ///@{ Access to ELEMEDGE attribute void setElementPosition(double elemedge); double getElementPosition() const; bool isElementPositionSet() const; ///@} /// attach a boundary geometry field to the element virtual void setBoundaryGeometry(BoundaryGeometry *geo); /// return the attached boundary geometrt object if there is any virtual BoundaryGeometry *getBoundaryGeometry() const; virtual bool hasBoundaryGeometry() const; /// attach a wake field to the element virtual void setWake(WakeFunction *wf); /// return the attached wake object if there is any virtual WakeFunction *getWake() const; virtual bool hasWake() const; virtual void setParticleMatterInteraction(ParticleMatterInteractionHandler *spys); virtual ParticleMatterInteractionHandler *getParticleMatterInteraction() const; virtual bool hasParticleMatterInteraction() const; void setCSTrafoGlobal2Local(const CoordinateSystemTrafo &ori); CoordinateSystemTrafo getCSTrafoGlobal2Local() const; void releasePosition(); void fixPosition(); bool isPositioned() const; virtual CoordinateSystemTrafo getEdgeToBegin() const; virtual CoordinateSystemTrafo getEdgeToEnd() const; void setAperture(const ApertureType& type, const std::vector &args); std::pair > getAperture() const; virtual bool isInside(const Vector_t &r) const; void setMisalignment(double x, double y, double s); void setMisalignment(const CoordinateSystemTrafo &cst); void getMisalignment(double &x, double &y, double &s) const; CoordinateSystemTrafo getMisalignment() const; void setActionRange(const std::queue > &range); void setCurrentSCoordinate(double s); /// Set rotation about z axis in bend frame. void setRotationAboutZ(double rotation); double getRotationAboutZ() const; struct BoundingBox { Vector_t lowerLeftCorner; Vector_t upperRightCorner; void getCombinedBoundingBox(const BoundingBox & other) { for (unsigned int d = 0; d < 3; ++ d) { lowerLeftCorner[d] = std::min(lowerLeftCorner[d], other.lowerLeftCorner[d]); upperRightCorner[d] = std::max(upperRightCorner[d], other.upperRightCorner[d]); } } bool isInside(const Vector_t &) const; /*! Computes the intersection point between a bounding box and the ray which * has the direction 'direction' and starts at the position 'position'. If * the position is inside the box then the algorithm should find an inter- * section point. * * @param position the position where the ray starts * @param direction the direction of the ray */ boost::optional getPointOfIntersection(const Vector_t & position, const Vector_t & direction) const; }; virtual BoundingBox getBoundingBoxInLabCoords() const; protected: bool isInsideTransverse(const Vector_t &r) const; // Sharable flag. // If this flag is true, the element is always shared. mutable bool shareFlag; CoordinateSystemTrafo csTrafoGlobal2Local_m; CoordinateSystemTrafo misalignment_m; std::pair > aperture_m; double elementEdge_m; double rotationZAxis_m; private: // Not implemented. void operator=(const ElementBase &); // The element's name std::string elementID; // The user-defined set of attributes. AttributeSet userAttribs; WakeFunction *wake_m; BoundaryGeometry *bgeometry_m; ParticleMatterInteractionHandler *parmatint_m; bool positionIsFixed; ///@{ ELEMEDGE attribute double elementPosition_m; bool elemedgeSet_m; ///@} std::queue > actionRange_m; }; // Inline functions. // ------------------------------------------------------------------------ inline double ElementBase::getArcLength() const { return getGeometry().getArcLength(); } inline double ElementBase::getElementLength() const { return getGeometry().getElementLength(); } inline void ElementBase::setElementLength(double length) { getGeometry().setElementLength(length); } inline double ElementBase::getOrigin() const { return getGeometry().getOrigin(); } inline double ElementBase::getEntrance() const { return getGeometry().getEntrance(); } inline double ElementBase::getExit() const { return getGeometry().getExit(); } inline Euclid3D ElementBase::getTransform(double fromS, double toS) const { return getGeometry().getTransform(fromS, toS); } inline Euclid3D ElementBase::getTotalTransform() const { return getGeometry().getTotalTransform(); } inline Euclid3D ElementBase::getTransform(double s) const { return getGeometry().getTransform(s); } inline Euclid3D ElementBase::getEntranceFrame() const { return getGeometry().getEntranceFrame(); } inline Euclid3D ElementBase::getExitFrame() const { return getGeometry().getExitFrame(); } inline Euclid3D ElementBase::getEntrancePatch() const { return getGeometry().getEntrancePatch(); } inline Euclid3D ElementBase::getExitPatch() const { return getGeometry().getExitPatch(); } inline bool ElementBase::isSharable() const { return shareFlag; } inline WakeFunction *ElementBase::getWake() const { return wake_m; } inline bool ElementBase::hasWake() const { return wake_m != NULL; } inline BoundaryGeometry *ElementBase::getBoundaryGeometry() const { return bgeometry_m; } inline bool ElementBase::hasBoundaryGeometry() const { return bgeometry_m != NULL; } inline ParticleMatterInteractionHandler *ElementBase::getParticleMatterInteraction() const { return parmatint_m; } inline bool ElementBase::hasParticleMatterInteraction() const { return parmatint_m != NULL; } inline void ElementBase::setCSTrafoGlobal2Local(const CoordinateSystemTrafo &trafo) { if (positionIsFixed) return; csTrafoGlobal2Local_m = trafo; } inline CoordinateSystemTrafo ElementBase::getCSTrafoGlobal2Local() const { return csTrafoGlobal2Local_m; } inline CoordinateSystemTrafo ElementBase::getEdgeToBegin() const { CoordinateSystemTrafo ret(Vector_t(0, 0, 0), Quaternion(1, 0, 0, 0)); return ret; } inline CoordinateSystemTrafo ElementBase::getEdgeToEnd() const { CoordinateSystemTrafo ret(Vector_t(0, 0, getElementLength()), Quaternion(1, 0, 0, 0)); return ret; } inline void ElementBase::setAperture(const ApertureType& type, const std::vector &args) { aperture_m.first = type; aperture_m.second = args; } inline std::pair > ElementBase::getAperture() const { return aperture_m; } inline bool ElementBase::isInside(const Vector_t &r) const { const double length = getElementLength(); return r(2) >= 0.0 && r(2) < length && isInsideTransverse(r); } inline void ElementBase::setMisalignment(const CoordinateSystemTrafo &cst) { misalignment_m = cst; } inline CoordinateSystemTrafo ElementBase::getMisalignment() const { return misalignment_m; } inline void ElementBase::releasePosition() { positionIsFixed = false; } inline void ElementBase::fixPosition() { positionIsFixed = true; } inline bool ElementBase::isPositioned() const { return positionIsFixed; } inline void ElementBase::setActionRange(const std::queue > &range) { actionRange_m = range; if (actionRange_m.size() > 0) elementEdge_m = actionRange_m.front().first; } inline void ElementBase::setRotationAboutZ(double rotation) { rotationZAxis_m = rotation; } inline double ElementBase::getRotationAboutZ() const { return rotationZAxis_m; } inline std::string ElementBase::getTypeString() const { return getTypeString(getType());} inline void ElementBase::setElementPosition(double elemedge) { elementPosition_m = elemedge; elemedgeSet_m = true; } inline double ElementBase::getElementPosition() const { if (elemedgeSet_m) return elementPosition_m; throw GeneralClassicException("ElementBase::getElementPosition()", std::string("ELEMEDGE for \"") + getName() + "\" not set"); } inline bool ElementBase::isElementPositionSet() const { return elemedgeSet_m; } #endif // CLASSIC_ElementBase_HH