ElementBase.h 18.9 KB
Newer Older
gsell's avatar
gsell committed
1
//
2
// Class ElementBase
gsell's avatar
gsell committed
3 4 5 6 7
//   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).
//
8 9 10 11 12 13 14 15 16 17 18
//   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
frey_m's avatar
frey_m committed
19
//   sharable. Instances of beam lines and integrators are by
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
//   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]
gsell's avatar
gsell committed
49
//
frey_m's avatar
frey_m committed
50
// Copyright (c) 200x - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
51
// All rights reserved
gsell's avatar
gsell committed
52
//
53 54 55 56 57 58 59 60 61 62 63
// 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 <https://www.gnu.org/licenses/>.
//
#ifndef CLASSIC_ElementBase_HH
64
#define CLASSIC_ElementBase_HH
gsell's avatar
gsell committed
65 66 67 68

#include "AbsBeamline/AttributeSet.h"
#include "BeamlineGeometry/Geometry.h"
#include "MemoryManagement/RCObject.h"
69 70 71
#include "Algorithms/Vektor.h"
#include "Algorithms/Quaternion.h"
#include "Algorithms/CoordinateSystemTrafo.h"
72
#include "Utilities/GeneralClassicException.h"
73

kraus's avatar
kraus committed
74 75
#include <boost/optional.hpp>

gsell's avatar
gsell committed
76
#include <string>
77
#include <queue>
gsell's avatar
gsell committed
78 79

class BeamlineVisitor;
snuverink_j's avatar
snuverink_j committed
80
class BoundaryGeometry;
gsell's avatar
gsell committed
81 82 83
class Channel;
class ConstChannel;
class ElementImage;
kraus's avatar
kraus committed
84

85
class ParticleMatterInteractionHandler;
snuverink_j's avatar
snuverink_j committed
86
class WakeFunction;
gsell's avatar
gsell committed
87 88 89 90 91 92

class ElementBase: public RCObject {

public:

    /// Constructor with given name.
93
    explicit ElementBase(const std::string &name);
gsell's avatar
gsell committed
94 95 96 97 98 99

    ElementBase();
    ElementBase(const ElementBase &);
    virtual ~ElementBase();

    /// Get element name.
100
    virtual const std::string &getName() const;
gsell's avatar
gsell committed
101 102

    /// Set element name.
103
    virtual void setName(const std::string &name);
gsell's avatar
gsell committed
104

105 106 107 108 109
    enum ApertureType {RECTANGULAR
                     , ELLIPTICAL
                     , CONIC_RECTANGULAR
                     , CONIC_ELLIPTICAL
    };
110

111
    enum ElementType {BEAMBEAM
112
                    , BEAMLINE
113
                    , BEAMSTRIPPING
114
                    , CCOLLIMATOR
115 116 117 118
                    , CORRECTOR
                    , CYCLOTRON
                    , DEGRADER
                    , DIAGNOSTIC
frey_m's avatar
frey_m committed
119
                    , DRIFT
120
                    , FLEXIBLECOLLIMATOR
121 122 123 124 125 126
                    , INTEGRATOR
                    , LAMBERTSON
                    , MARKER
                    , MONITOR
                    , MPSPLITINTEGRATOR
                    , MULTIPOLE
ext-rogers_c's avatar
ext-rogers_c committed
127
                    , MULTIPOLET
128 129 130 131 132
                    , OFFSET
                    , PARALLELPLATE
                    , PATCH
                    , PROBE
                    , RBEND
133
                    , RBEND3D
134 135 136 137 138 139 140 141
                    , RFCAVITY
                    , RFQUADRUPOLE
                    , RING
                    , SBEND3D
                    , SBEND
                    , SEPARATOR
                    , SEPTUM
                    , SOLENOID
142
                    , SOURCE
143 144 145 146 147
                    , STRIPPER
                    , TRAVELINGWAVE
                    , VARIABLERFCAVITY
                    , ANY};

148
    /// Get element type std::string.
149 150 151
    virtual ElementType getType() const = 0;

    std::string getTypeString() const;
152
    static std::string getTypeString(ElementType type);
gsell's avatar
gsell committed
153 154 155 156

    /// Get geometry.
    //  Return the element geometry.
    //  Version for non-constant object.
157
    virtual BGeometryBase  &getGeometry() = 0;
gsell's avatar
gsell committed
158 159 160 161

    /// Get geometry.
    //  Return the element geometry
    //  Version for constant object.
162
    virtual const BGeometryBase  &getGeometry() const = 0;
gsell's avatar
gsell committed
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

    /// 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);

178 179 180 181 182 183
    virtual void getElementDimensions(double &begin,
                                      double &end) const {
        begin = 0.0;
        end = getElementLength();
    }

gsell's avatar
gsell committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
    /// 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.
246
    virtual double getAttribute(const std::string &aKey) const;
gsell's avatar
gsell committed
247 248 249

    /// Test for existence of an attribute.
    //  If the attribute exists, return true, otherwise false.
250
    virtual bool hasAttribute(const std::string &aKey) const;
gsell's avatar
gsell committed
251 252

