ParallelCyclotronTracker.h 18.4 KB
Newer Older
gsell's avatar
gsell committed
1 2
#ifndef OPAL_ParallelCyclotronTracker_HH
#define OPAL_ParallelCyclotronTracker_HH
3

gsell's avatar
gsell committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// ------------------------------------------------------------------------
// $RCSfile: ParallelCyclotronTracker.h,v $
// ------------------------------------------------------------------------
// $Revision: 1.1.2.1 $
// ------------------------------------------------------------------------
// Copyright: see Copyright.readme
// ------------------------------------------------------------------------
//
// Class: ParallelCyclotron
//
// ------------------------------------------------------------------------
//
// $Date: 2004/11/12 20:10:11 $
// $Author: adelmann $
//
// ------------------------------------------------------------------------

#include "Algorithms/Tracker.h"
22
#include "AbsBeamline/ElementBase.h"
gsell's avatar
gsell committed
23
#include <vector>
24
#include <tuple>
25
#include <memory>
gsell's avatar
gsell committed
26

27
#include "MultiBunchHandler.h"
28
#include "Steppers/Steppers.h"
gsell's avatar
gsell committed
29

30 31
class DataSink;

frey_m's avatar
frey_m committed
32 33
template <class T, unsigned Dim>
class PartBunchBase;
gsell's avatar
gsell committed
34 35 36 37

// Class ParallelCyclotronTracker
// ------------------------------------------------------------------------

38 39 40 41 42 43 44
struct CavityCrossData {
    RFCavity * cavity;
    double sinAzimuth;
    double cosAzimuth;
    double perpenDistance;
};

gsell's avatar
gsell committed
45 46 47
class ParallelCyclotronTracker: public Tracker {

public:
48

49
    enum class MODE {
50 51 52 53 54
        UNDEFINED = -1,
        SINGLE = 0,
        SEO = 1,
        BUNCH = 2
    };
55

56 57
    typedef std::vector<double> dvector_t;
    typedef std::vector<int> ivector_t;
58
    typedef std::pair<double[8], Component *>      element_pair;
59
    typedef std::pair<ElementBase::ElementType, element_pair>        type_pair;
gsell's avatar
gsell committed
60 61 62 63 64 65 66 67
    typedef std::list<type_pair *>                 beamline_list;

    /// Constructor.
    //  The beam line to be tracked is "bl".
    //  The particle reference data are taken from "data".
    //  The particle bunch tracked is taken from [b]bunch[/b].
    //  If [b]revBeam[/b] is true, the beam runs from s = C to s = 0.
    //  If [b]revTrack[/b] is true, we track against the beam.
68 69 70
    ParallelCyclotronTracker(const Beamline &bl, PartBunchBase<double, 3> *bunch, DataSink &ds,
                             const PartData &data, bool revBeam,
                             bool revTrack, int maxSTEPS,
71 72 73 74 75 76
                             int timeIntegrator,
                             const int& numBunch,
                             const double& mbEta,
                             const double& mbPara,
                             const std::string& mbMode,
                             const std::string& mbBinning);
gsell's avatar
gsell committed
77 78 79

    virtual ~ParallelCyclotronTracker();

kraus's avatar
kraus committed
80 81
    /// Apply the algorithm to an Ring
    virtual void visitRing(const Ring &ring);
82

gsell's avatar
gsell committed
83 84 85 86 87 88 89 90 91 92
    /// Apply the algorithm to a Cyclotorn
    virtual void visitCyclotron(const Cyclotron &cycl);

    /// Apply the algorithm to a RFCavity.
    virtual void visitRFCavity(const RFCavity &);

    /// Apply the algorithm to a BeamBeam.
    virtual void visitBeamBeam(const BeamBeam &);

    /// Apply the algorithm to a collimator.
93
    virtual void visitCCollimator(const CCollimator &);
gsell's avatar
gsell committed
94 95 96 97

