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;
84
class ParticleMatterInteractionHandler;
snuverink_j's avatar
snuverink_j committed
85
class WakeFunction;
gsell's avatar
gsell committed
86 87 88 89 90 91

class ElementBase: public RCObject {

public:

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

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

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

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

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

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

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

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

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

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

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

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

gsell's avatar
gsell committed
183 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
    /// 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.
245
    virtual double getAttribute(const std::string &aKey) const;
gsell's avatar
gsell committed
246 247 248

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

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

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

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

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

    /// Construct an image.
270
    //  Return the image of the element, containing the name and type std::string
gsell's avatar
gsell committed
271 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
    //  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
303
    ///@{ Access to ELEMEDGE attribute
304 305 306
    void setElementPosition(double elemedge);
    double getElementPosition() const;
    bool isElementPositionSet() const;
snuverink_j's avatar
snuverink_j committed
307
    ///@}
gsell's avatar
gsell committed
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
    /// 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;

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

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

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

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

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

    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
358 359 360 361 362 363 364 365 366 367 368 369
    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
370 371 372 373

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

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

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

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

392 393 394 395 396 397 398 399 400
    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
401 402 403 404 405 406
private:

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

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

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

    WakeFunction *wake_m;

    BoundaryGeometry *bgeometry_m;

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    csTrafoGlobal2Local_m = trafo;
}

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

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

    return ret;
}

inline
CoordinateSystemTrafo ElementBase::getEdgeToEnd() const
533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
{
    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
557
    return r(2) >= 0.0 && r(2) < length && isInsideTransverse(r);
558 559 560 561 562 563 564 565 566 567 568 569
}

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

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

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

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

inline
581
bool ElementBase::isPositioned() const {
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
    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
605 606
{ return getTypeString(getType());}

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

frey_m's avatar
frey_m committed
626
#endif // CLASSIC_ElementBase_HH