    /// Remove an existing attribute.
253
    virtual void removeAttribute(const std::string &aKey);
gsell's avatar
gsell committed
254 255

    /// Set value of an attribute.
256
    virtual void setAttribute(const std::string &aKey, double val);
gsell's avatar
gsell committed
257 258 259 260 261

    /// 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.
262
    virtual Channel *getChannel(const std::string &aKey, bool create = false);
gsell's avatar
gsell committed
263 264 265 266 267

    /// 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.
268
    virtual const ConstChannel *getConstChannel(const std::string &aKey) const;
gsell's avatar
gsell committed
269 270

    /// Construct an image.
271
    //  Return the image of the element, containing the name and type std::string
gsell's avatar
gsell committed
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
    //  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 &);

snuverink_j's avatar
snuverink_j committed
304
    ///@{ Access to ELEMEDGE attribute
305 306 307
    void setElementPosition(double elemedge);
    double getElementPosition() const;
    bool isElementPositionSet() const;
snuverink_j's avatar
snuverink_j committed
308
    ///@}
gsell's avatar
gsell committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
    /// 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;

326
    virtual void setParticleMatterInteraction(ParticleMatterInteractionHandler *spys);
gsell's avatar
gsell committed
327

328
    virtual ParticleMatterInteractionHandler *getParticleMatterInteraction() const;
gsell's avatar
gsell committed
329

330
    virtual bool hasParticleMatterInteraction() const;
gsell's avatar
gsell committed
331

332 333
    void setCSTrafoGlobal2Local(const CoordinateSystemTrafo &ori);
    CoordinateSystemTrafo getCSTrafoGlobal2Local() const;
334
    void releasePosition();
335
    void fixPosition();
336
    bool isPositioned() const;
337

338 339
    virtual CoordinateSystemTrafo getEdgeToBegin() const;
    virtual CoordinateSystemTrafo getEdgeToEnd() const;
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358

    void setAperture(const ApertureType& type, const std::vector<double> &args);
    std::pair<ElementBase::ApertureType, std::vector<double> > 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<std::pair<double, double> > &range);
    void setCurrentSCoordinate(double s);

    /// Set rotation about z axis in bend frame.
    void setRotationAboutZ(double rotation);
    double getRotationAboutZ() const;

kraus's avatar
kraus committed
359 360 361 362 363 364 365 366 367 368 369 370
    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;
kraus's avatar
kraus committed
371 372 373 374

        /*! 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-
kraus's avatar
kraus committed
375
         *  section point.
kraus's avatar
kraus committed
376 377 378 379
         *
         *  @param position the position where the ray starts
         *  @param direction the direction of the ray
         */
kraus's avatar
kraus committed
380 381 382 383 384
        boost::optional<Vector_t> getPointOfIntersection(const Vector_t & position,
                                                         const Vector_t & direction) const;
    };

    virtual BoundingBox getBoundingBoxInLabCoords() const;
kraus's avatar
kraus committed
385

gsell's avatar
gsell committed
386
protected:
kraus's avatar
kraus committed
387
    bool isInsideTransverse(const Vector_t &r) const;
gsell's avatar
gsell committed
388 389 390 391 392

    // Sharable flag.
    // If this flag is true, the element is always shared.
    mutable bool shareFlag;

393 394 395 396 397 398 399 400 401
    CoordinateSystemTrafo csTrafoGlobal2Local_m;
    CoordinateSystemTrafo misalignment_m;

    std::pair<ApertureType, std::vector<double> > aperture_m;

    double elementEdge_m;

    double rotationZAxis_m;

gsell's avatar
gsell committed
402 403 404 405 406 407
private:

    // Not implemented.
    void operator=(const ElementBase &);

    // The element's name
408
    std::string elementID;
gsell's avatar
gsell committed
409 410 411 412 413 414 415 416

    // The user-defined set of attributes.
    AttributeSet userAttribs;

    WakeFunction *wake_m;

    BoundaryGeometry *bgeometry_m;

417
    ParticleMatterInteractionHandler *parmatint_m;
gsell's avatar
gsell committed
418

419
    bool positionIsFixed;
snuverink_j's avatar
snuverink_j committed
420
    ///@{ ELEMEDGE attribute
421 422
    double elementPosition_m;
    bool elemedgeSet_m;
snuverink_j's avatar
snuverink_j committed
423
    ///@}
424
    std::queue<std::pair<double, double> > actionRange_m;
gsell's avatar
gsell committed
425 426 427 428 429 430
};


// Inline functions.
// ------------------------------------------------------------------------

431 432
inline
double ElementBase::getArcLength() const
gsell's avatar
gsell committed
433 434
{ return getGeometry().getArcLength(); }

435 436
inline
double ElementBase::getElementLength() const
gsell's avatar
gsell committed
437 438
{ return getGeometry().getElementLength(); }

439 440
inline
void ElementBase::setElementLength(double length)
gsell's avatar
gsell committed
441 442
{ getGeometry().setElementLength(length); }