    /// Apply the algorithm to a Corrector.
    virtual void visitCorrector(const Corrector &);

adelmann's avatar
adelmann committed
98 99 100
    /// Apply the algorithm to a Degrader
    virtual void visitDegrader(const Degrader &);

gsell's avatar
gsell committed
101 102 103 104 105 106
    /// Apply the algorithm to a Diagnostic.
    virtual void visitDiagnostic(const Diagnostic &);

    /// Apply the algorithm to a Drift.
    virtual void visitDrift(const Drift &);

107 108 109
    /// Apply the algorithm to a flexible collimator
    virtual void visitFlexibleCollimator(const FlexibleCollimator &);

gsell's avatar
gsell committed
110 111 112 113 114 115 116 117 118 119 120 121
    /// Apply the algorithm to a Lambertson.
    virtual void visitLambertson(const Lambertson &);

    /// Apply the algorithm to a Marker.
    virtual void visitMarker(const Marker &);

    /// Apply the algorithm to a Monitor.
    virtual void visitMonitor(const Monitor &);

    /// Apply the algorithm to a Multipole.
    virtual void visitMultipole(const Multipole &);

ext-rogers_c's avatar
ext-rogers_c committed
122 123
    /// Apply the algorithm to a MultipoleT
    virtual void visitMultipoleT (const MultipoleT &);
124 125 126 127 128 129 130 131 132

    /// Apply the algorithm to a MultipoleTStraight
    virtual void visitMultipoleTStraight (const MultipoleTStraight &);

    /// Apply the algorithm to a MultipoleTCurvedConstRadius
    virtual void visitMultipoleTCurvedConstRadius (const MultipoleTCurvedConstRadius &);

    /// Apply the algorithm to a MultipoleTCurvedVarRadius
    virtual void visitMultipoleTCurvedVarRadius (const MultipoleTCurvedVarRadius &);
133

134 135 136
    /// Apply the algorithm to a Offset.
    virtual void visitOffset(const Offset &);

gsell's avatar
gsell committed
137 138 139 140 141 142 143 144 145 146 147 148
    /// Apply the algorithm to a Probe.
    virtual void visitProbe(const Probe &);

    /// Apply the algorithm to a RBend.
    virtual void visitRBend(const RBend &);

    /// Apply the algorithm to a RFQuadrupole.
    virtual void visitRFQuadrupole(const RFQuadrupole &);

    /// Apply the algorithm to a SBend.
    virtual void visitSBend(const SBend &);

149 150 151
    /// Apply the algorithm to a SBend3D.
    virtual void visitSBend3D(const SBend3D &);

ext-rogers_c's avatar
ext-rogers_c committed
152 153
    /// Apply the algorithm to a ScalingFFAMagnet.
    virtual void visitScalingFFAMagnet(const ScalingFFAMagnet &bend);
154

gsell's avatar
gsell committed
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
    /// Apply the algorithm to a Separator.
    virtual void visitSeparator(const Separator &);

    /// Apply the algorithm to a Septum.
    virtual void visitSeptum(const Septum &);

    /// Apply the algorithm to a Solenoid.
    virtual void visitSolenoid(const Solenoid &);

    /// Apply the algorithm to a charge stripper.
    virtual void visitStripper(const Stripper &);

    /// Apply the algorithm to a ParallelPlate, it is empty for cyclotrontracker .
    virtual void visitParallelPlate(const ParallelPlate &);

    /// Apply the algorithm to a CyclotronValley.it is empty for cyclotrontracker .
    virtual void visitCyclotronValley(const CyclotronValley &);

173 174 175
    /// Apply the algorithm to a VariabelRFCavity.
    virtual void visitVariableRFCavity(const VariableRFCavity &cav);

176 177 178 179
    /// Apply the algorithm to a VariabelRFCavity.
    virtual void visitVariableRFCavityFringeField
                                      (const VariableRFCavityFringeField &cav);

gsell's avatar
gsell committed
180 181 182 183 184 185 186 187 188 189 190
    /// Apply the algorithm to the top-level beamline.
    //  overwrite the execute-methode from DefaultVisitor
    virtual void execute();

