SetIntegrator.cpp 6.73 KB
Newer Older
gsell's avatar
gsell committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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
// ------------------------------------------------------------------------
// $RCSfile: SetIntegrator.cpp,v $
// ------------------------------------------------------------------------
// $Revision: 1.2 $
// ------------------------------------------------------------------------
// Copyright: see Copyright.readme
// ------------------------------------------------------------------------
//
// Definitions for class: SetIntegrator
//   The class for the OPAL SETINTEGRATOR command.
//
// ------------------------------------------------------------------------
//
// $Date: 2002/03/28 21:27:54 $
// $Author: jsberg $
//
// ------------------------------------------------------------------------

#include "PhysicsActions/SetIntegrator.h"
#include "AbsBeamline/AlignWrapper.h"
#include "AbsBeamline/Integrator.h"
#include "AbsBeamline/Multipole.h"
#include "AbstractObjects/BeamSequence.h"
#include "AbstractObjects/OpalData.h"
#include "Algorithms/DefaultVisitor.h"
#include "Algorithms/MPSplitIntegrator.h"
#include "Attributes/Attributes.h"
#include "Beamlines/Beamline.h"
#include "Beamlines/FlaggedElmPtr.h"
#include "Utilities/Options.h"
#include <iostream>

using std::cerr;


// Class SetIntegrator
// ------------------------------------------------------------------------

namespace {

    // Visitor class Setter for attaching the integrators.
    class Setter: public DefaultVisitor {

    public:
        // Construction/destruction.
46
        Setter(const Beamline &, const std::string &type, int slices);
gsell's avatar
gsell committed
47 48 49 50 51 52 53 54 55 56
        virtual ~Setter();

        // Override method for integratorconst  visit.
        virtual void visitFlaggedElmPtr(const FlaggedElmPtr &);

        // Return error counts.
        void getCounts(int &add, int &rem, int &rep) const;

    private:
        // The type of integrator.
57
        const std::string itsType;
gsell's avatar
gsell committed
58 59 60 61 62 63 64 65 66

        // The number of slices.
        int itsSlices;

        // Keeps track of inserted integrators.
        int added, removed, replaced;
    };


67
    Setter::Setter(const Beamline &beamline, const std::string &type, int slices):
gsell's avatar
gsell committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
        DefaultVisitor(beamline, false, false),
        itsType(type), itsSlices(slices), added(0), removed(0), replaced(0)
    {}


    Setter::~Setter()
    {}


    void Setter::visitFlaggedElmPtr(const FlaggedElmPtr &fep) {
        // The pointer "base" points to the actual element or integrator.
        ElementBase *temp = fep.getElement();
        ElementBase *base = temp->removeAlignWrapper();

        // The pointer "wrap" points to an AlignWrapper, if it exist,
        // otherwise it is NULL.
        AlignWrapper *wrap = dynamic_cast<AlignWrapper *>(temp);

        if(dynamic_cast<Beamline *>(base)) {
            // Enter beam line via the default action.
            DefaultVisitor::visitFlaggedElmPtr(fep);
        } else if(fep.getSelectionFlag()) {
            // Single element is selected.
            if(Integrator *i = dynamic_cast<Integrator *>(base)) {
                // The embedded element should be a multipole.
                if(Multipole *mult = dynamic_cast<Multipole *>(i->getElement())) {
                    // Replace/remove an existing integrator.
                    ElementBase *mpsi;
                    if(itsType == "NONE") {
                        // Going to link the multipole directly, without an integrator.
                        removed++;
                        mpsi = mult;
                    } else {
                        // Going to link the multipole with a new integrator.
                        replaced++;
                        mpsi = new MPSplitIntegrator(mult, itsSlices);
                    }
                    if(wrap) {
                        wrap->setElement(mpsi);
                    } else {
                        const_cast<FlaggedElmPtr &>(fep).setElement(mpsi);
                    }
                }
            } else if(Multipole *mult = dynamic_cast<Multipole *>(base)) {
                // Going to wrap the multipole with a new integrator.
                ElementBase *mpsi = new MPSplitIntegrator(mult, itsSlices);
                added++;

                if(wrap) {
                    wrap->setElement(mpsi);
                } else {
                    const_cast<FlaggedElmPtr &>(fep).setElement(mpsi);
                }
            }
            // Nothing to be done for any other element.
        }
    }


    void Setter::getCounts(int &add, int &rem, int &rep) const {
        add = added;
        rem = removed;
        rep = replaced;
    }


    // The attributes of class SetIntegrator.
    enum {
        LINE,        // The lattice to be used.
        TYPE,        // The type of integrator.
        SLICES,      // The number of slices.
        SIZE
    };
}


SetIntegrator::SetIntegrator():
    Action(SIZE, "SETINT",
           "The \"SETINT\" statement attaches special integrators to selected "
           "elements.") {
    itsAttr[LINE] = Attributes::makeString
                    ("LINE", "Name of the lattice to be changed");
    itsAttr[TYPE] = Attributes::makeString
                    ("TYPE", "Type of integrator to be attached: default = THIN", "THIN");
    itsAttr[SLICES] = Attributes::makeReal
                      ("SLICES", "Number of slices to be used for \"TYPE=THIN\"", 1.0);
154 155

    registerOwnership(AttributeHandler::STATEMENT);
gsell's avatar
gsell committed
156 157 158
}


159
SetIntegrator::SetIntegrator(const std::string &name, SetIntegrator *parent):
gsell's avatar
gsell committed
160 161 162 163 164 165 166 167
    Action(name, parent)
{}


SetIntegrator::~SetIntegrator()
{}


168
SetIntegrator *SetIntegrator::clone(const std::string &name) {
gsell's avatar
gsell committed
169 170 171 172 173 174 175 176 177 178 179 180 181 182 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
    return new SetIntegrator(name, this);
}


void SetIntegrator::execute() {
    // Find BeamSequence definition.
    BeamSequence *use = BeamSequence::find(Attributes::getString(itsAttr[LINE]));

    // Initialize the visitor.
    int slices = int(Attributes::getReal(itsAttr[SLICES]));
    Setter splitter(*use->fetchLine(), Attributes::getString(itsAttr[TYPE]), slices);
    splitter.execute();

    // Confirm action to user.
    if(Options::info) {
        int add = 0, rem = 0, rep = 0;
        splitter.getCounts(add, rem, rep);
        cerr << '\n';

        if(rem == 0) {
            cerr << "No integrator removed.\n";
        } else if(rem == 1) {
            cerr << "1 integrator removed.\n";
        } else if(rem > 1) {
            cerr << rem << " integrators removed.\n";
        }

        if(rep == 0) {
            cerr << "No integrator replaced.\n";
        } else if(rep == 1) {
            cerr << "1 integrator replaced.\n";
        } else if(rep > 1) {
            cerr << rep << " integrators replaced.\n";
        }

        if(add == 0) {
            cerr << "No integrator installed.\n";
        } else if(add == 1) {
            cerr << "1 integrator installed.\n";
        } else if(add > 1) {
            cerr << add << " integrators installed.\n";
        }

        cerr << std::endl;
    }
214
}