443 444
inline
double ElementBase::getOrigin() const
gsell's avatar
gsell committed
445 446
{ return getGeometry().getOrigin(); }

447 448
inline
double ElementBase::getEntrance() const
gsell's avatar
gsell committed
449 450
{ return getGeometry().getEntrance(); }

451 452
inline
double ElementBase::getExit() const
gsell's avatar
gsell committed
453 454
{ return getGeometry().getExit(); }

455 456
inline
Euclid3D ElementBase::getTransform(double fromS, double toS) const
gsell's avatar
gsell committed
457 458
{ return getGeometry().getTransform(fromS, toS); }

459 460
inline
Euclid3D ElementBase::getTotalTransform() const
gsell's avatar
gsell committed
461 462
{ return getGeometry().getTotalTransform(); }

463 464
inline
Euclid3D ElementBase::getTransform(double s) const
gsell's avatar
gsell committed
465 466
{ return getGeometry().getTransform(s); }

467 468
inline
Euclid3D ElementBase::getEntranceFrame() const
gsell's avatar
gsell committed
469 470
{ return getGeometry().getEntranceFrame(); }

471 472
inline
Euclid3D ElementBase::getExitFrame() const
gsell's avatar
gsell committed
473 474
{ return getGeometry().getExitFrame(); }

475 476
inline
Euclid3D ElementBase::getEntrancePatch() const
gsell's avatar
gsell committed
477 478
{ return getGeometry().getEntrancePatch(); }

479 480
inline
Euclid3D ElementBase::getExitPatch() const
gsell's avatar
gsell committed
481 482
{ return getGeometry().getExitPatch(); }

483 484
inline
bool ElementBase::isSharable() const
gsell's avatar
gsell committed
485 486
{ return shareFlag; }

487 488
inline
WakeFunction *ElementBase::getWake() const
gsell's avatar
gsell committed
489 490
{ return wake_m; }

491 492
inline
bool ElementBase::hasWake() const
gsell's avatar
gsell committed
493 494
{ return wake_m != NULL; }

495 496
inline
BoundaryGeometry *ElementBase::getBoundaryGeometry() const
gsell's avatar
gsell committed
497 498
{ return bgeometry_m; }

499 500
inline
bool ElementBase::hasBoundaryGeometry() const
gsell's avatar
gsell committed
501 502
{ return bgeometry_m != NULL; }

503
inline
504
ParticleMatterInteractionHandler *ElementBase::getParticleMatterInteraction() const
505
{ return parmatint_m; }
gsell's avatar
gsell committed
506

507
inline
508
bool ElementBase::hasParticleMatterInteraction() const
509
{ return parmatint_m != NULL; }
gsell's avatar
gsell committed
510

511 512 513 514 515 516 517 518 519 520 521 522 523
inline
void ElementBase::setCSTrafoGlobal2Local(const CoordinateSystemTrafo &trafo)
{
    if (positionIsFixed) return;

    csTrafoGlobal2Local_m = trafo;
}

inline
CoordinateSystemTrafo ElementBase::getCSTrafoGlobal2Local() const
{ return csTrafoGlobal2Local_m; }

inline
524 525 526 527 528 529 530 531 532 533
CoordinateSystemTrafo ElementBase::getEdgeToBegin() const
{
    CoordinateSystemTrafo ret(Vector_t(0, 0, 0),
                              Quaternion(1, 0, 0, 0));

    return ret;
}

inline
CoordinateSystemTrafo ElementBase::getEdgeToEnd() const
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
{
    CoordinateSystemTrafo ret(Vector_t(0, 0, getElementLength()),
                              Quaternion(1, 0, 0, 0));

    return ret;
}

inline
void ElementBase::setAperture(const ApertureType& type, const std::vector<double> &args)
{
    aperture_m.first = type;
    aperture_m.second = args;
}

inline
std::pair<ElementBase::ApertureType, std::vector<double> > ElementBase::getAperture() const
{
    return aperture_m;
}

inline
bool ElementBase::isInside(const Vector_t &r) const
{
    const double length = getElementLength();
kraus's avatar
kraus committed
558
    return r(2) >= 0.0 && r(2) < length && isInsideTransverse(r);
559 560 561 562 563 564 565 566 567 568 569 570
}

inline
void ElementBase::setMisalignment(const CoordinateSystemTrafo &cst) {
    misalignment_m = cst;
}

inline
CoordinateSystemTrafo ElementBase::getMisalignment() const {
    return misalignment_m;
}

571 572 573 574 575
inline
void ElementBase::releasePosition() {
    positionIsFixed = false;
}

576 577 578 579 580 581
inline
void ElementBase::fixPosition() {
    positionIsFixed = true;
}

inline
582
bool ElementBase::isPositioned() const {
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
    return positionIsFixed;
}

inline
void ElementBase::setActionRange(const std::queue<std::pair<double, double> > &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
606 607
{ return getTypeString(getType());}

608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
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; }

kraus's avatar
kraus committed
627
#endif // CLASSIC_ElementBase_HH