    /// Apply the algorithm to a beam line.
    //  overwrite the execute-methode from DefaultVisitor
    virtual void visitBeamline(const Beamline &);

    /// set last dumped step
    inline void setLastDumpedStep(const int para) {lastDumpedStep_m = para ; }

191
    ///@{ Method for restart
192
    inline void setPr(double x) {referencePr = x;}
193 194
    inline void setPt(double x) {referencePt = x;}
    inline void setPz(double x) {referencePz = x;}
195 196
    inline void setR(double x) {referenceR = x;}
    inline void setTheta(double x) {referenceTheta = x;}
197
    inline void setZ(double x) {referenceZ = x;}
198
    inline void setBeGa(double x) {bega = x;}
199 200 201
    inline void setPhi(double x) {referencePhi = x;}
    inline void setPsi(double x) {referencePsi = x;}
    inline void setPreviousH5Local(bool x) {previousH5Local = x;}
202
    ///@}
203 204
    void bgf_main_collision_test();
    void initializeBoundaryGeometry();
205

gsell's avatar
gsell committed
206 207 208 209 210 211 212 213 214 215 216 217
private:

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

    beamline_list FieldDimensions;
    std::list<Component *> myElements;
    Beamline *itsBeamline;

    DataSink *itsDataSink;
218

219 220
    BoundaryGeometry *bgf_m;

gsell's avatar
gsell committed
221 222 223
    /// The maximal number of steps the system is integrated
    int maxSteps_m;

224
    /// The positive axes unit vectors
225 226 227
    static Vector_t const xaxis;
    static Vector_t const yaxis;
    static Vector_t const zaxis;
228

Daniel Winklehner's avatar
Daniel Winklehner committed
229
    /// The reference variables
230
    double bega;
gsell's avatar
gsell committed
231 232
    double referenceR;
    double referenceTheta;
Daniel Winklehner's avatar
Daniel Winklehner committed
233
    double referenceZ = 0.0;
gsell's avatar
gsell committed
234 235 236

    double referencePr;
    double referencePt;
Daniel Winklehner's avatar
Daniel Winklehner committed
237
    double referencePz = 0.0;
gsell's avatar
gsell committed
238 239
    double referencePtot;

240 241 242
    double referencePsi;
    double referencePhi;

243 244
    bool spiral_flag = false;

245 246
    Vector_t PreviousMeanP;

247 248
    bool previousH5Local;

gsell's avatar
gsell committed
249 250
    double sinRefTheta_m;
    double cosRefTheta_m;
251

252 253
    // only used for multi-bunch mode
    std::unique_ptr<MultiBunchHandler> mbHandler_m;
gsell's avatar
gsell committed
254 255 256

    int lastDumpedStep_m;

257 258
    // for each bunch we have a path length
    double pathLength_m;
gsell's avatar
gsell committed
259

260
    void MtsTracker();
gsell's avatar
gsell committed
261

262
    void GenericTracker();
263 264
    bool getFieldsAtPoint(const double &t, const size_t &Pindex, Vector_t &Efield, Vector_t &Bfield);

gsell's avatar
gsell committed
265
    /*
266
      Local Variables both used by the integration methods
gsell's avatar
gsell committed
267 268 269 270 271
    */

    long long step_m;
    long long restartStep0_m;

272 273
    int turnnumber_m;

274 275 276 277
    // only for dumping
    double azimuth_m;
    double prevAzimuth_m;

frey_m's avatar
frey_m committed
278 279 280 281 282 283 284 285
    /* only for dumping to stat-file --> make azimuth monotonically increasing
     * @param theta computed azimuth [deg]
     * @param prevAzimuth previous angle [deg]
     * @param azimuth to be updated [deg]
     */
    void dumpAngle(const double& theta,
                   double& prevAzimuth,
                   double& azimuth);
286

frey_m's avatar
frey_m committed
287 288
    double computeRadius(const Vector_t& meanR) const;

frey_m's avatar
frey_m committed
289
    void computePathLengthUpdate(std::vector<double>& dl, const double& dt);
gsell's avatar
gsell committed
290 291 292 293 294 295 296 297

    // external field arrays for dumping
    Vector_t FDext_m[2], extE_m, extB_m;

    const int myNode_m;
    const size_t initialLocalNum_m;
    const size_t initialTotalNum_m;

298
    /// output coordinates at different azimuthal angles and one after every turn
299
    std::vector<std::unique_ptr<std::ofstream> > outfTheta_m;
300 301 302
    /// the different azimuthal angles for the outfTheta_m output files
    std::vector<double> azimuth_angle_m;
    ///@ open / close output coordinate files
303
    void openFiles(size_t numFiles, std::string fn);
304 305 306 307
    void closeFiles();
    ///@}
    /// output file for six dimensional phase space
    std::ofstream outfTrackOrbit_m;
gsell's avatar
gsell committed
308

309
    void buildupFieldList(double BcParameter[], ElementBase::ElementType elementType, Component *elptr);
gsell's avatar
gsell committed
310 311 312 313 314 315 316 317 318

    // angle range [0~2PI) degree
    double calculateAngle(double x, double y);
    // angle range [-PI~PI) degree
    double calculateAngle2(double x, double y);

    bool checkGapCross(Vector_t Rold, Vector_t Rnew, RFCavity * rfcavity, double &DistOld);
    bool RFkick(RFCavity * rfcavity, const double t, const double dt, const int Pindex);

319
    bool getTunes(dvector_t &t,  dvector_t &r,  dvector_t &z, int lastTurn, double &nur, double &nuz);
gsell's avatar
gsell committed
320 321 322 323 324

    IpplTimings::TimerRef IntegrationTimer_m;
    IpplTimings::TimerRef DumpTimer_m ;
    IpplTimings::TimerRef TransformTimer_m;
    IpplTimings::TimerRef BinRepartTimer_m;
325 326
    IpplTimings::TimerRef PluginElemTimer_m;
    IpplTimings::TimerRef DelParticleTimer_m;
gsell's avatar
gsell committed
327

frey_m's avatar
frey_m committed
328 329 330 331 332
    /*
     * @param bunchNr if <= -1 --> take all particles in simulation, if bunchNr > -1,
     * take only particles of *this* bunch
     */
    Vector_t calcMeanR(short bunchNr = -1) const;
333

gsell's avatar
gsell committed
334
    Vector_t calcMeanP() const;
335

gsell's avatar
gsell committed
336
    void repartition(); // Do repartition between nodes if step_m is multiple of Options::repartFreq
337 338

    // Transform the x- and y-parts of a particle attribute (position, momentum, fields) from the
gsell's avatar
gsell committed
339
    // global reference frame to the local reference frame.
340

gsell's avatar
gsell committed
341
    // phi is the angle of the bunch measured counter-clockwise from the positive x-axis.
342 343
    void globalToLocal(ParticleAttrib<Vector_t> & vectorArray,
                       double phi, Vector_t const translationToGlobal = 0);
344 345

    // Transform the x- and y-parts of a particle attribute (position, momentum, fields) from the
gsell's avatar
gsell committed
346
    // local reference frame to the global reference frame.
347
    void localToGlobal(ParticleAttrib<Vector_t> & vectorArray,
348
                       double phi, Vector_t const translationToGlobal = 0);
349

350
    // Overloaded version of globalToLocal using a quaternion for 3D rotation
351 352
    inline void globalToLocal(ParticleAttrib<Vector_t> & vectorArray,
                              Quaternion_t const quaternion,
353
                              Vector_t const meanR = Vector_t(0.0));
354

355
    // Overloaded version of localToGlobal using a quaternion for 3D rotation
356
    inline void localToGlobal(ParticleAttrib<Vector_t> & vectorArray,
357
                              Quaternion_t const quaternion,
358
                              Vector_t const meanR = Vector_t(0.0));
359

360
    // Overloaded version of globalToLocal using phi and theta for pseudo 3D rotation
361 362
    inline void globalToLocal(ParticleAttrib<Vector_t> & particleVectors,
                              double const phi, double const psi,
363
                              Vector_t const meanR = Vector_t(0.0));
364 365

    // Overloaded version of localToGlobal using phi and theta for pseudo 3D rotation
366 367
    inline void localToGlobal(ParticleAttrib<Vector_t> & particleVectors,
                              double const phi, double const psi,
368 369 370
                              Vector_t const meanR = Vector_t(0.0));

    // Overloaded version of globalToLocal using phi and theta for pseudo 3D rotation, single vector
371 372
    inline void globalToLocal(Vector_t & myVector,
                              double const phi, double const psi,
373 374 375
                              Vector_t const meanR = Vector_t(0.0));

    // Overloaded version of localToGlobal using phi and theta for pseudo 3D rotation, single vector
376 377
    inline void localToGlobal(Vector_t & myVector,
                              double const phi, double const psi,
378
                              Vector_t const meanR = Vector_t(0.0));
379 380

    // Rotate the particles by an angle and axis defined in the quaternion (4-vector w,x,y,z)
adelmann's avatar
adelmann committed
381
    inline void rotateWithQuaternion(ParticleAttrib<Vector_t> & vectorArray, Quaternion_t const quaternion);
382 383

    // Returns the quaternion of the rotation from vector u to vector v
adelmann's avatar
adelmann committed
384
    inline void getQuaternionTwoVectors(Vector_t u, Vector_t v, Quaternion_t & quaternion);
385 386

    // Normalization of a quaternion
adelmann's avatar
adelmann committed
387
    inline void normalizeQuaternion(Quaternion_t & quaternion);
388

389
    // Normalization of a quaternion
390
    inline void normalizeVector(Vector_t & vector);
391 392 393 394

    // Some rotations
    inline void rotateAroundZ(ParticleAttrib<Vector_t> & particleVectors, double const phi);
    inline void rotateAroundX(ParticleAttrib<Vector_t> & particleVectors, double const psi);
395 396
    inline void rotateAroundZ(Vector_t & myVector, double const phi);
    inline void rotateAroundX(Vector_t & myVector, double const psi);
397

398
    // Push particles for time h.
gsell's avatar
gsell committed
399 400
    // Apply effects of RF Gap Crossings.
    // Update time and path length.
frey_m's avatar
frey_m committed
401
    // Unit assumptions: [itsBunch_m->R] = m, [itsBunch_m->P] = 1, [h] = s, [c] = m/s, [itsBunch_m->getT()] = s
402
    bool push(double h);
gsell's avatar
gsell committed
403

404
    // Kick particles for time h
frey_m's avatar
frey_m committed
405
    // The fields itsBunch_m->Bf, itsBunch_m->Ef are used to calculate the forces
406
    bool kick(double h);
407 408 409 410

    // Apply the trilogy half push - kick - half push,
    // considering only external fields
    void borisExternalFields(double h);
411 412

    // apply the plugin elements: probe, collimator, stripper, septum
413
    bool applyPluginElements(const double dt);
414

415
    // destroy particles if they are marked as Bin=-1 in the plugin elements or out of global apeture
416
    bool deleteParticle(bool = false);
417

418 419 420 421
    void initTrackOrbitFile();

    void singleParticleDump();

422 423 424
    void bunchDumpStatData();

    void bunchDumpPhaseSpaceData();
425

426 427
    void evaluateSpaceChargeField();

428 429
    void initDistInGlobalFrame();

Matthias Toggweiler's avatar
Matthias Toggweiler committed
430 431
    void checkNumPart(std::string s);

kraus's avatar
kraus committed
432 433
    // we store a pointer explicitly to the Ring
    Ring* opalRing_m;
434

435

kraus's avatar
kraus committed
436
    // If Ring is defined take the harmonic number from Ring; else use
437 438
    // cyclotron
    double getHarmonicNumber() const;
439

440 441 442 443
    typedef std::function<bool(const double&,
                               const size_t&,
                               Vector_t&,
                               Vector_t&)> function_t;
444

445
    std::unique_ptr< Stepper<function_t> > itsStepper_mp;
446

447 448 449 450 451 452
    struct settings {
        int scSolveFreq;
        int stepsPerTurn;
        double deltaTheta;
        int stepsNextCheck;
    } setup_m;
453

454
    MODE mode_m;
455

456
    stepper::INTEGRATOR stepper_m;
457

458
    void update_m(double& t, const double& dt, const bool& dumpEachTurn);
459

460 461 462
    /*!
     * @returns the time t [ns], time step dt [ns] and the azimuth angle [rad]
     */
463
    std::tuple<double, double, double> initializeTracking_m();
464

465 466 467 468
    void finalizeTracking_m(dvector_t& Ttime,
                            dvector_t& Tdeltr,
                            dvector_t& Tdeltz,
                            ivector_t& TturnNumber);
469

470
    void seoMode_m(double& t, const double dt, bool& dumpEachTurn,
471 472
                   dvector_t& Ttime, dvector_t& Tdeltr,
                   dvector_t& Tdeltz, ivector_t& TturnNumber);
473

474
    void singleMode_m(double& t, const double dt, bool& dumpEachTurn, double& oldReferenceTheta);
475

476
    void bunchMode_m(double& t, const double dt, bool& dumpEachTurn);
477

478 479
    void gapCrossKick_m(size_t i, double t, double dt,
                        const Vector_t& Rold, const Vector_t& Pold);
480 481


482 483 484 485 486
    inline void dumpAzimuthAngles_m(const double& t,
                                    const Vector_t& R,
                                    const Vector_t& P,
                                    const double& oldReferenceTheta,
                                    const double& temp_meanTheta);
487

488 489 490 491 492
    inline void dumpThetaEachTurn_m(const double& t,
                                    const Vector_t& R,
                                    const Vector_t& P,
                                    const double& temp_meanTheta,
                                    bool& dumpEachTurn);
493

494
    void computeSpaceChargeFields_m();
495

496 497 498 499
    bool computeExternalFields_m(const size_t& i,
                                 const double& t,
                                 Vector_t& Efield,
                                 Vector_t& Bfield);
500

501
    void injectBunch(bool& flagTransition);
502

frey_m's avatar
frey_m committed
503 504
    void saveInjectValues();

505
    bool isMultiBunch() const;
506 507

    bool hasMultiBunch() const;
frey_m's avatar
frey_m committed
508 509 510 511 512 513 514 515 516 517 518

    /*
     * @param dt time step in ns
     */
    void updatePathLength(const double& dt);

    /*
     * @param dt time step in ns
     */
    void updateTime(const double& dt);

frey_m's avatar
frey_m committed
519
    void updateAzimuthAndRadius();
gsell's avatar
gsell committed
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
};

/**
 * @param x
 * @param y
 *
 * @return angle range [0~2PI) degree
 */
inline
double ParallelCyclotronTracker::calculateAngle(double x, double y) {
    double thetaXY = atan2(y, x);

    if (thetaXY < 0) return thetaXY + Physics::two_pi;
    return thetaXY;
}

/**
 * @param x
 * @param y
 *
 * @return angle range [-PI~PI) degree
 */
inline
543
double ParallelCyclotronTracker::calculateAngle2(double x, double y)
544 545 546 547 548 549 550
{
    return atan2(y,x);
}


inline
bool ParallelCyclotronTracker::isMultiBunch() const {
551 552 553 554 555 556 557
    return ( (mbHandler_m != nullptr) && itsBunch_m->weHaveBins() );
}


inline
bool ParallelCyclotronTracker::hasMultiBunch() const {
    return ( isMultiBunch() && mbHandler_m->getNumBunch() > 1 );
558
}
gsell's avatar
gsell committed
559

560
#endif // OPAL_ParallelCyclotronTracker_HH