diff --git a/src/Algorithms/MultiBunchHandler.cpp b/src/Algorithms/MultiBunchHandler.cpp
index 0d12afb95376806a15da55652221d5660b5d8176..516107b65e0d9db0c9b978ef8304e7974c22628b 100644
--- a/src/Algorithms/MultiBunchHandler.cpp
+++ b/src/Algorithms/MultiBunchHandler.cpp
@@ -112,7 +112,7 @@ void MultiBunchHandler::saveBunch(PartBunchBase<double, 3> *beam)
 
     Ppos_t coord, momentum;
     ParticleAttrib<double> mass, charge;
-    ParticleAttrib<short> ptype;
+    ParticleAttrib<ParticleOrigin> porigin;
 
     std::size_t localNum = beam->getLocalNum();
 
@@ -128,8 +128,8 @@ void MultiBunchHandler::saveBunch(PartBunchBase<double, 3> *beam)
     charge.create(localNum);
     charge = beam->Q;
 
-    ptype.create(localNum);
-    ptype = beam->PType;
+    porigin.create(localNum);
+    porigin = beam->POrigin;
 
     std::map<std::string, double> additionalAttributes = {
         std::make_pair("REFPR", 0.0),
@@ -234,7 +234,7 @@ bool MultiBunchHandler::readBunch(PartBunchBase<double, 3> *beam,
         beam->P[localNum] = tmpBunch->P[ii];
         beam->M[localNum] = tmpBunch->M[ii];
         beam->Q[localNum] = tmpBunch->Q[ii];
-        beam->PType[localNum] = ParticleType::REGULAR;
+        beam->POrigin[localNum] = ParticleOrigin::REGULAR;
         beam->Bin[localNum] = bunchNum;
         beam->bunchNum[localNum] = bunchNum;
     }
diff --git a/src/Algorithms/ParallelCyclotronTracker.cpp b/src/Algorithms/ParallelCyclotronTracker.cpp
index 983ed6cbcd6041b837f7ef88f467fcf9528d6362..229d92bcce672e8dede9ea63a0ef44273fdf98a8 100644
--- a/src/Algorithms/ParallelCyclotronTracker.cpp
+++ b/src/Algorithms/ParallelCyclotronTracker.cpp
@@ -565,7 +565,7 @@ void ParallelCyclotronTracker::visitBeamStripping(const BeamStripping &bstp) {
     double temperature = elptr->getTemperature();
     *gmsg << "* Temperature  = " << temperature << " [K]" << endl;
 
-    std::string gas = elptr->getResidualGas();
+    std::string gas = elptr->getResidualGasName();
     *gmsg << "* Residual gas = " << gas << endl;
 
     bool stop = elptr->getStop();
@@ -2047,8 +2047,7 @@ bool ParallelCyclotronTracker::applyPluginElements(const double dt) {
     for(beamline_list::iterator sindex = ++(FieldDimensions.begin()); sindex != FieldDimensions.end(); ++sindex) {
         if(((*sindex)->first) == ElementBase::BEAMSTRIPPING) {
             BeamStripping *bstp = static_cast<BeamStripping *>(((*sindex)->second).second);
-            bstp->checkBeamStripping(itsBunch_m, cycl_m, turnnumber_m,
-                                     itsBunch_m->getT()*1e9 /*[ns]*/, dt);
+            bstp->checkBeamStripping(itsBunch_m, cycl_m);
         }
     }
 
diff --git a/src/Algorithms/ParallelTTracker.cpp b/src/Algorithms/ParallelTTracker.cpp
index 3565273eaf2cfc02711feb8bb8115e8e288d8596..62affcfd093b94bc6b5f59041afe3db3935a99fc 100644
--- a/src/Algorithms/ParallelTTracker.cpp
+++ b/src/Algorithms/ParallelTTracker.cpp
@@ -1341,8 +1341,8 @@ void ParallelTTracker::evenlyDistributeParticles() {
                 send_msgbuf.insert(send_msgbuf.end(), buffer, buffer + sizeof(double));
                 buffer = reinterpret_cast<const char*>(&(itsBunch_m->dt[idx]));
                 send_msgbuf.insert(send_msgbuf.end(), buffer, buffer + sizeof(double));
-                buffer = reinterpret_cast<const char*>(&(itsBunch_m->PType[idx]));
-                send_msgbuf.insert(send_msgbuf.end(), buffer, buffer + sizeof(short));
+                buffer = reinterpret_cast<const char*>(&(itsBunch_m->POrigin[idx]));
+                send_msgbuf.insert(send_msgbuf.end(), buffer, buffer + sizeof(ParticleOrigin));
                 buffer = reinterpret_cast<const char*>(&(itsBunch_m->TriID[idx]));
                 send_msgbuf.insert(send_msgbuf.end(), buffer, buffer + sizeof(int));
                 buffer = reinterpret_cast<const char*>(&(itsBunch_m->ID[idx]));
@@ -1384,10 +1384,10 @@ void ParallelTTracker::evenlyDistributeParticles() {
             j += 9 * sizeof(double);
 
             {
-                const short *buffer = reinterpret_cast<const short*>(recvbuf + j);
-                itsBunch_m->PType[idx] = buffer[0];
+                const ParticleOrigin *buffer = reinterpret_cast<const ParticleOrigin*>(recvbuf + j);
+                itsBunch_m->POrigin[idx] = buffer[0];
             }
-            j += sizeof(short);
+            j += sizeof(ParticleOrigin);
 
             {
                 const int *buffer = reinterpret_cast<const int*>(recvbuf + j);
@@ -1408,4 +1408,4 @@ void ParallelTTracker::evenlyDistributeParticles() {
     if (requests.size() > 0) {
         MPI_Waitall(requests.size(), &(requests[0]), MPI_STATUSES_IGNORE);
     }
-}
\ No newline at end of file
+}
diff --git a/src/Classic/AbsBeamline/BeamStripping.cpp b/src/Classic/AbsBeamline/BeamStripping.cpp
index 90f384fe91d3ff3ed50011f9024521f74f37dd6a..b2617619ed8ab67260155be79f79238004c4a3d7 100644
--- a/src/Classic/AbsBeamline/BeamStripping.cpp
+++ b/src/Classic/AbsBeamline/BeamStripping.cpp
@@ -3,7 +3,7 @@
 //   Defines the abstract interface environment for
 //   beam stripping physics.
 //
-// Copyright (c) 2018-2019, Pedro Calvo, CIEMAT, Spain
+// Copyright (c) 2018-2021, Pedro Calvo, CIEMAT, Spain
 // All rights reserved
 //
 // Implemented as part of the PhD thesis
@@ -44,17 +44,14 @@
 throw GeneralClassicException("BeamStripping::getPressureFromFile",\
                               "fscanf returned EOF at " #arg);
 
-extern Inform *gmsg;
+extern Inform* gmsg;
 
-// Class BeamStripping
-// ------------------------------------------------------------------------
 
 BeamStripping::BeamStripping():
     BeamStripping("")
 {}
 
-
-BeamStripping::BeamStripping(const BeamStripping &right):
+BeamStripping::BeamStripping(const BeamStripping& right):
     Component(right),
     gas_m(right.gas_m),
     pressure_m(right.pressure_m),
@@ -69,9 +66,9 @@ BeamStripping::BeamStripping(const BeamStripping &right):
     parmatint_m(NULL) {
 }
 
-BeamStripping::BeamStripping(const std::string &name):
+BeamStripping::BeamStripping(const std::string& name):
     Component(name),
-    gas_m(""),
+    gas_m(ResidualGas::NOGAS),
     pressure_m(0.0),
     pmapfn_m(""),
     pscale_m(0.0),
@@ -84,13 +81,13 @@ BeamStripping::BeamStripping(const std::string &name):
     parmatint_m(NULL) {
 }
 
-
 BeamStripping::~BeamStripping() {
     if (online_m)
         goOffline();
 }
 
-void BeamStripping::accept(BeamlineVisitor &visitor) const {
+
+void BeamStripping::accept(BeamlineVisitor& visitor) const {
     visitor.visitBeamStripping(*this);
 }
 
@@ -142,16 +139,27 @@ double BeamStripping::getPScale() const {
 }
 
 void BeamStripping::setResidualGas(std::string gas) {
-    gas_m = gas;
+    if (gas == "AIR") {
+        gas_m = ResidualGas::AIR;
+    } else if (gas == "H2") {
+        gas_m = ResidualGas::H2;
+    }
 }
 
-std::string BeamStripping::getResidualGas() const {
-    if (gas_m == "H2" || gas_m == "AIR")
-        return gas_m;
-    else {
-        throw GeneralClassicException("BeamStripping::getResidualGas",
-                                      "Residual gas " + gas_m + " not found");
-    }
+ResidualGas BeamStripping::getResidualGas() const {
+    return gas_m;
+}
+
+std::string BeamStripping::getResidualGasName() {
+    switch (gas_m) {
+    case ResidualGas::AIR:
+        return "AIR";
+    case ResidualGas::H2:
+        return "H2";
+    default:
+       throw GeneralClassicException("BeamStripping::getResidualGasName",
+                                      "Residual gas not found");
+    }		
 }
 
 void BeamStripping::setStop(bool stopflag) {
@@ -163,8 +171,7 @@ bool BeamStripping::getStop() const {
 }
 
 
-bool BeamStripping::checkBeamStripping(PartBunchBase<double, 3> *bunch, Cyclotron* cycl,
-                                       const int /*turnnumber*/, const double /*t*/, const double /*tstep*/) {
+bool BeamStripping::checkBeamStripping(PartBunchBase<double, 3>* bunch, Cyclotron* cycl) {
 
     bool flagNeedUpdate = false;
 
@@ -194,12 +201,12 @@ bool BeamStripping::checkBeamStripping(PartBunchBase<double, 3> *bunch, Cyclotro
 }
 
 
-void BeamStripping::initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField) {
+void BeamStripping::initialise(PartBunchBase<double, 3>* bunch, double& startField, double& endField) {
     endField = startField + getElementLength();
     initialise(bunch, pscale_m);
 }
 
-void BeamStripping::initialise(PartBunchBase<double, 3> *bunch, const double &scaleFactor) {
+void BeamStripping::initialise(PartBunchBase<double, 3>* bunch, const double& scaleFactor) {
 
     RefPartBunch_m = bunch;
 
@@ -214,7 +221,6 @@ void BeamStripping::initialise(PartBunchBase<double, 3> *bunch, const double &sc
     goOnline(-1e6);
 
     // change the mass and charge to simulate real particles
-    //*gmsg << "* Mass and charge have been reseted for beam stripping " <<  endl;
     for (size_t i = 0; i < bunch->getLocalNum(); ++i) {
         bunch->M[i] = bunch->getM()*1E-9;
         bunch->Q[i] = bunch->getQ() * Physics::q_e;
@@ -240,7 +246,7 @@ bool BeamStripping::bends() const {
     return false;
 }
 
-void BeamStripping::getDimensions(double &/*zBegin*/, double &/*zEnd*/) const {}
+void BeamStripping::getDimensions(double& /*zBegin*/, double& /*zEnd*/) const {}
 
 ElementBase::ElementType BeamStripping::getType() const {
     return BEAMSTRIPPING;
@@ -250,17 +256,18 @@ std::string BeamStripping::getBeamStrippingShape() {
     return "BeamStripping";
 }
 
-int BeamStripping::checkPoint(const double &x, const double &y, const double &z) {
+int BeamStripping::checkPoint(const double& x, const double& y, const double& z) {
     int cn;
     double rpos = std::sqrt(x * x + y * y);
-    if (z >= maxz_m || z <= minz_m || rpos >= maxr_m || rpos <= minr_m)
+    if (z >= maxz_m || z <= minz_m || rpos >= maxr_m || rpos <= minr_m) {
         cn = 0;
-    else
+    } else {
         cn = 1;
+    }
     return (cn);  // 0 if out, and 1 if in
 }
 
-double BeamStripping::checkPressure(const double &x, const double &y) {
+double BeamStripping::checkPressure(const double& x, const double& y) {
 
     double pressure = 0.0;
 
@@ -296,7 +303,7 @@ double BeamStripping::checkPressure(const double &x, const double &y) {
         // include zero degree point
         it++;
         double epsilon = 0.06;
-        if  (tet > 360 - epsilon && tet < 360 + epsilon) it = 0;
+        if (tet > 360 - epsilon && tet < 360 + epsilon) it = 0;
 
         int r1t1, r2t1, r1t2, r2t2;
         // r1t1 : the index of the "min angle, min radius" point in the 2D field array.
@@ -317,18 +324,15 @@ double BeamStripping::checkPressure(const double &x, const double &y) {
                 *gmsg << level4 << getName() << ": Take constant value through BeamStripping::getPressure" << endl;
                 pressure = getPressure();
             }
-        }
-        else if (ir >= PField.nrad) {
+        } else if (ir >= PField.nrad) {
             *gmsg << level4 << getName() << ": Particle out of maximum radial position of pressure field map." << endl;
             *gmsg << level4 << getName() << ": Take constant value through BeamStripping::getPressure" << endl;
             pressure = getPressure();
-        }
-        else {
+        } else {
             throw GeneralClassicException("BeamStripping::checkPressure",
                                           "Pressure data not found");
         }
-    }
-    else {
+    } else {
         pressure = getPressure();
     }
 
@@ -345,9 +349,9 @@ void BeamStripping::initR(double rmin, double dr, int nrad) {
 }
 
 // Read pressure map from external file.
-void BeamStripping::getPressureFromFile(const double &scaleFactor) {
+void BeamStripping::getPressureFromFile(const double& scaleFactor) {
 
-    FILE *f = NULL;
+    FILE* f = NULL;
 
     *gmsg << "* " << endl;
     *gmsg << "* Reading pressure field map " << pmapfn_m << endl;
@@ -356,7 +360,8 @@ void BeamStripping::getPressureFromFile(const double &scaleFactor) {
 
     if ((f = std::fopen(pmapfn_m.c_str(), "r")) == NULL) {
         throw GeneralClassicException("BeamStripping::getPressureFromFile",
-                                      "failed to open file '" + pmapfn_m + "', please check if it exists");
+                                      "failed to open file '" + pmapfn_m +
+                                      "', please check if it exists");
     }
 
     CHECK_BSTP_FSCANF_EOF(std::fscanf(f, "%lf", &PP.rmin));
@@ -403,4 +408,4 @@ void BeamStripping::getPressureFromFile(const double &scaleFactor) {
     std::fclose(f);
 }
 
-#undef CHECK_BSTP_FSCANF_EOF
\ No newline at end of file
+#undef CHECK_BSTP_FSCANF_EOF
diff --git a/src/Classic/AbsBeamline/BeamStripping.h b/src/Classic/AbsBeamline/BeamStripping.h
index c96ba3ddd84b53356e35b4332214bb130d882a39..3d4325386af22eeb07bb1a21d5adf5a892718043 100644
--- a/src/Classic/AbsBeamline/BeamStripping.h
+++ b/src/Classic/AbsBeamline/BeamStripping.h
@@ -58,53 +58,55 @@ struct PPositions {
     double  Pfact; // MULTIPLICATION FACTOR FOR PRESSURE MAP
 };
 
+enum class ResidualGas:short {AIR,
+                              H2,
+                              NOGAS};
 
 
-// Class BeamStripping
-// ------------------------------------------------------------------------
-
 class BeamStripping: public Component {
 
 public:
 
     /// Constructor with given name.
-    explicit BeamStripping(const std::string &name);
+    explicit BeamStripping(const std::string& name);
 
     BeamStripping();
-    BeamStripping(const BeamStripping &rhs);
+    BeamStripping(const BeamStripping& rhs);
     virtual ~BeamStripping();
 
     /// Apply visitor to BeamStripping.
-    virtual void accept(BeamlineVisitor &) const;
+    virtual void accept(BeamlineVisitor&) const;
 
-    virtual bool checkBeamStripping(PartBunchBase<double, 3> *bunch, Cyclotron* cycl, const int turnnumber, const double t, const double tstep);
+    virtual bool checkBeamStripping(PartBunchBase<double, 3>* bunch,
+                                    Cyclotron* cycl);
 
-    virtual void initialise(PartBunchBase<double, 3> *bunch, double &startField, double &endField);
+    virtual void initialise(PartBunchBase<double, 3>* bunch,
+                            double& startField, double& endField);
 
-    virtual void initialise(PartBunchBase<double, 3> *bunch, const double &scaleFactor);
+    virtual void initialise(PartBunchBase<double, 3>* bunch,
+                            const double& scaleFactor);
 
     virtual void finalise();
 
     virtual bool bends() const;
 
-    virtual void goOnline(const double &kineticEnergy);
-
+    virtual void goOnline(const double& kineticEnergy);
     virtual void goOffline();
 
     virtual ElementBase::ElementType getType() const;
 
-    virtual void getDimensions(double &zBegin, double &zEnd) const;
+    virtual void getDimensions(double& zBegin, double& zEnd) const;
 
     std::string  getBeamStrippingShape();
 
-    int checkPoint(const double &x, const double &y, const double &z);
+    int checkPoint(const double& x, const double& y, const double& z);
     
-    double checkPressure(const double &x, const double &y);
+    double checkPressure(const double& x, const double& y);
 
-    void setPressure(double pressure) ;
+    void setPressure(double pressure);
     double getPressure() const;
 
-    void setTemperature(double temperature) ;
+    void setTemperature(double temperature);
     double getTemperature() const;
 
     void setPressureMapFN(std::string pmapfn);
@@ -114,7 +116,8 @@ public:
     virtual double getPScale() const;
 
     void setResidualGas(std::string gas);
-    virtual std::string getResidualGas() const;
+    ResidualGas getResidualGas() const;
+    std::string getResidualGasName();
 
     void setStop(bool stopflag);
     virtual bool getStop() const;
@@ -130,7 +133,7 @@ protected:
 private:
 
     ///@{ parameters for BeamStripping
-    std::string gas_m;
+    ResidualGas gas_m;
     double pressure_m;    /// mbar
     std::string pmapfn_m; /// stores the filename of the pressure map
     double pscale_m;      /// a scale factor for the P-field
@@ -145,7 +148,7 @@ private:
     double maxz_m;   /// mm
     ///@}
 
-    ParticleMatterInteractionHandler *parmatint_m;
+    ParticleMatterInteractionHandler* parmatint_m;
 
 protected:
     // object of Matrices including pressure field map and its derivates
@@ -155,4 +158,4 @@ protected:
     PPositions PP;
 };
 
-#endif // CLASSIC_BeamStripping_HH
\ No newline at end of file
+#endif // CLASSIC_BeamStripping_HH
diff --git a/src/Classic/AbsBeamline/CCollimator.cpp b/src/Classic/AbsBeamline/CCollimator.cpp
index a1007272edf6349a809b229bb19fe447026c0031..3ce0cca889b98ad1a50d54d3e1df4a721c0192b9 100644
--- a/src/Classic/AbsBeamline/CCollimator.cpp
+++ b/src/Classic/AbsBeamline/CCollimator.cpp
@@ -82,7 +82,7 @@ bool CCollimator::doCheck(PartBunchBase<double, 3> *bunch, const int /*turnnumbe
     int pflag = 0;
     // now check each particle in bunch
     for (unsigned int i = 0; i < tempnum; ++i) {
-        if (bunch->PType[i] == ParticleType::REGULAR && bunch->R[i](2) < zend_m && bunch->R[i](2) > zstart_m ) {
+        if (bunch->POrigin[i] == ParticleOrigin::REGULAR && bunch->R[i](2) < zend_m && bunch->R[i](2) > zstart_m ) {
             // only now careful check in r
             pflag = checkPoint(bunch->R[i](0), bunch->R[i](1));
             /// bunch->Bin[i] != -1 makes sure the particle is not stored in more than one collimator
@@ -172,4 +172,4 @@ void CCollimator::doSetGeom() {
     //     *gmsg << "point " << i << " ( " << geom_m[i].x << ", " << geom_m[i].y << ")" << endl;
     // }
     // *gmsg << "rmin " << rmin_m << " rmax " << rmax_m << endl;
-}
\ No newline at end of file
+}
diff --git a/src/Classic/AbsBeamline/Degrader.cpp b/src/Classic/AbsBeamline/Degrader.cpp
index 13930d0bcb082581531d3ec566fd941b9d922cb8..7128202ff00b0fb90b5c17ad2c6d3f8d063640c3 100644
--- a/src/Classic/AbsBeamline/Degrader.cpp
+++ b/src/Classic/AbsBeamline/Degrader.cpp
@@ -111,7 +111,7 @@ bool Degrader::applyToReferenceParticle(const Vector_t &R,
     if (!isInMaterial(R(2))) return false;
 
     Vector_t updatedP = P;
-    bool isDead = getParticleMatterInteraction()->computeEnergyLoss(updatedP, RefPartBunch_m->getdT(), false);
+    bool isDead = getParticleMatterInteraction()->computeEnergyLoss(RefPartBunch_m, updatedP, RefPartBunch_m->getdT(), false);
     double deltaP = euclidean_norm(updatedP) - euclidean_norm(P);
     E(2) += deltaP * RefPartBunch_m->getM() / (RefPartBunch_m->getdT() * RefPartBunch_m->getQ() * Physics::c);
 
@@ -188,4 +188,4 @@ ElementBase::ElementType Degrader::getType() const {
 std::string Degrader::getDegraderShape() {
     return "DEGRADER";
 
-}
\ No newline at end of file
+}
diff --git a/src/Classic/AbsBeamline/Stripper.cpp b/src/Classic/AbsBeamline/Stripper.cpp
index 53d326e61151ae1d0e742c715be036abf4e166e0..f0440ca4b1cf3baa839e803692b164caf6da0fd8 100644
--- a/src/Classic/AbsBeamline/Stripper.cpp
+++ b/src/Classic/AbsBeamline/Stripper.cpp
@@ -117,7 +117,7 @@ bool Stripper::doCheck(PartBunchBase<double, 3> *bunch, const int turnnumber, co
 
     Inform gmsgALL("OPAL", INFORM_ALL_NODES);
     for (unsigned int i = 0; i < tempnum; ++i) {
-        if (bunch->PType[i] != ParticleType::REGULAR) continue;
+        if (bunch->POrigin[i] != ParticleOrigin::REGULAR) continue;
 
         double tangle = calculateIncidentAngle(bunch->P[i](0), bunch->P[i](1));
         changeWidth(bunch, i, tstep, tangle);
@@ -142,12 +142,12 @@ bool Stripper::doCheck(PartBunchBase<double, 3> *bunch, const int turnnumber, co
             gmsgALL << level4 << getName() << ": Particle " << bunch->ID[i] << " collide in stripper " << getName() << endl;
             // change charge and mass of PartData when the reference particle hits the stripper.
             if (bunch->ID[i] == 0)
-                bunch->setPType(ParticleType::STRIPPED);
+                bunch->setPOrigin(ParticleOrigin::STRIPPED);
 
             // change the mass and charge
             bunch->M[i] = opmass_m;
             bunch->Q[i] = opcharge_m * Physics::q_e;
-            bunch->PType[i] = ParticleType::STRIPPED;
+            bunch->POrigin[i] = ParticleOrigin::STRIPPED;
 
             int j = 1;
             //create new particles
@@ -158,8 +158,8 @@ bool Stripper::doCheck(PartBunchBase<double, 3> *bunch, const int turnnumber, co
                 bunch->P[index] = bunch->P[i];
                 bunch->Q[index] = bunch->Q[i];
                 bunch->M[index] = bunch->M[i];
-                // once the particle is stripped, change PType from 0 to 1 as a flag so as to avoid repetitive stripping.
-                bunch->PType[index] = ParticleType::STRIPPED;
+                // once the particle is stripped, change POrigin from 0 to 1 as a flag so as to avoid repetitive stripping.
+                bunch->POrigin[index] = ParticleOrigin::STRIPPED;
                 if (bunch->weHaveBins())
                     bunch->Bin[index] = bunch->Bin[i];
 
@@ -176,7 +176,7 @@ bool Stripper::doFinaliseCheck(PartBunchBase<double, 3> *bunch, bool flagNeedUpd
 
     if (!stop_m){
         // change charge and mass of PartData when the reference particle hits the stripper.
-        if (bunch->getPType() == ParticleType::STRIPPED) {
+        if (bunch->getPOrigin() == ParticleOrigin::STRIPPED) {
             bunch->resetM(opmass_m * 1.0e9); // GeV -> eV
             bunch->resetQ(opcharge_m);       // elementary charge
         }
@@ -187,4 +187,4 @@ bool Stripper::doFinaliseCheck(PartBunchBase<double, 3> *bunch, bool flagNeedUpd
 
 ElementBase::ElementType Stripper::getType() const {
     return STRIPPER;
-}
\ No newline at end of file
+}
diff --git a/src/Classic/Algorithms/PartBunchBase.h b/src/Classic/Algorithms/PartBunchBase.h
index be9af282f1a973c900efb1b834b76eb33386bd30..3dfd20502bd5fb3221c13b44b1cb5abdce043ad4 100644
--- a/src/Classic/Algorithms/PartBunchBase.h
+++ b/src/Classic/Algorithms/PartBunchBase.h
@@ -41,13 +41,25 @@ class PartBins;
 class PartBinsCyc;
 class PartData;
 
-namespace ParticleType {
-    enum type { REGULAR,
-                FIELDEMISSION,
-                SECONDARY,
-                NEWSECONDARY,
-                STRIPPED};
-}
+enum class ParticleOrigin:short {REGULAR,
+                               SECONDARY,
+                               STRIPPED};
+
+enum class ParticleType:short {ELECTRON,
+                               PROTON,
+                               POSITRON,
+                               ANTIPROTON,
+                               CARBON,
+                               HMINUS,
+                               URANIUM,
+                               MUON,
+                               DEUTERON,
+                               XENON,
+                               H2P,
+                               ALPHA,
+                               HYDROGEN,
+                               H3P,
+                               UNNAMED};
 
 template <class T, unsigned Dim>
 class PartBunchBase
@@ -65,19 +77,18 @@ public:
     enum UnitState_t { units = 0, unitless = 1 };
 
 public:
-
     virtual ~PartBunchBase() { }
 
-    PartBunchBase(AbstractParticle<T, Dim>* pb, const PartData *ref);
+    PartBunchBase(AbstractParticle<T, Dim>* pb, const PartData* ref);
 
-    PartBunchBase(const PartBunchBase &rhs) = delete; // implement if needed
+    PartBunchBase(const PartBunchBase& rhs) = delete; // implement if needed
 
     /*
      * Bunch common member functions
      */
 
     // This is required since we initialize the Layout and the RegionLayout with default constructor
-    virtual void initialize(FieldLayout_t *fLayout) = 0;
+    virtual void initialize(FieldLayout_t* fLayout) = 0;
 
     bool getIfBeamEmitting();
 
@@ -99,9 +110,9 @@ public:
     //FIXME: unify methods, use convention that all particles have own dt
     void switchOffUnitlessPositions(bool use_dt_per_particle = false);
 
-    void setDistribution(Distribution *d,
-                         std::vector<Distribution *> addedDistributions,
-                         size_t &np);
+    void setDistribution(Distribution* d,
+                         std::vector<Distribution*> addedDistributions,
+                         size_t& np);
 
     bool isGridFixed() const;
 
@@ -120,9 +131,9 @@ public:
 
     bool weHaveBins() const;
 
-    void setPBins(PartBins *pbin);
+    void setPBins(PartBins* pbin);
 
-    void setPBins(PartBinsCyc *pbin);
+    void setPBins(PartBinsCyc* pbin);
 
     /** \brief Emit particles in the given bin
         i.e. copy the particles from the bin structure into the
@@ -155,8 +166,8 @@ public:
     /** \brief returns the number of particles outside of a box defined by x */
     size_t calcNumPartsOutside(Vector_t x);
 
-    void calcLineDensity(unsigned int nBins, std::vector<double> &lineDensity,
-                         std::pair<double, double> &meshInfo);
+    void calcLineDensity(unsigned int nBins, std::vector<double>& lineDensity,
+                         std::pair<double, double>& meshInfo);
 
     void setBeamFrequency(double v);
 
@@ -177,7 +188,6 @@ public:
     /*
        Read out coordinates
      */
-
     virtual double getPx(int i);
     virtual double getPy(int i);
     virtual double getPz(int i);
@@ -194,9 +204,9 @@ public:
 
     virtual void setZ(int i, double zcoo);
 
-    void get_bounds(Vector_t &rmin, Vector_t &rmax);
+    void get_bounds(Vector_t& rmin, Vector_t& rmax);
 
-    void getLocalBounds(Vector_t &rmin, Vector_t &rmax);
+    void getLocalBounds(Vector_t& rmin, Vector_t& rmax);
 
     std::pair<Vector_t, double> getBoundingSphere();
 
@@ -206,7 +216,6 @@ public:
     /*
        Compatibility function push_back
      */
-
     void push_back(OpalParticle p);
 
     void set_part(FVector<double, 6> z, int ii);
@@ -219,8 +228,8 @@ public:
     //  The matrix [b]D[/b] is used to normalise the first two modes.
     //  The maximum normalised amplitudes for these modes are stored
     //  in [b]axmax[/b] and [b]aymax[/b].
-    void maximumAmplitudes(const FMatrix<double, 6, 6> &D,
-                           double &axmax, double &aymax);
+    void maximumAmplitudes(const FMatrix<double, 6, 6>& D,
+                           double& axmax, double& aymax);
 
     void   setdT(double dt);
     double getdT() const;
@@ -240,7 +249,6 @@ public:
     void set_sPos(double s);
 
     double get_gamma() const;
-
     double get_meanKineticEnergy() const;
     Vector_t get_origin() const;
     Vector_t get_maxExtent() const;
@@ -258,7 +266,6 @@ public:
 
     double get_Dx() const;
     double get_Dy() const;
-
     double get_DDx() const;
     double get_DDy() const;
 
@@ -270,7 +277,6 @@ public:
     void get_PBounds(Vector_t &min, Vector_t &max) const;
 
     void calcBeamParameters();
-
     void calcBeamParametersInitial(); // Calculate initial beam parameters before emission.
 
     double getCouplingConstant() const;
@@ -344,21 +350,24 @@ public:
     double getM() const;
     double getP() const;
     double getE() const;
-    ParticleType::type getPType() const;
+    ParticleOrigin getPOrigin() const;
+    ParticleType getPType() const;
+    std::string getPTypeString();
     double getInitialBeta() const;
     double getInitialGamma() const;
     ///@}
     ///@{ Set reference data
     void resetQ(double q);
     void resetM(double m);
-    void setPType(ParticleType::type);
+    void setPOrigin(ParticleOrigin);
+    void setPType(std::string type);
     ///@}
     double getdE() const;
     virtual double getGamma(int i);
     virtual double getBeta(int i);
     virtual void actT();
 
-    const PartData *getReference() const;
+    const PartData* getReference() const;
 
     double getEmissionDeltaT();
 
@@ -373,7 +382,7 @@ public:
 
     void calcEMean();
 
-    Inform &print(Inform &os);
+    Inform& print(Inform& os);
 
     /*
      * (Pure) virtual member functions
@@ -385,14 +394,14 @@ public:
 
     virtual void resetInterpolationCache(bool clearCache = false);
 
-    /** \brief calculates back the max/min of the efield on the grid */
+    //brief calculates back the max/min of the efield on the grid
     virtual VectorPair_t getEExtrema() = 0;
 
     virtual double getRho(int x, int y, int z) = 0;
 
     virtual void computeSelfFields() = 0;
 
-    /** /brief used for self fields with binned distribution */
+    //brief used for self fields with binned distribution
     virtual void computeSelfFields(int bin) = 0;
 
     virtual void computeSelfFields_cycl(double gamma) = 0;
@@ -414,7 +423,7 @@ public:
 //     virtual Mesh_t &getMesh() = 0;
 
 //     virtual void setFieldLayout(FieldLayout_t* fLayout) = 0;
-    virtual FieldLayout_t &getFieldLayout() = 0;
+    virtual FieldLayout_t& getFieldLayout() = 0;
 
     virtual void resizeMesh() { };
 
@@ -433,7 +442,7 @@ public:
     unsigned int getMinimumNumberOfParticlesPerCore() const;
     void setMinimumNumberOfParticlesPerCore(unsigned int n);
 
-    ParticleLayout<T, Dim> & getLayout();
+    ParticleLayout<T, Dim>& getLayout();
     const ParticleLayout<T, Dim>& getLayout() const;
 
     bool getUpdateFlag(UpdateFlags_t f) const;
@@ -485,38 +494,36 @@ public:
     /*
      * Bunch attributes
      */
-
-
     ParticlePos_t& R;
     ParticleIndex_t& ID;
 
-
     // Particle container attributes
-    ParticleAttrib< Vector_t > P;      // particle momentum //  ParticleSpatialLayout<double, 3>::ParticlePos_t P;
-    ParticleAttrib< double >   Q;      // charge per simulation particle, unit: C.
-    ParticleAttrib< double >   M;      // mass per simulation particle, for multi-species particle tracking, unit:GeV/c^2.
-    ParticleAttrib< double >   Phi;    // the electric potential
-    ParticleAttrib< Vector_t > Ef;     // e field vector
-    ParticleAttrib< Vector_t > Eftmp;  // e field vector for gun simulations
-
-    ParticleAttrib< Vector_t > Bf;    // b field vector
-    ParticleAttrib< int >      Bin;   // holds the bin in which the particle is in, if zero particle is marked for deletion
-    ParticleAttrib< double >   dt;   // holds the dt timestep for particle
-
-    ParticleAttrib< short >    PType; // we can distinguish dark current particles from primary particle
-    ParticleAttrib< int >      TriID; // holds the ID of triangle that the particle hit. Only for BoundaryGeometry case.
-    ParticleAttrib< short >    cavityGapCrossed; ///< particle just crossed cavity gap (for ParallelCyclotronTracker)
-
-    ParticleAttrib< short >    bunchNum; // bunch number to which particle belongs (multi-bunch mode)
-
+    ParticleAttrib< Vector_t >     P;      // particle momentum //  ParticleSpatialLayout<double, 3>::ParticlePos_t P;
+    ParticleAttrib< double >       Q;      // charge per simulation particle, unit: C.
+    ParticleAttrib< double >       M;      // mass per simulation particle, for multi-species particle tracking, unit:GeV/c^2.
+    ParticleAttrib< double >       Phi;    // the electric potential
+    ParticleAttrib< Vector_t >     Ef;     // e field vector
+    ParticleAttrib< Vector_t >     Eftmp;  // e field vector for gun simulations
+
+    ParticleAttrib< Vector_t >     Bf;     // b field vector
+    ParticleAttrib< int >          Bin;    // holds the bin in which the particle is in, if zero particle is marked for deletion
+    ParticleAttrib< double >       dt;     // holds the dt timestep for particle
+    ParticleAttrib< ParticleType > PType;  // particle names
+    ParticleAttrib< ParticleOrigin > POrigin;  // we can distinguish dark current particles from primary particle
+    ParticleAttrib< int >          TriID;  // holds the ID of triangle that the particle hit. Only for BoundaryGeometry case.
+    ParticleAttrib< short >        cavityGapCrossed; // particle just crossed cavity gap (for ParallelCyclotronTracker)
+    ParticleAttrib< short >        bunchNum; // bunch number to which particle belongs (multi-bunch mode)
 
     Vector_t RefPartR_m;
     Vector_t RefPartP_m;
-    ParticleType::type refPType_m;
+
     CoordinateSystemTrafo toLabTrafo_m;
 
+    ParticleOrigin refPOrigin_m;
+    ParticleType refPType_m;
+
     // The structure for particle binning
-    PartBins *pbin_m;
+    PartBins* pbin_m;
 
     /// timer for IC, can not be in Distribution.h
     IpplTimings::TimerRef distrReload_m;
@@ -548,13 +555,11 @@ protected:
     /// timer for selfField calculation
     IpplTimings::TimerRef selfFieldTimer_m;
 
+    const PartData* reference;
 
-    const PartData *reference;
-
-
-//     /*
-//       Member variables starts here
-//     */
+    /*
+       Member variables starts here
+     */
 
     // unit state of PartBunch
     UnitState_t unit_state_;
@@ -601,7 +606,6 @@ protected:
 
     /// rms emittance (not normalized)
     Vector_t eps_m;
-
     /// rms normalized emittance
     Vector_t eps_norm_m;
 
@@ -613,7 +617,6 @@ protected:
     /// dispersion x & y
     double Dx_m;
     double Dy_m;
-
     /// derivative of the dispersion
     double DDx_m;
     double DDy_m;
@@ -624,7 +627,7 @@ protected:
     Vektor<int, 3> nr_m;
 
     /// stores the used field solver
-    FieldSolver *fs_m;
+    FieldSolver* fs_m;
 
     double couplingConstant_m;
 
@@ -674,8 +677,7 @@ protected:
 
     std::unique_ptr<size_t[]> globalPartPerNode_m;
 
-
-    Distribution *dist_m;
+    Distribution* dist_m;
 
     // flag to tell if we are a DC-beam
     bool dcBeam_m;
@@ -685,4 +687,4 @@ protected:
 
 #include "PartBunchBase.hpp"
 
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Algorithms/PartBunchBase.hpp b/src/Classic/Algorithms/PartBunchBase.hpp
index 4559a3d35181d8189f8ec3cc0d22c0710ccd3a5b..44a493be1b8228c378ca5f2dfe529b2e1aa3261d 100644
--- a/src/Classic/Algorithms/PartBunchBase.hpp
+++ b/src/Classic/Algorithms/PartBunchBase.hpp
@@ -2,7 +2,7 @@
 // Class PartBunchBase
 //   Base class for representing particle bunches.
 //
-// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
+// Copyright (c) 2008 - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
 // All rights reserved
 //
 // This file is part of OPAL.
@@ -23,7 +23,7 @@
 
 #include "Distribution/Distribution.h"
 
-#include "AbstractObjects/OpalData.h"   // OPAL file
+#include "AbstractObjects/OpalData.h"
 #include "Algorithms/PartBins.h"
 #include "Algorithms/PartBinsCyc.h"
 #include "Algorithms/PartData.h"
@@ -35,10 +35,10 @@
 #include "Utilities/SwitcherError.h"
 #include "Utilities/Util.h"
 
-extern Inform *gmsg;
+extern Inform* gmsg;
 
 template <class T, unsigned Dim>
-PartBunchBase<T, Dim>::PartBunchBase(AbstractParticle<T, Dim>* pb, const PartData *ref)
+PartBunchBase<T, Dim>::PartBunchBase(AbstractParticle<T, Dim>* pb, const PartData* ref)
     : R(*(pb->R_p)),
       ID(*(pb->ID_p)),
       pbin_m(nullptr),
@@ -159,7 +159,7 @@ template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::setEnergyBins(int numberOfEnergyBins) {
     bingamma_m = std::unique_ptr<double[]>(new double[numberOfEnergyBins]);
     binemitted_m = std::unique_ptr<size_t[]>(new size_t[numberOfEnergyBins]);
-    for(int i = 0; i < numberOfEnergyBins; i++)
+    for (int i = 0; i < numberOfEnergyBins; i++)
         binemitted_m[i] = 0;
 }
 
@@ -177,16 +177,16 @@ bool PartBunchBase<T, Dim>::weHaveEnergyBins() {
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::switchToUnitlessPositions(bool use_dt_per_particle) {
 
-    if(unit_state_ == unitless)
+    if (unit_state_ == unitless)
         throw SwitcherError("PartBunch::switchToUnitlessPositions",
                             "Cannot make a unitless PartBunch unitless");
 
     bool hasToReset = false;
-    if(!R.isDirty()) hasToReset = true;
+    if (!R.isDirty()) hasToReset = true;
 
-    for(size_t i = 0; i < getLocalNum(); i++) {
+    for (size_t i = 0; i < getLocalNum(); i++) {
         double dt = getdT();
-        if(use_dt_per_particle)
+        if (use_dt_per_particle)
             dt = this->dt[i];
 
         R[i] /= Vector_t(Physics::c * dt);
@@ -194,24 +194,23 @@ void PartBunchBase<T, Dim>::switchToUnitlessPositions(bool use_dt_per_particle)
 
     unit_state_ = unitless;
 
-    if(hasToReset) R.resetDirtyFlag();
+    if (hasToReset) R.resetDirtyFlag();
 }
 
-
 //FIXME: unify methods, use convention that all particles have own dt
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::switchOffUnitlessPositions(bool use_dt_per_particle) {
 
-    if(unit_state_ == units)
+    if (unit_state_ == units)
         throw SwitcherError("PartBunch::switchOffUnitlessPositions",
                             "Cannot apply units twice to PartBunch");
 
     bool hasToReset = false;
-    if(!R.isDirty()) hasToReset = true;
+    if (!R.isDirty()) hasToReset = true;
 
-    for(size_t i = 0; i < getLocalNum(); i++) {
+    for (size_t i = 0; i < getLocalNum(); i++) {
         double dt = getdT();
-        if(use_dt_per_particle)
+        if (use_dt_per_particle)
             dt = this->dt[i];
 
         R[i] *= Vector_t(Physics::c * dt);
@@ -219,7 +218,7 @@ void PartBunchBase<T, Dim>::switchOffUnitlessPositions(bool use_dt_per_particle)
 
     unit_state_ = units;
 
-    if(hasToReset) R.resetDirtyFlag();
+    if (hasToReset) R.resetDirtyFlag();
 }
 
 
@@ -230,13 +229,11 @@ void PartBunchBase<T, Dim>::do_binaryRepart() {
 
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::setDistribution(Distribution *d,
-                                            std::vector<Distribution *> addedDistributions,
-                                            size_t &np)
-{
+void PartBunchBase<T, Dim>::setDistribution(Distribution* d,
+                                            std::vector<Distribution*> addedDistributions,
+                                            size_t& np) {
     Inform m("setDistribution " );
     dist_m = d;
-
     dist_m->createOpalT(this, addedDistributions, np);
 
 //    if (Options::cZero)
@@ -281,8 +278,7 @@ bool PartBunchBase<T, Dim>::doEmission() {
 
 template <class T, unsigned Dim>
 bool PartBunchBase<T, Dim>::weHaveBins() const {
-
-    if(pbin_m != NULL)
+    if (pbin_m != NULL)
         return pbin_m->weHaveBins();
     else
         return false;
@@ -290,7 +286,7 @@ bool PartBunchBase<T, Dim>::weHaveBins() const {
 
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::setPBins(PartBins *pbin) {
+void PartBunchBase<T, Dim>::setPBins(PartBins* pbin) {
     pbin_m = pbin;
     *gmsg << *pbin_m << endl;
     setEnergyBins(pbin_m->getNBins());
@@ -298,7 +294,7 @@ void PartBunchBase<T, Dim>::setPBins(PartBins *pbin) {
 
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::setPBins(PartBinsCyc *pbin) {
+void PartBunchBase<T, Dim>::setPBins(PartBinsCyc* pbin) {
     pbin_m = pbin;
     setEnergyBins(pbin_m->getNBins());
 }
@@ -329,7 +325,7 @@ void PartBunchBase<T, Dim>::rebin() {
 
 template <class T, unsigned Dim>
 int PartBunchBase<T, Dim>::getLastemittedBin() {
-    if(pbin_m != NULL)
+    if (pbin_m != NULL)
         return pbin_m->getLastemittedBin();
     else
         return 0;
@@ -338,7 +334,7 @@ int PartBunchBase<T, Dim>::getLastemittedBin() {
 
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::setLocalBinCount(size_t num, int bin) {
-    if(pbin_m != NULL) {
+    if (pbin_m != NULL) {
         pbin_m->setPartNum(bin, num);
     }
 }
@@ -351,18 +347,18 @@ void PartBunchBase<T, Dim>::calcGammas() {
 
     size_t s = 0;
 
-    for(int i = 0; i < emittedBins; i++)
+    for (int i = 0; i < emittedBins; i++)
         bingamma_m[i] = 0.0;
 
-    for(unsigned int n = 0; n < getLocalNum(); n++)
+    for (unsigned int n = 0; n < getLocalNum(); n++)
         bingamma_m[this->Bin[n]] += std::sqrt(1.0 + dot(this->P[n], this->P[n]));
 
     std::unique_ptr<size_t[]> particlesInBin(new size_t[emittedBins]);
     reduce(bingamma_m.get(), bingamma_m.get() + emittedBins, bingamma_m.get(), OpAddAssign());
     reduce(binemitted_m.get(), binemitted_m.get() + emittedBins, particlesInBin.get(), OpAddAssign());
-    for(int i = 0; i < emittedBins; i++) {
+    for (int i = 0; i < emittedBins; i++) {
         size_t &pInBin = particlesInBin[i];
-        if(pInBin != 0) {
+        if (pInBin != 0) {
             bingamma_m[i] /= pInBin;
             INFOMSG(level2 << "Bin " << std::setw(3) << i
                            << " gamma = " << std::setw(8) << std::scientific
@@ -378,12 +374,12 @@ void PartBunchBase<T, Dim>::calcGammas() {
     particlesInBin.reset();
 
 
-    if(s != getTotalNum() && !OpalData::getInstance()->hasGlobalGeometry())
+    if (s != getTotalNum() && !OpalData::getInstance()->hasGlobalGeometry())
         ERRORMSG("sum(Bins)= " << s << " != sum(R)= " << getTotalNum() << endl;);
 
-    if(emittedBins >= 2) {
-        for(int i = 1; i < emittedBins; i++) {
-            if(binemitted_m[i - 1] != 0 && binemitted_m[i] != 0)
+    if (emittedBins >= 2) {
+        for (int i = 1; i < emittedBins; i++) {
+            if (binemitted_m[i - 1] != 0 && binemitted_m[i] != 0)
                 INFOMSG(level2 << "d(gamma)= " << 100.0 * std::abs(bingamma_m[i - 1] - bingamma_m[i]) / bingamma_m[i] << " [%] "
                         << "between bin " << i - 1 << " and " << i << endl);
         }
@@ -396,9 +392,9 @@ void PartBunchBase<T, Dim>::calcGammas_cycl() {
 
     const int emittedBins = pbin_m->getLastemittedBin();
 
-    for(int i = 0; i < emittedBins; i++)
+    for (int i = 0; i < emittedBins; i++)
         bingamma_m[i] = 0.0;
-    for(unsigned int n = 0; n < getLocalNum(); n++) {
+    for (unsigned int n = 0; n < getLocalNum(); n++) {
         if ( this->Bin[n] > -1 ) {
             bingamma_m[this->Bin[n]] += std::sqrt(1.0 + dot(this->P[n], this->P[n]));
         }
@@ -406,11 +402,12 @@ void PartBunchBase<T, Dim>::calcGammas_cycl() {
 
     allreduce(*bingamma_m.get(), emittedBins, std::plus<double>());
 
-    for(int i = 0; i < emittedBins; i++) {
-        if(pbin_m->getTotalNumPerBin(i) > 0)
+    for (int i = 0; i < emittedBins; i++) {
+        if (pbin_m->getTotalNumPerBin(i) > 0) {
             bingamma_m[i] /= pbin_m->getTotalNumPerBin(i);
-        else
+        } else {
             bingamma_m[i] = 0.0;
+        }
         INFOMSG("Bin " << i << " : particle number = " << pbin_m->getTotalNumPerBin(i)
                        << " gamma = " << bingamma_m[i] << endl);
     }
@@ -442,7 +439,7 @@ size_t PartBunchBase<T, Dim>::calcNumPartsOutside(Vector_t x) {
     std::size_t localnum = 0;
     const Vector_t meanR = get_rmean();
 
-    for(unsigned long k = 0; k < getLocalNum(); ++ k)
+    for (unsigned long k = 0; k < getLocalNum(); ++ k)
         if (std::abs(R[k](0) - meanR(0)) > x(0) ||
             std::abs(R[k](1) - meanR(1)) > x(1) ||
             std::abs(R[k](2) - meanR(2)) > x(2)) {
@@ -471,9 +468,8 @@ size_t PartBunchBase<T, Dim>::calcNumPartsOutside(Vector_t x) {
  */
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::calcLineDensity(unsigned int nBins,
-                                            std::vector<double> &lineDensity,
-                                            std::pair<double, double> &meshInfo)
-{
+                                            std::vector<double>& lineDensity,
+                                            std::pair<double, double>& meshInfo) {
     Vector_t rmin, rmax;
     get_bounds(rmin, rmax);
 
@@ -509,7 +505,6 @@ void PartBunchBase<T, Dim>::calcLineDensity(unsigned int nBins,
 }
 
 
-
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::boundp() {
     /*
@@ -517,12 +512,12 @@ void PartBunchBase<T, Dim>::boundp() {
      */
 
     IpplTimings::startTimer(boundpTimer_m);
-    //if(!R.isDirty() && stateOfLastBoundP_ == unit_state_) return;
+    //if (!R.isDirty() && stateOfLastBoundP_ == unit_state_) return;
     if ( !(R.isDirty() || ID.isDirty() ) && stateOfLastBoundP_ == unit_state_) return; //-DW
 
     stateOfLastBoundP_ = unit_state_;
 
-    if(!isGridFixed()) {
+    if (!isGridFixed()) {
         const int dimIdx = (dcBeam_m? 2: 3);
 
         /**
@@ -538,7 +533,7 @@ void PartBunchBase<T, Dim>::boundp() {
         Vector_t len = rmax_m - rmin_m;
 
         double volume = 1.0;
-        for(int i = 0; i < dimIdx; i++) {
+        for (int i = 0; i < dimIdx; i++) {
             double length = std::abs(rmax_m[i] - rmin_m[i]);
             if (length < 1e-10) {
                 rmax_m[i] += 1e-10;
@@ -579,7 +574,7 @@ void PartBunchBase<T, Dim>::boundp() {
         }
         //INFOMSG("It is a full boundp hz= " << hr_m << " rmax= " << rmax_m << " rmin= " << rmin_m << endl);
 
-        if(hr_m[0] * hr_m[1] * hr_m[2] <= 0) {
+        if (hr_m[0] * hr_m[1] * hr_m[2] <= 0) {
             throw GeneralClassicException("boundp() ", "h<0, can not build a mesh");
         }
 
@@ -605,15 +600,14 @@ void PartBunchBase<T, Dim>::boundp_destroy() {
     IpplTimings::startTimer(boundpTimer_m);
 
     std::unique_ptr<size_t[]> countLost;
-    if(weHaveBins()) {
+    if (weHaveBins()) {
         const int tempN = pbin_m->getLastemittedBin();
         countLost = std::unique_ptr<size_t[]>(new size_t[tempN]);
-        for(int ii = 0; ii < tempN; ii++) countLost[ii] = 0;
+        for (int ii = 0; ii < tempN; ii++) countLost[ii] = 0;
     }
 
     this->updateDomainLength(nr_m);
 
-
     IpplTimings::startTimer(boundpBoundsTimer_m);
     get_bounds(rmin_m, rmax_m);
     IpplTimings::stopTimer(boundpBoundsTimer_m);
@@ -626,20 +620,20 @@ void PartBunchBase<T, Dim>::boundp_destroy() {
     if (checkfactor != 0) {
         //INFOMSG("checkfactor= " << checkfactor << endl);
         // check the bunch if its full size is larger than checkfactor times of its rms size
-        if(checkfactor < 0) {
+        if (checkfactor < 0) {
             checkfactor *= -1;
             if (len[0] > checkfactor * rrms_m[0] ||
                 len[1] > checkfactor * rrms_m[1] ||
-                len[2] > checkfactor * rrms_m[2])
-            {
-                for(unsigned int ii = 0; ii < this->getLocalNum(); ii++) {
+                len[2] > checkfactor * rrms_m[2]  ) {
+
+                for (unsigned int ii = 0; ii < this->getLocalNum(); ii++) {
                     /* delete the particle if the distance to the beam center
                      * is larger than 8 times of beam's rms size
                      */
                     if (std::abs(R[ii](0) - rmean_m(0)) > checkfactor * rrms_m[0] ||
                         std::abs(R[ii](1) - rmean_m(1)) > checkfactor * rrms_m[1] ||
-                        std::abs(R[ii](2) - rmean_m(2)) > checkfactor * rrms_m[2])
-                    {
+                        std::abs(R[ii](2) - rmean_m(2)) > checkfactor * rrms_m[2]  ) {
+
                         // put particle onto deletion list
                         destroy(1, ii);
                         //update bin parameter
@@ -651,18 +645,17 @@ void PartBunchBase<T, Dim>::boundp_destroy() {
                     }
                 }
             }
-        }
-        else {
+        } else {
             if (len[0] > checkfactor * rrms_m[0] ||
-                len[2] > checkfactor * rrms_m[2])
-            {
-                for(unsigned int ii = 0; ii < this->getLocalNum(); ii++) {
+                len[2] > checkfactor * rrms_m[2]  ) {
+
+                for (unsigned int ii = 0; ii < this->getLocalNum(); ii++) {
                     /* delete the particle if the distance to the beam center
                      * is larger than 8 times of beam's rms size
                      */
                     if (std::abs(R[ii](0) - rmean_m(0)) > checkfactor * rrms_m[0] ||
-                        std::abs(R[ii](2) - rmean_m(2)) > checkfactor * rrms_m[2])
-                    {
+                        std::abs(R[ii](2) - rmean_m(2)) > checkfactor * rrms_m[2]  ) {
+
                         // put particle onto deletion list
                         destroy(1, ii);
                         //update bin parameter
@@ -677,7 +670,7 @@ void PartBunchBase<T, Dim>::boundp_destroy() {
         }
     }
 
-    for(int i = 0; i < dimIdx; i++) {
+    for (int i = 0; i < dimIdx; i++) {
         double length = std::abs(rmax_m[i] - rmin_m[i]);
         rmax_m[i] += dh_m * length;
         rmin_m[i] -= dh_m * length;
@@ -687,7 +680,7 @@ void PartBunchBase<T, Dim>::boundp_destroy() {
     // rescale mesh
     this->updateFields(hr_m, rmin_m);
 
-    if(weHaveBins()) {
+    if (weHaveBins()) {
         pbin_m->updatePartInBin_cyc(countLost.get());
     }
 
@@ -718,21 +711,22 @@ size_t PartBunchBase<T, Dim>::boundp_destroyT() {
     size_t ne = 0;
     const size_t localNum = getLocalNum();
 
-    if(weHaveEnergyBins()) {
+    if (weHaveEnergyBins()) {
         tmpbinemitted = std::unique_ptr<size_t[]>(new size_t[getNumberOfEnergyBins()]);
-        for(int i = 0; i < getNumberOfEnergyBins(); i++) {
+        for (int i = 0; i < getNumberOfEnergyBins(); i++) {
             tmpbinemitted[i] = 0;
         }
-        for(unsigned int i = 0; i < localNum; i++) {
+        for (unsigned int i = 0; i < localNum; i++) {
             if (Bin[i] < 0) {
                 ne++;
                 destroy(1, i);
-            } else
+            } else {
                 tmpbinemitted[Bin[i]]++;
+            }
         }
     } else {
-        for(unsigned int i = 0; i < localNum; i++) {
-            if((Bin[i] < 0) && ((localNum - ne) > minNumParticlesPerCore)) {   // need in minimum x particles per node
+        for (unsigned int i = 0; i < localNum; i++) {
+            if ((Bin[i] < 0) && ((localNum - ne) > minNumParticlesPerCore)) {   // need in minimum x particles per node
                 ne++;
                 destroy(1, i);
             }
@@ -751,9 +745,9 @@ size_t PartBunchBase<T, Dim>::boundp_destroyT() {
     calcBeamParameters();
     gatherLoadBalanceStatistics();
 
-    if(weHaveEnergyBins()) {
+    if (weHaveEnergyBins()) {
         const int lastBin = dist_m->getLastEmittedEnergyBin();
-        for(int i = 0; i < lastBin; i++) {
+        for (int i = 0; i < lastBin; i++) {
             binemitted_m[i] = tmpbinemitted[i];
         }
     }
@@ -772,12 +766,12 @@ size_t PartBunchBase<T, Dim>::destroyT() {
     const size_t totalNum = getTotalNum();
     size_t ne = 0;
 
-    if(weHaveEnergyBins()) {
+    if (weHaveEnergyBins()) {
         tmpbinemitted = std::unique_ptr<size_t[]>(new size_t[getNumberOfEnergyBins()]);
-        for(int i = 0; i < getNumberOfEnergyBins(); i++) {
+        for (int i = 0; i < getNumberOfEnergyBins(); i++) {
             tmpbinemitted[i] = 0;
         }
-        for(unsigned int i = 0; i < localNum; i++) {
+        for (unsigned int i = 0; i < localNum; i++) {
             if (Bin[i] < 0) {
                 destroy(1, i);
                 ++ ne;
@@ -786,8 +780,8 @@ size_t PartBunchBase<T, Dim>::destroyT() {
         }
     } else {
         Inform dmsg("destroy: ", INFORM_ALL_NODES);
-        for(size_t i = 0; i < localNum; i++) {
-            if((Bin[i] < 0)) {
+        for (size_t i = 0; i < localNum; i++) {
+            if ((Bin[i] < 0)) {
                 if ((localNum - ne) > minNumParticlesPerCore) {   // need in minimum x particles per node
                     ne++;
                     destroy(1, i);
@@ -807,7 +801,7 @@ size_t PartBunchBase<T, Dim>::destroyT() {
 
     if (weHaveEnergyBins()) {
         const int lastBin = dist_m->getLastEmittedEnergyBin();
-        for(int i = 0; i < lastBin; i++) {
+        for (int i = 0; i < lastBin; i++) {
             binemitted_m[i] = tmpbinemitted[i];
         }
     }
@@ -819,64 +813,56 @@ size_t PartBunchBase<T, Dim>::destroyT() {
     return totalNum - newTotalNum;
 }
 
+
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getPx(int /*i*/) {
     return 0.0;
 }
 
-
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getPy(int) {
     return 0.0;
 }
 
-
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getPz(int) {
     return 0.0;
 }
 
-
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getPx0(int) {
     return 0.0;
 }
 
-
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getPy0(int) {
     return 0;
 }
 
-
 //ff
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getX(int i) {
     return this->R[i](0);
 }
 
-
 //ff
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getY(int i) {
     return this->R[i](1);
 }
 
-
 //ff
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getZ(int i) {
     return this->R[i](2);
 }
 
-
 //ff
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getX0(int /*i*/) {
     return 0.0;
 }
 
-
 //ff
 template <class T, unsigned Dim>
 double PartBunchBase<T, Dim>::getY0(int /*i*/) {
@@ -890,7 +876,7 @@ void PartBunchBase<T, Dim>::setZ(int /*i*/, double /*zcoo*/) {
 
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::get_bounds(Vector_t &rmin, Vector_t &rmax) {
+void PartBunchBase<T, Dim>::get_bounds(Vector_t& rmin, Vector_t& rmax) {
 
     this->getLocalBounds(rmin, rmax);
 
@@ -911,7 +897,7 @@ void PartBunchBase<T, Dim>::get_bounds(Vector_t &rmin, Vector_t &rmax) {
 
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::getLocalBounds(Vector_t &rmin, Vector_t &rmax) {
+void PartBunchBase<T, Dim>::getLocalBounds(Vector_t& rmin, Vector_t& rmax) {
     const size_t localNum = getLocalNum();
     if (localNum == 0) {
         double maxValue = 1e8;
@@ -1013,12 +999,12 @@ OpalParticle PartBunchBase<T, Dim>::get_part(int ii) {
 
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::maximumAmplitudes(const FMatrix<double, 6, 6> &D,
-                                              double &axmax, double &aymax) {
+void PartBunchBase<T, Dim>::maximumAmplitudes(const FMatrix<double, 6, 6>& D,
+                                              double& axmax, double& aymax) {
     axmax = aymax = 0.0;
     OpalParticle part;
 
-    for(unsigned int ii = 0; ii < getLocalNum(); ii++) {
+    for (unsigned int ii = 0; ii < getLocalNum(); ii++) {
 
         part = get_part(ii);
 
@@ -1210,7 +1196,7 @@ void PartBunchBase<T, Dim>::set_meshEnlargement(double dh) {
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::gatherLoadBalanceStatistics() {
 
-    for(int i = 0; i < Ippl::getNodes(); i++)
+    for (int i = 0; i < Ippl::getNodes(); i++)
         globalPartPerNode_m[i] = 0;
 
     std::size_t localnum = getLocalNum();
@@ -1243,8 +1229,8 @@ void PartBunchBase<T, Dim>::calcBeamParameters() {
 
     get_bounds(rmin_m, rmax_m);
 
-    if(totalNum == 0) {
-        for(unsigned int i = 0 ; i < Dim; i++) {
+    if (totalNum == 0) {
+        for (unsigned int i = 0 ; i < Dim; i++) {
             rmean_m(i) = 0.0;
             pmean_m(i) = 0.0;
             rrms_m(i) = 0.0;
@@ -1261,19 +1247,19 @@ void PartBunchBase<T, Dim>::calcBeamParameters() {
     const size_t intN = calcMoments();
     const double N = static_cast<double>(intN);
 
-    for(unsigned int i = 0 ; i < Dim; i++) {
+    for (unsigned int i = 0 ; i < Dim; i++) {
         rmean_m(i) = centroid_m[2 * i] / N;
         pmean_m(i) = centroid_m[(2 * i) + 1] / N;
         rsqsum(i) = moments_m(2 * i, 2 * i) - N * rmean_m(i) * rmean_m(i);
         psqsum(i) = moments_m((2 * i) + 1, (2 * i) + 1) - N * pmean_m(i) * pmean_m(i);
-        if(psqsum(i) < 0)
+        if (psqsum(i) < 0)
             psqsum(i) = 0;
         rpsum(i) = moments_m((2 * i), (2 * i) + 1) - N * rmean_m(i) * pmean_m(i);
     }
     eps2 = (rsqsum * psqsum - rpsum * rpsum) / (N * N);
     rpsum /= N;
 
-    for(unsigned int i = 0 ; i < Dim; i++) {
+    for (unsigned int i = 0 ; i < Dim; i++) {
         rrms_m(i) = std::sqrt(rsqsum(i) / N);
         prms_m(i) = std::sqrt(psqsum(i) / N);
         eps_norm_m(i)  =  std::sqrt(std::max(eps2(i), zero));
@@ -1291,7 +1277,7 @@ void PartBunchBase<T, Dim>::calcBeamParameters() {
 
     // Find unnormalized emittance.
     double gamma = 0.0;
-    for(size_t i = 0; i < locNp; i++)
+    for (size_t i = 0; i < locNp; i++)
         gamma += std::sqrt(1.0 + dot(P[i], P[i]));
 
     allreduce(&gamma, 1, std::plus<double>());
@@ -1322,14 +1308,14 @@ void PartBunchBase<T, Dim>::calcBeamParametersInitial() {
 
     const double N =  static_cast<double>(getTotalNum());
 
-    if(N == 0) {
+    if (N == 0) {
         rmean_m = Vector_t(0.0);
         pmean_m = Vector_t(0.0);
         rrms_m  = Vector_t(0.0);
         prms_m  = Vector_t(0.0);
         eps_m   = Vector_t(0.0);
     } else {
-        if(Ippl::myNode() == 0) {
+        if (Ippl::myNode() == 0) {
             // fixme:  the following code is crap!
             // Only use one node as this function will get called only once before
             // particles have been emitted (at least in principle).
@@ -1339,19 +1325,19 @@ void PartBunchBase<T, Dim>::calcBeamParametersInitial() {
             const double  N =  static_cast<double>(pbin_m->getNp());
             calcMomentsInitial();
 
-            for(unsigned int i = 0 ; i < Dim; i++) {
+            for (unsigned int i = 0 ; i < Dim; i++) {
                 rmean_m(i) = centroid_m[2 * i] / N;
                 pmean_m(i) = centroid_m[(2 * i) + 1] / N;
                 rsqsum(i) = moments_m(2 * i, 2 * i) - N * rmean_m(i) * rmean_m(i);
                 psqsum(i) = moments_m((2 * i) + 1, (2 * i) + 1) - N * pmean_m(i) * pmean_m(i);
-                if(psqsum(i) < 0)
+                if (psqsum(i) < 0)
                     psqsum(i) = 0;
                 rpsum(i) =  moments_m((2 * i), (2 * i) + 1) - N * rmean_m(i) * pmean_m(i);
             }
             eps2 = (rsqsum * psqsum - rpsum * rpsum) / (N * N);
             rpsum /= N;
 
-            for(unsigned int i = 0 ; i < Dim; i++) {
+            for (unsigned int i = 0 ; i < Dim; i++) {
 
                 rrms_m(i) = std::sqrt(rsqsum(i) / N);
                 prms_m(i) = std::sqrt(psqsum(i) / N);
@@ -1380,7 +1366,7 @@ void PartBunchBase<T, Dim>::setCouplingConstant(double c) {
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::setCharge(double q) {
     qi_m = q;
-    if(getTotalNum() != 0)
+    if (getTotalNum() != 0)
         Q = qi_m;
     else
         WARNMSG("Could not set total charge in PartBunch::setCharge based on getTotalNum" << endl);
@@ -1420,7 +1406,7 @@ void PartBunchBase<T, Dim>::setSolver(FieldSolver *fs) {
        CAN not re-inizialize ParticleLayout
        this is an IPPL issue
      */
-    if(!OpalData::getInstance()->hasBunchAllocated()) {
+    if (!OpalData::getInstance()->hasBunchAllocated()) {
         this->initialize(fs_m->getFieldLayout());
 //         this->setMesh(fs_m->getMesh());
 //         this->setFieldLayout(fs_m->getFieldLayout());
@@ -1430,7 +1416,7 @@ void PartBunchBase<T, Dim>::setSolver(FieldSolver *fs) {
 
 template <class T, unsigned Dim>
 bool PartBunchBase<T, Dim>::hasFieldSolver() {
-    if(fs_m)
+    if (fs_m)
         return fs_m->hasValidSolver();
     else
         return false;
@@ -1440,7 +1426,7 @@ bool PartBunchBase<T, Dim>::hasFieldSolver() {
 /// \brief Return the fieldsolver type if we have a fieldsolver
 template <class T, unsigned Dim>
 std::string PartBunchBase<T, Dim>::getFieldSolverType() const {
-    if(fs_m)
+    if (fs_m)
         return fs_m->getFieldSolverType();
     else
         return "";
@@ -1603,21 +1589,20 @@ double PartBunchBase<T, Dim>::calcMeanPhi() {
     double py[emittedBins];
     double meanPhi = 0.0;
 
-    for(int ii = 0; ii < emittedBins; ii++) {
+    for (int ii = 0; ii < emittedBins; ii++) {
         phi[ii] = 0.0;
         px[ii] = 0.0;
         py[ii] = 0.0;
     }
 
-    for(unsigned int ii = 0; ii < getLocalNum(); ii++) {
-
+    for (unsigned int ii = 0; ii < getLocalNum(); ii++) {
         px[Bin[ii]] += P[ii](0);
         py[Bin[ii]] += P[ii](1);
     }
 
     reduce(px, px + emittedBins, px, OpAddAssign());
     reduce(py, py + emittedBins, py, OpAddAssign());
-    for(int ii = 0; ii < emittedBins; ii++) {
+    for (int ii = 0; ii < emittedBins; ii++) {
         phi[ii] = calculateAngle(px[ii], py[ii]);
         meanPhi += phi[ii];
         INFOMSG("Bin " << ii  << "  mean phi = " << phi[ii] * 180.0 / Physics::pi - 90.0 << "[degree]" << endl);
@@ -1642,31 +1627,31 @@ bool PartBunchBase<T, Dim>::resetPartBinID2(const double eta) {
     calcGammas_cycl();
     int maxbin = pbin_m->getNBins();
     size_t partInBin[maxbin];
-    for(int ii = 0; ii < maxbin; ii++) partInBin[ii] = 0;
+    for (int ii = 0; ii < maxbin; ii++) partInBin[ii] = 0;
 
     double pMin0 = 1.0e9;
     double pMin = 0.0;
     double maxbinIndex = 0;
 
-    for(unsigned long int n = 0; n < getLocalNum(); n++) {
+    for (unsigned long int n = 0; n < getLocalNum(); n++) {
         double temp_betagamma = std::sqrt(std::pow(P[n](0), 2) + std::pow(P[n](1), 2));
-        if(pMin0 > temp_betagamma)
+        if (pMin0 > temp_betagamma)
             pMin0 = temp_betagamma;
     }
     reduce(pMin0, pMin, OpMinAssign());
     INFOMSG("minimal beta*gamma = " << pMin << endl);
 
     double asinh0 = std::asinh(pMin);
-    for(unsigned long int n = 0; n < getLocalNum(); n++) {
+    for (unsigned long int n = 0; n < getLocalNum(); n++) {
 
         double temp_betagamma = std::sqrt(std::pow(P[n](0), 2) + std::pow(P[n](1), 2));
         int itsBinID = std::floor((std::asinh(temp_betagamma) - asinh0) / eta + 1.0E-6);
         Bin[n] = itsBinID;
-        if(maxbinIndex < itsBinID) {
+        if (maxbinIndex < itsBinID) {
             maxbinIndex = itsBinID;
         }
 
-        if(itsBinID >= maxbin) {
+        if (itsBinID >= maxbin) {
             ERRORMSG("The bin number limit is " << maxbin << ", please increase the energy interval and try again" << endl);
             return false;
         } else
@@ -1682,7 +1667,6 @@ bool PartBunchBase<T, Dim>::resetPartBinID2(const double eta) {
     calcGammas_cycl();
 
     return true;
-
 }
 
 
@@ -1733,15 +1717,97 @@ double PartBunchBase<T, Dim>::getE() const {
 
 
 template <class T, unsigned Dim>
-ParticleType::type PartBunchBase<T, Dim>::getPType() const {
+ParticleOrigin PartBunchBase<T, Dim>::getPOrigin() const {
+    return refPOrigin_m;
+}
+
+template <class T, unsigned Dim>
+void PartBunchBase<T, Dim>::setPOrigin(ParticleOrigin origin) {
+    refPOrigin_m = origin;
+}
+
+
+template <class T, unsigned Dim>
+ParticleType PartBunchBase<T, Dim>::getPType() const {
     return refPType_m;
 }
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::setPType(ParticleType::type type) {
-    refPType_m = type;
+std::string PartBunchBase<T, Dim>::getPTypeString() {
+
+    switch (refPType_m) {
+    case ParticleType::ELECTRON:
+        return "ELECTRON";
+    case ParticleType::PROTON:
+        return "PROTON";
+    case ParticleType::POSITRON:
+        return "POSITRON";
+    case ParticleType::ANTIPROTON:
+        return "ANTIPROTON";
+    case ParticleType::CARBON:
+        return "CARBON";
+    case ParticleType::HMINUS:
+        return "HMINUS";
+    case ParticleType::URANIUM:
+        return "URANIUM";
+    case ParticleType::MUON:
+        return "MUON";
+    case ParticleType::DEUTERON:
+        return "DEUTERON";
+    case ParticleType::XENON:
+        return "XENON";
+    case ParticleType::H2P:
+        return "H2P";
+    case ParticleType::ALPHA:
+        return "ALPHA";
+    case ParticleType::HYDROGEN:
+        return "HYDROGEN";
+    case  ParticleType::H3P:
+        return "H3P";
+    default:
+        INFOMSG("Unknown type for OPAL particles" << endl);
+        return "UNNAMED";
+    }
 }
 
+template <class T, unsigned Dim>
+void PartBunchBase<T, Dim>::setPType(std::string type) {
+
+    if (type == "ELECTRON") {
+        refPType_m = ParticleType::ELECTRON;
+    } else if (type == "PROTON") {
+        refPType_m = ParticleType::PROTON;
+    } else if (type == "POSITRON") {
+        refPType_m = ParticleType::POSITRON;
+    } else if (type == "ANTIPROTON") {
+        refPType_m = ParticleType::ANTIPROTON;
+    } else if (type == "CARBON") {
+        refPType_m = ParticleType::CARBON;
+    } else if (type == "HMINUS") {
+        refPType_m = ParticleType::HMINUS;
+    } else if (type == "URANIUM") {
+        refPType_m = ParticleType::URANIUM;
+    } else if (type == "MUON") {
+        refPType_m = ParticleType::MUON;
+    } else if (type == "DEUTERON") {
+        refPType_m = ParticleType::DEUTERON;
+    } else if (type == "XENON") {
+        refPType_m = ParticleType::XENON;
+    } else if (type == "H2P") {
+        refPType_m = ParticleType::H2P;
+    } else if (type == "ALPHA") {
+        refPType_m = ParticleType::ALPHA;
+    } else if (type == "HYDROGEN") {
+        refPType_m = ParticleType::HYDROGEN;
+    } else if (type == "H3P") {
+        refPType_m = ParticleType::H3P;
+    } else {
+        INFOMSG("Unknown type for OPAL particles. Default ParticleType::UNNAMED is set" << endl);
+        refPType_m = ParticleType::UNNAMED;
+    }
+}
+
+
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::resetQ(double q)  {
     const_cast<PartData *>(reference)->setQ(q);
@@ -1785,14 +1851,13 @@ double PartBunchBase<T, Dim>::getBeta(int /*i*/) {
 
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::actT()
-{
+void PartBunchBase<T, Dim>::actT() {
     // do nothing here
 };
 
 
 template <class T, unsigned Dim>
-const PartData *PartBunchBase<T, Dim>::getReference() const {
+const PartData* PartBunchBase<T, Dim>::getReference() const {
     return reference;
 }
 
@@ -1817,7 +1882,7 @@ void PartBunchBase<T, Dim>::calcEMean() {
 
     eKin_m = 0.0;
 
-    for(unsigned int k = 0; k < locNp; k++) {
+    for (unsigned int k = 0; k < locNp; k++) {
         eKin_m += std::sqrt(dot(P[k], P[k]) + 1.0);
     }
 
@@ -1830,9 +1895,9 @@ void PartBunchBase<T, Dim>::calcEMean() {
 }
 
 template <class T, unsigned Dim>
-Inform &PartBunchBase<T, Dim>::print(Inform &os) {
+Inform& PartBunchBase<T, Dim>::print(Inform& os) {
 
-    if(getTotalNum() != 0) {  // to suppress Nans
+    if (getTotalNum() != 0) {  // to suppress Nans
         Inform::FmtFlags_t ff = os.flags();
 
         double pathLength = get_sPos();
@@ -1887,12 +1952,10 @@ size_t PartBunchBase<T, Dim>::calcMoments() {
     std::vector<double> loc_moments(4 * Dim + Dim * ( 2 * Dim + 1 ));
 
     long int totalNum = this->getTotalNum();
-    if (!Options::amr && OpalData::getInstance()->isInOPALCyclMode())
-    {
-        /* FIXME After issue 287 is resolved this shouldn't be necessary
-         * anymore
-         */
-        for(unsigned long k = 0; k < localNum; ++ k) {
+    if (!Options::amr && OpalData::getInstance()->isInOPALCyclMode()) {
+        //FIXME After issue 287 is resolved this shouldn't be necessary anymore
+
+        for (unsigned long k = 0; k < localNum; ++ k) {
             if (ID[k] == 0) {
                 part[1] = P[k](0);
                 part[3] = P[k](1);
@@ -1904,7 +1967,7 @@ size_t PartBunchBase<T, Dim>::calcMoments() {
                 unsigned int l = 2 * Dim;
                 for (unsigned int i = 0; i < 2 * Dim; ++i) {
                     loc_moments[i] -= part[i];
-                    for(unsigned int j = 0; j <= i; j++) {
+                    for (unsigned int j = 0; j <= i; j++) {
                         loc_moments[l++] -= part[i] * part[j];
                     }
                 }
@@ -1922,7 +1985,7 @@ size_t PartBunchBase<T, Dim>::calcMoments() {
         allreduce(totalNum, 1, std::less<long int>());
     }
 
-    for(unsigned long k = 0; k < localNum; ++ k) {
+    for (unsigned long k = 0; k < localNum; ++ k) {
         part[1] = P[k](0);
         part[3] = P[k](1);
         part[5] = P[k](2);
@@ -1933,7 +1996,7 @@ size_t PartBunchBase<T, Dim>::calcMoments() {
         unsigned int l = 2 * Dim;
         for (unsigned int i = 0; i < 2 * Dim; ++i) {
             loc_moments[i] += part[i];
-            for(unsigned int j = 0; j <= i; j++) {
+            for (unsigned int j = 0; j <= i; j++) {
                 loc_moments[l++] += part[i] * part[j];
             }
         }
@@ -1953,7 +2016,7 @@ size_t PartBunchBase<T, Dim>::calcMoments() {
 
     unsigned int l = 2 * Dim;
     for (unsigned int i = 0; i < 2 * Dim; ++i) {
-        for(unsigned int j = 0; j <= i; j++) {
+        for (unsigned int j = 0; j <= i; j++) {
             moments_m(i, j) = loc_moments[l++];
             moments_m(j, i) = moments_m(i, j);
         }
@@ -1987,19 +2050,19 @@ void PartBunchBase<T, Dim>::calcMomentsInitial() {
 
     double part[2 * Dim];
 
-    for(unsigned int i = 0; i < 2 * Dim; ++i) {
+    for (unsigned int i = 0; i < 2 * Dim; ++i) {
         centroid_m[i] = 0.0;
-        for(unsigned int j = 0; j <= i; ++j) {
+        for (unsigned int j = 0; j <= i; ++j) {
             moments_m(i, j) = 0.0;
             moments_m(j, i) = moments_m(i, j);
         }
     }
 
-    for(size_t k = 0; k < pbin_m->getNp(); k++) {
-        for(int binNumber = 0; binNumber < pbin_m->getNBins(); binNumber++) {
+    for (size_t k = 0; k < pbin_m->getNp(); k++) {
+        for (int binNumber = 0; binNumber < pbin_m->getNBins(); binNumber++) {
             std::vector<double> p;
 
-            if(pbin_m->getPart(k, binNumber, p)) {
+            if (pbin_m->getPart(k, binNumber, p)) {
                 part[0] = p.at(0);
                 part[1] = p.at(3);
                 part[2] = p.at(1);
@@ -2007,9 +2070,9 @@ void PartBunchBase<T, Dim>::calcMomentsInitial() {
                 part[4] = p.at(2);
                 part[5] = p.at(5);
 
-                for(unsigned int i = 0; i < 2 * Dim; ++i) {
+                for (unsigned int i = 0; i < 2 * Dim; ++i) {
                     centroid_m[i] += part[i];
-                    for(unsigned int j = 0; j <= i; ++j) {
+                    for (unsigned int j = 0; j <= i; ++j) {
                         moments_m(i, j) += part[i] * part[j];
                     }
                 }
@@ -2017,8 +2080,8 @@ void PartBunchBase<T, Dim>::calcMomentsInitial() {
         }
     }
 
-    for(unsigned int i = 0; i < 2 * Dim; ++i) {
-        for(unsigned int j = 0; j < i; ++j) {
+    for (unsigned int i = 0; i < 2 * Dim; ++i) {
+        for (unsigned int j = 0; j < i; ++j) {
             moments_m(j, i) = moments_m(i, j);
         }
     }
@@ -2035,7 +2098,7 @@ double PartBunchBase<T, Dim>::calculateAngle(double x, double y) {
 
 
 template <class T, unsigned Dim>
-Inform &operator<<(Inform &os, PartBunchBase<T, Dim> &p) {
+Inform& operator<<(Inform &os, PartBunchBase<T, Dim>& p) {
     return p.print(os);
 }
 
@@ -2070,6 +2133,7 @@ void PartBunchBase<T, Dim>::swap(unsigned int i, unsigned int j) {
     std::swap(Bin[i], Bin[j]);
     std::swap(dt[i], dt[j]);
     std::swap(PType[i], PType[j]);
+    std::swap(POrigin[i], POrigin[j]);
     std::swap(TriID[i], TriID[j]);
     std::swap(cavityGapCrossed[i], cavityGapCrossed[j]);
     std::swap(bunchNum[i], bunchNum[j]);
@@ -2095,26 +2159,26 @@ void PartBunchBase<T, Dim>::setBCForDCBeam() {
 
 
 template <class T, unsigned Dim>
-void PartBunchBase<T, Dim>::updateFields(const Vector_t &/*hr*/, const Vector_t &/*origin*/) {
+void PartBunchBase<T, Dim>::updateFields(const Vector_t& /*hr*/, const Vector_t& /*origin*/) {
 }
 
 
 template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::setup(AbstractParticle<T, Dim>* pb) {
+
     pb->addAttribute(P);
     pb->addAttribute(Q);
     pb->addAttribute(M);
     pb->addAttribute(Phi);
     pb->addAttribute(Ef);
     pb->addAttribute(Eftmp);
-
     pb->addAttribute(Bf);
     pb->addAttribute(Bin);
     pb->addAttribute(dt);
     pb->addAttribute(PType);
+    pb->addAttribute(POrigin);
     pb->addAttribute(TriID);
     pb->addAttribute(cavityGapCrossed);
-
     pb->addAttribute(bunchNum);
 
     boundpTimer_m       = IpplTimings::getTimer("Boundingbox");
@@ -2128,7 +2192,6 @@ void PartBunchBase<T, Dim>::setup(AbstractParticle<T, Dim>* pb) {
     distrCreate_m       = IpplTimings::getTimer("Create Distr");
     distrReload_m       = IpplTimings::getTimer("Load Distr");
 
-
     globalPartPerNode_m = std::unique_ptr<size_t[]>(new size_t[Ippl::getNodes()]);
 
     pmsg_m.release();
@@ -2213,7 +2276,7 @@ template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::update() {
     try {
         pbase->update();
-    } catch (const IpplException &ex) {
+    } catch (const IpplException& ex) {
         throw OpalException(ex.where(), ex.what());
     }
 }
@@ -2222,7 +2285,7 @@ template <class T, unsigned Dim>
 void PartBunchBase<T, Dim>::update(const ParticleAttrib<char>& canSwap) {
     try {
         pbase->update(canSwap);
-    } catch (const IpplException &ex) {
+    } catch (const IpplException& ex) {
         throw OpalException(ex.where(), ex.what());
     }
 }
@@ -2282,4 +2345,4 @@ FMatrix<double, 2 * Dim, 2 * Dim> PartBunchBase<T, Dim>::getSigmaMatrix() {
     return sigmaMatrix;
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Air.h b/src/Classic/Physics/Air.h
index 139b5c17d9f6e070880956c38fd31a3fe89ee0a6..ee45271c8227589287ff3b75857f86c02801bcf6 100644
--- a/src/Classic/Physics/Air.h
+++ b/src/Classic/Physics/Air.h
@@ -1,3 +1,24 @@
+//
+// Class Air
+//   Defines Air as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef AIR_H
 #define AIR_H
 
@@ -9,11 +30,12 @@ namespace Physics {
         Air():
             Material(7,
                      14,
-                     0.0012,
-                     37.99,
+                     1.205e-3,
+                     36.62,
                      85.7,
-                     {{3.350, 1.683e3, 1.900e3, 2.513e-2}})
+                     {{2.954, 3.350, 1.683e3, 1.900e3, 2.513e-2,
+                       1.9259, 0.5550, 27.15125, 26.0665, 6.2768}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/AluminaAL2O3.h b/src/Classic/Physics/AluminaAL2O3.h
index ee2609d7398d4ef019de7e975ff0928882a8a14d..2288756f2ff65da4a9df743559b41142155ca4e7 100644
--- a/src/Classic/Physics/AluminaAL2O3.h
+++ b/src/Classic/Physics/AluminaAL2O3.h
@@ -1,3 +1,24 @@
+//
+// Class AluminaAL2O3
+//   Defines Alumina as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef ALUMINAAL2O3_H
 #define ALUMINAAL2O3_H
 
@@ -10,12 +31,13 @@ namespace Physics {
     public:
         AluminaAL2O3():
             Material(50,
-                     101.96,
+                     101.9600768,
                      3.97,
                      27.94,
                      145.2,
-                     {{7.227, 1.121e4, 3.864e2, 4.474e-3}})
+                     {{1.187e1, 1.343e1, 1.069e4, 7.723e2, 2.153e-2,
+                       5.4, 0.53, 103.1, 3.931, 7.767}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Aluminum.h b/src/Classic/Physics/Aluminum.h
index 5e31fb46eeceeff7da8feaa8fe34e408d7bbe608..fbdf7b36b26ef6e7a12e7abff170a39c9e56406e 100644
--- a/src/Classic/Physics/Aluminum.h
+++ b/src/Classic/Physics/Aluminum.h
@@ -1,3 +1,24 @@
+//
+// Class Aluminum
+//   Defines Aluminum as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef ALUMINUM_H
 #define ALUMINUM_H
 
@@ -10,12 +31,13 @@ namespace Physics {
     public:
         Aluminum():
             Material(13,
-                     26.98,
-                     2.7,
+                     26.9815384,
+                     2.699,
                      24.01,
                      166.0,
-                     {{4.739, 2.766e3, 1.645e2, 2.023e-2}})
+                     {{4.154, 4.739, 2.766e3, 1.645e2, 2.023e-2,
+                       2.5, 0.625, 45.7, 0.1, 4.359}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Beryllium.h b/src/Classic/Physics/Beryllium.h
index d7175db2ade1009bd54317830d588388a8def01d..cf4b7df36f1fc788a008b92cf0f172f9d66b8fb8 100644
--- a/src/Classic/Physics/Beryllium.h
+++ b/src/Classic/Physics/Beryllium.h
@@ -1,3 +1,24 @@
+//
+// Class Beryllium
+//   Defines Beryllium as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef BERYLLIUM_H
 #define BERYLLIUM_H
 
@@ -8,12 +29,13 @@ namespace Physics {
     public:
         Beryllium():
             Material(4,
-                     9.012,
+                     9.0121831,
                      1.848,
                      65.19,
                      63.7,
-                     {{2.590, 9.660e2, 1.538e2, 3.475e-2}})
+                     {{2.248, 2.590, 9.660e2, 1.538e2, 3.475e-2,
+                       2.1895, 0.47183, 7.2362, 134.30, 197.96}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/BoronCarbide.h b/src/Classic/Physics/BoronCarbide.h
index 6c07c03e7a7284d6e11456a8403fde41180045df..27ec86d9f94fe4a090bfffcec5063ce5c643f42e 100644
--- a/src/Classic/Physics/BoronCarbide.h
+++ b/src/Classic/Physics/BoronCarbide.h
@@ -1,3 +1,24 @@
+//
+// Class BoronCarbide
+//   Defines BoronCarbide as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef BORONCARBIDE_H
 #define BORONCARBIDE_H
 
@@ -10,12 +31,13 @@ namespace Physics {
     public:
         BoronCarbide():
             Material(26,
-                     55.25,
-                     2.48,
-                     50.14,
+                     55.251,
+                     2.52,
+                     50.13,
                      84.7,
-                     {{3.963, 6065.0, 1243.0, 7.782e-3}})
+                     {{3.519, 3.963, 6065.0, 1243.0, 7.782e-3,
+                       5.013, 0.4707, 85.8, 16.55, 3.211}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Copper.h b/src/Classic/Physics/Copper.h
index 9e3c70697284fffc94e0d50e3677c1e93ff09d22..583127a48ae1dbf5ffcc73d920921a199169882d 100644
--- a/src/Classic/Physics/Copper.h
+++ b/src/Classic/Physics/Copper.h
@@ -1,3 +1,24 @@
+//
+// Class Copper
+//   Defines Copper as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef COPPER_H
 #define COPPER_H
 
@@ -10,12 +31,13 @@ namespace Physics {
     public:
         Copper():
             Material(29,
-                     63.54,
+                     63.546,
                      8.96,
                      12.86,
                      322.0,
-                     {{4.194, 4.649e3, 8.113e1, 2.242e-2}})
+                     {{3.969, 4.194, 4.649e3, 8.113e1, 2.242e-2,
+                       3.114, 0.5236, 76.67, 7.62, 6.385}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Gold.h b/src/Classic/Physics/Gold.h
index 506e54cd11a0df332a966e35025da60ef4ebeccb..b742fddb129dc31786a637d03317c9e949a699a1 100644
--- a/src/Classic/Physics/Gold.h
+++ b/src/Classic/Physics/Gold.h
@@ -1,3 +1,24 @@
+//
+// Class Gold
+//   Defines Gold as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef GOLD_H
 #define GOLD_H
 
@@ -10,12 +31,13 @@ namespace Physics {
     public:
         Gold():
             Material(79,
-                     197,
-                     19.3,
+                     196.966570,
+                     19.32,
                      6.46,
                      790.0,
-                     {{5.458, 7.852e3, 9.758e2, 2.077e-2}})
+                     {{4.844, 5.458, 7.852e3, 9.758e2, 2.077e-2,
+                       3.223, 0.5883, 232.7, 2.954, 1.05}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Graphite.h b/src/Classic/Physics/Graphite.h
index e1cbf0cb21bba5a018dc83d692d7f53e061fd447..2113ed11554a20add7cb6ea0b2ea026cb177b218 100644
--- a/src/Classic/Physics/Graphite.h
+++ b/src/Classic/Physics/Graphite.h
@@ -1,3 +1,24 @@
+//
+// Class Graphite
+//   Defines Graphite as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef GRAPHITE_H
 #define GRAPHITE_H
 
@@ -12,8 +33,9 @@ namespace Physics {
                      2.210,
                      42.70,
                      78.0,
-                     {{2.601, 1.701e3, 1.279e3, 1.638e-2}})
+                     {{0.0, 2.601, 1.701e3, 1.279e3, 1.638e-2,
+                       3.80133, 0.41590, 12.9966, 117.83, 242.28}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/GraphiteR6710.h b/src/Classic/Physics/GraphiteR6710.h
index 4cddd6fe18166bcc5a8844dc31670d2151bcde3b..7a2cad7ab2657b442e348fefcacf8dee9c888fef 100644
--- a/src/Classic/Physics/GraphiteR6710.h
+++ b/src/Classic/Physics/GraphiteR6710.h
@@ -1,3 +1,24 @@
+//
+// Class GraphiteR6710
+//   Defines GraphiteR6710 as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef GRAPHITER6710_H
 #define GRAPHITER6710_H
 
@@ -12,8 +33,9 @@ namespace Physics {
                      1.88,
                      42.70,
                      78.0,
-                     {{2.601, 1.701e3, 1.279e3, 1.638e-2}})
+                     {{0.0, 2.601, 1.701e3, 1.279e3, 1.638e-2,
+                       3.80133, 0.41590, 12.9966, 117.83, 242.28}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Kapton.h b/src/Classic/Physics/Kapton.h
index 9331da245537a838c98c8def68b0a9cd3d2e3811..2c93455e9ff3b07a2fc9e5aca92ea156c750a1be 100644
--- a/src/Classic/Physics/Kapton.h
+++ b/src/Classic/Physics/Kapton.h
@@ -1,3 +1,24 @@
+//
+// Class Kapton
+//   Defines Kapton as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef KAPTON_H
 #define KAPTON_H
 
@@ -9,11 +30,12 @@ namespace Physics {
         Kapton():
             Material(6,
                      12,
-                     1.4,
-                     39.95,
-                     79.6, // source: pstar from NIST
-                     {{2.601, 1.701e3, 1.279e3, 1.638e-2}})
+                     1.420,
+                     40.58,
+                     79.6,
+                     {{0.0, 2.601, 1.701e3, 1.279e3, 1.638e-2,
+                       3.83523, 0.42993, 12.6125, 227.41, 188.97}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Material.cpp b/src/Classic/Physics/Material.cpp
index 74235251e0c82fd4ab2f22c9e09dbc68dbb08cc2..e3d2a6767305535458c878fa9790c18e46e5143c 100644
--- a/src/Classic/Physics/Material.cpp
+++ b/src/Classic/Physics/Material.cpp
@@ -1,3 +1,20 @@
+//
+// Class Material
+//   Base class for representing materials
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #include "Physics/Material.h"
 #include "Physics/Air.h"
 #include "Physics/AluminaAL2O3.h"
@@ -22,7 +39,7 @@ using namespace Physics;
 
 std::map<std::string, std::shared_ptr<Material> > Material::protoTable_sm;
 
-std::shared_ptr<Material> Material::addMaterial(const std::string &name,
+std::shared_ptr<Material> Material::addMaterial(const std::string& name,
                                                 std::shared_ptr<Material> mat_ptr) {
     std::string nameUp = Util::toUpper(name);
     if (protoTable_sm.find(nameUp) != protoTable_sm.end())
@@ -33,7 +50,7 @@ std::shared_ptr<Material> Material::addMaterial(const std::string &name,
     return mat_ptr;
 }
 
-std::shared_ptr<Material> Material::getMaterial(const std::string &name) {
+std::shared_ptr<Material> Material::getMaterial(const std::string& name) {
     std::string nameUp = Util::toUpper(name);
     if (protoTable_sm.find(nameUp) != protoTable_sm.end()) return protoTable_sm[nameUp];
 
@@ -73,4 +90,4 @@ namespace {
                                                titanium);
     auto water         = Material::addMaterial("Water",
                                                std::shared_ptr<Material>(new Water()));
-}
\ No newline at end of file
+}
diff --git a/src/Classic/Physics/Material.h b/src/Classic/Physics/Material.h
index c9c7a1d4219c2101e5e6a5bc5e5e018a395d3ca9..41f20e78fd7846ccc5bf0dcf038cc569ebed3f9a 100644
--- a/src/Classic/Physics/Material.h
+++ b/src/Classic/Physics/Material.h
@@ -1,3 +1,20 @@
+//
+// Class Material
+//   Base class for representing materials
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef MATERIAL_H
 #define MATERIAL_H
 
@@ -11,10 +28,16 @@ namespace Physics {
     class Material {
     public:
         enum FitCoeffs {
-            A2 = 0,
+            A1 = 0,
+            A2,
             A3,
             A4,
-            A5
+            A5,
+            B1,
+            B2,
+            B3,
+            B4,
+            B5
         };
 
         Material(double atomicNumber,
@@ -22,7 +45,7 @@ namespace Physics {
                  double massDensity,
                  double radiationLength,
                  double meanExcitationEnergy,
-                 std::array<double, 4> fitCoefficients):
+                 std::array<double, 10> fitCoefficients):
             atomicNumber_m(atomicNumber),
             atomicMass_m(atomicMass),
             massDensity_m(massDensity),
@@ -38,8 +61,8 @@ namespace Physics {
         double getMeanExcitationEnergy() const; // [eV]
         double getStoppingPowerFitCoefficients(FitCoeffs n) const;
 
-        static std::shared_ptr<Material> getMaterial(const std::string &name);
-        static std::shared_ptr<Material> addMaterial(const std::string &name,
+        static std::shared_ptr<Material> getMaterial(const std::string& name);
+        static std::shared_ptr<Material> addMaterial(const std::string& name,
                                                      std::shared_ptr<Material> mat_ptr);
     private:
         static
@@ -50,7 +73,7 @@ namespace Physics {
         const double massDensity_m;
         const double radiationLength_m;
         const double meanExcitationEnergy_m;
-        const std::array<double,4> stoppingPowerFitCoefficients_m;
+        const std::array<double,10> stoppingPowerFitCoefficients_m;
     };
 
     inline
diff --git a/src/Classic/Physics/Molybdenum.h b/src/Classic/Physics/Molybdenum.h
index 8dda9e5e9a38dbec6a6c76fd4ea5d10da85922c3..346bc43127e7549abfc8acdb1e7521540418eef3 100644
--- a/src/Classic/Physics/Molybdenum.h
+++ b/src/Classic/Physics/Molybdenum.h
@@ -1,3 +1,24 @@
+//
+// Class Molybdenum
+//   Defines Molybdenum as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef MOLYBDENUM_H
 #define MOLYBDENUM_H
 
@@ -10,12 +31,13 @@ namespace Physics {
     public:
         Molybdenum():
             Material(42,
-                     95.94,
+                     95.95,
                      10.22,
-                     9.8,
+                     9.80,
                      424.0,
-                     {{7.248, 9.545e3, 4.802e2, 5.376e-3}})
+                     {{6.424, 7.248, 9.545e3, 4.802e2, 5.376e-3,
+                       9.276, 0.418, 157.1, 8.038, 1.29}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Mylar.h b/src/Classic/Physics/Mylar.h
index 6fa7aa629178af61063adbab2d46dd3006629657..8b98133411f13895f7a94a085227b5274abcc944 100644
--- a/src/Classic/Physics/Mylar.h
+++ b/src/Classic/Physics/Mylar.h
@@ -1,3 +1,24 @@
+//
+// Class Mylar
+//   Defines Mylar as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef MYLAR_H
 #define MYLAR_H
 
@@ -9,11 +30,12 @@ namespace Physics {
         Mylar():
             Material(6.702,
                      12.88,
-                     1.4,
+                     1.400,
                      39.95,
                      78.7,
-                     {{3.350, 1683, 1900, 2.513e-02}})
+                     {{2.954, 3.350, 1683, 1900, 2.513e-02,
+                       1.9259, 0.5550, 27.15125, 26.0665, 6.2768}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Physics.h b/src/Classic/Physics/Physics.h
index 922bea72559bd4506e26f232d620dfedd9bb59d7..00f85a6af77d1d2c349e27feb3927bc6a1c44541 100644
--- a/src/Classic/Physics/Physics.h
+++ b/src/Classic/Physics/Physics.h
@@ -2,7 +2,7 @@
 // Class Physics
 //   A namespace defining various mathematical and physical constants.
 //
-// Copyright (c) 2015-2019, Christof Metzger-Kraus, Helmholtz-Zentrum Berlin
+// Copyright (c) 2015-2021, Christof Metzger-Kraus, Helmholtz-Zentrum Berlin
 //                          Pedro Calvo, CIEMAT, Spain
 // All rights reserved
 //
@@ -24,9 +24,6 @@
 #define CLASSIC_Physics_HH
 
 
-// Class Physics
-// ------------------------------------------------------------------------
-
 namespace Physics {
 
     /// The value of \f[ \pi \f]
@@ -128,6 +125,9 @@ namespace Physics {
     /// The xenon rest mass in GeV
     constexpr double m_xe       = 124 * amu;
 
+    /// The alpha particle rest mass in GeV
+    constexpr double m_alpha    = 4.001506179127 * amu;
+
     /// The hydrogen atom rest mass in GeV
     constexpr double m_h        = 1.00782503224 * amu;
 
@@ -137,7 +137,7 @@ namespace Physics {
     /// The H3+ rest mass in GeV
     constexpr double m_h3p       = 3.02293 * amu;
 
-    constexpr double PMASS      = 1.67262192369e-27;  // kg
+    constexpr double PMASS      = 1.67262192369e-27; // kg
 
     constexpr double EMASS      = 9.1093837015e-31; // kg
 
@@ -149,7 +149,6 @@ namespace Physics {
     constexpr double e0m        = 1.75882001076e+11;
     // e/mc
     constexpr double e0mc       = e0m / c;
-
 };
 
-#endif // CLASSIC_Physics_HH
\ No newline at end of file
+#endif // CLASSIC_Physics_HH
diff --git a/src/Classic/Physics/Titanium.h b/src/Classic/Physics/Titanium.h
index 0b82127264a7200406c08e5335717bfaee6a24ba..a28b8f501f73210362fdac2b04868f7c7f65fe66 100644
--- a/src/Classic/Physics/Titanium.h
+++ b/src/Classic/Physics/Titanium.h
@@ -1,3 +1,24 @@
+//
+// Class Titanium
+//   Defines Titanium as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef TITANIUM_H
 #define TITANIUM_H
 
@@ -10,12 +31,13 @@ namespace Physics {
     public:
         Titanium():
             Material(22,
-                     47.8,
-                     4.54,
+                     47.867,
+                     4.540,
                      16.16,
                      233.0,
-                     {{5.489, 5.260e3, 6.511e2, 8.930e-3}})
+                     {{4.858, 5.489, 5.260e3, 6.511e2, 8.930e-3,
+                       4.71, 0.5087, 65.28, 8.806, 5.948}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Physics/Water.h b/src/Classic/Physics/Water.h
index 5022243b9061da68ac28ad1ba8074201a58bb1d9..7fcf1dcd3a9581f1e9469a3edcbc2247bc58a17e 100644
--- a/src/Classic/Physics/Water.h
+++ b/src/Classic/Physics/Water.h
@@ -1,3 +1,24 @@
+//
+// Class Water
+//   Defines Water as a material for particle-matter interactions
+//
+//   Data taken from Standard Atomic Weight 2019 (https://www.qmul.ac.uk/sbcs/iupac/AtWt/), 
+//   atomic properties from PDG database (https://pdg.lbl.gov/2020/AtomicNuclearProperties)
+//   and fit coefficients from ICRU Report 49.
+//
+// Copyright (c) 2019 - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef WATER_H
 #define WATER_H
 
@@ -8,12 +29,13 @@ namespace Physics {
     public:
         Water():
             Material(10,
-                     18,
+                     18.0152,
                      1,
                      36.08,
-                     75.0, // source: pstar from NIST
-                     {{2.199, 2.393e3, 2.699e3, 1.568e-2}})
+                     75.0,
+                     {{4.015, 4.542, 3.955e3, 4.847e2, 7.904e-3,
+                       2.9590, 0.53255, 34.247, 60.655, 15.153}})
         { }
     };
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Classic/Solvers/BeamStrippingPhysics.cpp b/src/Classic/Solvers/BeamStrippingPhysics.cpp
index bb4cafcb6f11d84cd35af762d3bb7ad8d92e0d76..c03bc202eda16a176004191bb1340b71632e38ec 100644
--- a/src/Classic/Solvers/BeamStrippingPhysics.cpp
+++ b/src/Classic/Solvers/BeamStrippingPhysics.cpp
@@ -1,9 +1,9 @@
 //
 // Class BeamStrippingPhysics
-//   This class provides beam stripping physical processes as
-//   particle matter interaction type.
+//   Defines the physical processes of residual gas 
+//   interactions and Lorentz stripping
 //
-// Copyright (c) 2018-2019, Pedro Calvo, CIEMAT, Spain
+// Copyright (c) 2018-2021, Pedro Calvo, CIEMAT, Spain
 // All rights reserved
 //
 // Implemented as part of the PhD thesis
@@ -20,7 +20,6 @@
 // You should have received a copy of the GNU General Public License
 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
 //
-
 #include "Solvers/BeamStrippingPhysics.hh"
 
 #include "AbsBeamline/BeamStripping.h"
@@ -29,6 +28,7 @@
 #include "Algorithms/PartData.h"
 #include "Physics/Physics.h"
 #include "Structure/LossDataSink.h"
+#include "Utilities/GeneralClassicException.h"
 #include "Utilities/Options.h"
 
 #include "Utility/Inform.h"
@@ -40,37 +40,31 @@
 #include <sys/time.h>
 #include <boost/math/special_functions/chebyshev.hpp>
 
-using Physics::q_e;
-using Physics::m_e;
-using Physics::m_hm;
-using Physics::m_p;
-using Physics::m_h;
-using Physics::m_h2p;
 
 namespace {
     struct InsideTester {
         virtual ~InsideTester() {}
 
-        virtual bool checkHit(const Vector_t &R) = 0;
-        virtual double getPressure(const Vector_t &R) = 0;
+        virtual bool checkHit(const Vector_t& R) = 0;
+        virtual double getPressure(const Vector_t& R) = 0;
     };
     struct BeamStrippingInsideTester: public InsideTester {
-        explicit BeamStrippingInsideTester(ElementBase * el) {
+        explicit BeamStrippingInsideTester(ElementBase* el) {
             bstp_m = static_cast<BeamStripping*>(el);
         }
-        virtual bool checkHit(const Vector_t &R) {
+        virtual bool checkHit(const Vector_t& R) {
             return bstp_m->checkPoint(R(0), R(1), R(2));
         }
-        double getPressure(const Vector_t &R) {
+        double getPressure(const Vector_t& R) {
             return bstp_m->checkPressure(R(0), R(1));
         }
     private:
-        BeamStripping *bstp_m;
+        BeamStripping* bstp_m;
     };
 }
 
 
-BeamStrippingPhysics::BeamStrippingPhysics(const std::string &name, ElementBase *element):
+BeamStrippingPhysics::BeamStrippingPhysics(const std::string& name, ElementBase* element):
     ParticleMatterInteractionHandler(name, element),
     T_m(0.0),
     dT_m(0.0),
@@ -86,11 +80,11 @@ BeamStrippingPhysics::BeamStrippingPhysics(const std::string &name, ElementBase
     rediffusedStat_m(0),
     locPartsInMat_m(0)
 {
-    bstp_m = dynamic_cast<BeamStripping *>(getElement());
+    bstp_m = dynamic_cast<BeamStripping* >(getElement());
     bstpshape_m = element_ref_m->getType();
     lossDs_m = std::unique_ptr<LossDataSink>(new LossDataSink(element_ref_m->getName(), !Options::asciidump));
 
-    const gsl_rng_type * T;
+    const gsl_rng_type* T;
     gsl_rng_env_setup();
     struct timeval tv; // Seed generation based on time
     gettimeofday(&tv,0);
@@ -98,8 +92,6 @@ BeamStrippingPhysics::BeamStrippingPhysics(const std::string &name, ElementBase
     T = gsl_rng_default; // Generator setup
     r_m = gsl_rng_alloc (T);
     gsl_rng_set(r_m, mySeed);
-
-    gas_m = bstp_m->getResidualGas();
 }
 
 
@@ -112,30 +104,30 @@ const std::string BeamStrippingPhysics::getType() const {
     return "BeamStrippingPhysics";
 }
 
-void BeamStrippingPhysics::apply(PartBunchBase<double, 3> *bunch,
-                                 const std::pair<Vector_t, double> &/*boundingSphere*/) {
+void BeamStrippingPhysics::apply(PartBunchBase<double, 3>* bunch,
+                                 const std::pair<Vector_t, double>& /*boundingSphere*/) {
 
     dT_m = bunch->getdT();
 
-    double mass = bunch->getM()*1E-9;
+    ParticleType pType = bunch->getPType();
+    if (pType == ParticleType::PROTON  ||
+        pType == ParticleType::HMINUS  ||
+        pType == ParticleType::H2P     ||
+        pType == ParticleType::HYDROGEN ) {
 
-    if (bunch->get_sPos() != 0) {
-        if (std::abs(mass-m_hm)  < 1E-6 ||
-            std::abs(mass-m_p)   < 1E-6 ||
-            std::abs(mass-m_h2p) < 1E-6 ||
-            std::abs(mass-m_h)   < 1E-6) {
+        if (bunch->get_sPos() != 0) {
             doPhysics(bunch);
         }
-        else {
-           Inform gmsgALL("OPAL", INFORM_ALL_NODES);
-           gmsgALL << getName() << ": Unsupported type of particle for residual gas interactions!"<< endl;
-           gmsgALL << getName() << "-> Beam Stripping Physics not apply"<< endl;
-        }
+    } else {
+        throw GeneralClassicException(
+            "BeamStrippingPhysics::apply",
+            "Particle " + bunch->getPTypeString() +
+            " is not supported for residual stripping interactions!");
     }
 }
 
 
-void BeamStrippingPhysics::doPhysics(PartBunchBase<double, 3> *bunch) {
+void BeamStrippingPhysics::doPhysics(PartBunchBase<double, 3>* bunch) {
     /*
       Do physics if
       -- particle in material
@@ -148,7 +140,7 @@ void BeamStrippingPhysics::doPhysics(PartBunchBase<double, 3> *bunch) {
 
     bool stop = bstp_m->getStop();
 
-    InsideTester *tester;
+    InsideTester* tester;
     tester = new BeamStrippingInsideTester(element_ref_m);
 
     Inform gmsgALL("OPAL", INFORM_ALL_NODES);
@@ -167,10 +159,10 @@ void BeamStrippingPhysics::doPhysics(PartBunchBase<double, 3> *bunch) {
             double beta = std::sqrt(1.0 - 1.0 / (gamma * gamma));
             double deltas = dT_m * beta * Physics::c;
 
-            crossSection(Eng);
+            crossSection(bunch, i, Eng);
             pdead_GS = gasStripping(deltas);
 
-            if (std::abs(mass_m-m_hm) < 1E-6 && charge_m == -q_e) {
+            if (bunch->PType[i] == ParticleType::HMINUS) {
                 cycl_m->apply(bunch->R[i], bunch->P[i], T_m, extE, extB);
                 double B = 0.1 * std::sqrt(extB[0]*extB[0] + extB[1]*extB[1] + extB[2]*extB[2]); //T
                 double E = gamma * beta * Physics::c * B;
@@ -185,10 +177,9 @@ void BeamStrippingPhysics::doPhysics(PartBunchBase<double, 3> *bunch) {
                     stoppedPartStat_m++;
                     gmsgALL << level4 << getName() << ": Particle " << bunch->ID[i]
                             << " is deleted by beam stripping" << endl;
-                }
-                else {
+                } else {
                     secondaryParticles(bunch, i, pdead_LS);
-                    bunch->updateNumTotal();
+                    //bunch->updateNumTotal();
                     gmsgALL << level4 << getName()
                             << ": Total number of particles after beam stripping = "
                             << bunch->getTotalNum() << endl;
@@ -200,12 +191,13 @@ void BeamStrippingPhysics::doPhysics(PartBunchBase<double, 3> *bunch) {
 }
 
 
-void BeamStrippingPhysics::crossSection(double Eng){
+void BeamStrippingPhysics::crossSection(PartBunchBase<double, 3>* bunch, size_t& i, double Eng){
 
-    const double temperature = bstp_m->getTemperature();    // K
+    const double temperature = bstp_m->getTemperature(); // K
+    const ParticleType& pType = bunch->PType[i];
+    const ResidualGas& gas = bstp_m->getResidualGas();
 
     Eng *=1E6; //keV
-
     double Eth = 0.0;
     double a1 = 0.0;
     double a2 = 0.0;
@@ -222,9 +214,9 @@ void BeamStrippingPhysics::crossSection(double Eng){
 
     double molecularDensity[3] ={};
 
-    if (gas_m == "H2") {
+    if (gas == ResidualGas::H2) {
 
-        molecularDensity[0] = 100 * pressure_m / (Physics::kB * q_e * temperature);
+        molecularDensity[0] = 100 * pressure_m / (Physics::kB * Physics::q_e * temperature);
 
         double Emin = 0.0;
         double Emax = 0.0;
@@ -233,37 +225,37 @@ void BeamStrippingPhysics::crossSection(double Eng){
         double CS_c = 0.0;
         double CS_total = 0.0;
 
-        if (std::abs(mass_m-m_hm) < 1E-6 && charge_m == -q_e) {
+        if (pType == ParticleType::HMINUS) {
             // Single-electron detachment - Hydrogen Production
             Emin = csCoefSingle_Hminus_Chebyshev[0];
             Emax = csCoefSingle_Hminus_Chebyshev[1];
             for (int i = 0; i < 9; ++i)
                 a_m[i] = {csCoefSingle_Hminus_Chebyshev[i+2]};
             CS_a = csChebyshevFitting(Eng*1E3, Emin, Emax);
-            
+
             // Double-electron detachment - Proton Production
             Emin = csCoefDouble_Hminus_Chebyshev[0];
             Emax = csCoefDouble_Hminus_Chebyshev[1];
             for (int i = 0; i < 9; ++i)
                 a_m[i] = {csCoefDouble_Hminus_Chebyshev[i+2]};
             CS_b = csChebyshevFitting(Eng*1E3, Emin, Emax);
-        }
-        else if (std::abs(mass_m-m_p) < 1E-6 && charge_m == q_e) {
+
+        } else if (pType == ParticleType::PROTON) {
             // Single-electron capture - Hydrogen Production
             Emin = csCoefSingle_Hplus_Chebyshev[0];
             Emax = csCoefSingle_Hplus_Chebyshev[1];
             for (int i = 0; i < 9; ++i)
                 a_m[i] = {csCoefSingle_Hplus_Chebyshev[i+2]};
             CS_a = csChebyshevFitting(Eng*1E3, Emin, Emax);
-        
+
             // Double-electron capture - Hminus Production
             Emin = csCoefDouble_Hplus_Chebyshev[0];
             Emax = csCoefDouble_Hplus_Chebyshev[1];
             for (int i = 0; i < 9; ++i)
                 a_m[i] = {csCoefDouble_Hplus_Chebyshev[i+2]};
             CS_b = csChebyshevFitting(Eng*1E3, Emin, Emax);
-        }
-        else if (std::abs(mass_m-m_h) < 1E-6 && charge_m == 0.0) {
+
+        } else if (pType == ParticleType::HYDROGEN) {
             // Single-electron detachment - Proton Production
             Eth = csCoefProtonProduction_H_Tabata[0];
             a1 = csCoefProtonProduction_H_Tabata[1];
@@ -274,7 +266,7 @@ void BeamStrippingPhysics::crossSection(double Eng){
             a6 = csCoefProtonProduction_H_Tabata[6];
             CS_a = csAnalyticFunctionTabata(Eng, Eth, a1, a2, 0.0, 0.0, a3, a4) +
                 a5 * csAnalyticFunctionTabata(Eng/a6, Eth/a6, a1, a2, 0.0, 0.0, a3, a4);
-            
+
             // Single-electron capture - Hminus Production
             Eth = csCoefHminusProduction_H_Tabata[0];
             a1 = csCoefHminusProduction_H_Tabata[1];
@@ -291,8 +283,8 @@ void BeamStrippingPhysics::crossSection(double Eng){
             a12 = csCoefHminusProduction_H_Tabata[12];
             CS_b = csAnalyticFunctionTabata(Eng, Eth, a1, a2, a3, a4, a5, a6) +
                 csAnalyticFunctionTabata(Eng, Eth, a7, a8, a9, a10, a11, a12);
-        }
-        else if (std::abs(mass_m-m_h2p) < 1E-6 && charge_m == q_e) {
+
+        } else if (pType == ParticleType::H2P) {
             // Proton production
             Eth = csCoefProtonProduction_H2plus_Tabata[0];
             a1 = csCoefProtonProduction_H2plus_Tabata[1];
@@ -308,14 +300,14 @@ void BeamStrippingPhysics::crossSection(double Eng){
             CS_a = csAnalyticFunctionTabata(Eng, Eth, a1, a2, 0.0, 0.0, a3, a4) + 
                 csAnalyticFunctionTabata(Eng, Eth, a5, a6, 0.0, 0.0, a7, a8) +
                 a9 * csAnalyticFunctionTabata(Eng/a10, Eth/a10, a5, a6, 0.0, 0.0, a7, a8);
-            
+
             // Hydrogen production
             Emin = csCoefHydrogenProduction_H2plus_Chebyshev[0];
             Emax = csCoefHydrogenProduction_H2plus_Chebyshev[1];
             for (int i = 0; i < 9; ++i)
                 a_m[i] = {csCoefHydrogenProduction_H2plus_Chebyshev[i+2]};
             CS_b = csChebyshevFitting(Eng*1E3, Emin, Emax);
-        
+
             // H3+, H
             Eth = csCoefH3plusProduction_H2plus_Tabata[0];
             a1 = csCoefH3plusProduction_H2plus_Tabata[1];
@@ -327,14 +319,13 @@ void BeamStrippingPhysics::crossSection(double Eng){
             CS_c = csAnalyticFunctionTabata(Eng, Eth, a1, a2, a3, a4, a5, a6);
         }
         CS_total = CS_a + CS_b + CS_c;
-    
+
         NCS_a = CS_a * 1E-4 * molecularDensity[0];
         NCS_b = CS_b * 1E-4 * molecularDensity[0];
         NCS_c = CS_c * 1E-4 * molecularDensity[0];
         NCS_total = CS_total * 1E-4 * molecularDensity[0];
-    }
 
-    else if (gas_m == "AIR") {
+    } else if (gas == ResidualGas::AIR) {
 
         static const double fMolarFraction[3] = {
             // Nitrogen
@@ -342,8 +333,8 @@ void BeamStrippingPhysics::crossSection(double Eng){
             //Oxygen
             20.947/100,
             //Argon
-            0.934/100
-        };
+            0.934/100 };
+
         double CS_single[3];
         double CS_double[3];
         double CS_total[3];
@@ -356,9 +347,9 @@ void BeamStrippingPhysics::crossSection(double Eng){
 
         for (int i = 0; i < 3; ++i) {
 
-            molecularDensity[i] = 100 * pressure_m * fMolarFraction[i] / (Physics::kB * q_e * temperature);
+            molecularDensity[i] = 100 * pressure_m * fMolarFraction[i] / (Physics::kB * Physics::q_e * temperature);
 
-            if (std::abs(mass_m-m_hm) < 1E-6 && charge_m == -q_e) {
+            if (pType == ParticleType::HMINUS) {
                 // Single-electron detachment - Hydrogen Production
                 Eth = csCoefSingle_Hminus[i][0];
                 for (int j = 0; j < 8; ++j)
@@ -370,8 +361,8 @@ void BeamStrippingPhysics::crossSection(double Eng){
                 for (int j = 0; j < 8; ++j)
                     b_m[i][j] = csCoefDouble_Hminus[i][j+1];
                 CS_double[i] = csAnalyticFunctionNakai(Eng, Eth, i);
-            }
-            else if (std::abs(mass_m-m_p) < 1E-6 && charge_m == q_e) {
+
+            } else if (pType == ParticleType::PROTON) {
                 // Single-electron capture - Hydrogen Production
                 Eth = csCoefSingle_Hplus[i][0];
                 for (int j = 0; j < 8; ++j)
@@ -386,11 +377,11 @@ void BeamStrippingPhysics::crossSection(double Eng){
                 if (b_m[i][7] != 0) {
                     CS_double[i] = csAnalyticFunctionNakai(Eng, Eth, i) +
                         b_m[i][6] * csAnalyticFunctionNakai(Eng/b_m[i][7], Eth/b_m[i][7], i);
-                }
-                else
+                } else {
                     CS_double[i] = csAnalyticFunctionNakai(Eng, Eth, i);
-            }
-            else if (std::abs(mass_m-m_h) < 1E-6 && charge_m == 0.0) {
+                }
+
+            } else if (pType == ParticleType::HYDROGEN) {
                 // Single-electron detachment - Proton Production
                 Eth = csCoefSingleLoss_H[i][0];
                 for (int j = 0; j < 8; ++j)
@@ -404,11 +395,10 @@ void BeamStrippingPhysics::crossSection(double Eng){
                 if (b_m[i][7] != 0) {
                     CS_double[i] = csAnalyticFunctionNakai(Eng, Eth, i) +
                         b_m[i][6] * csAnalyticFunctionNakai(Eng/b_m[i][7], Eth/b_m[i][7], i);
-                }
-                else
+                } else {
                     CS_double[i] = csAnalyticFunctionNakai(Eng, Eth, i);
-            }
-            else {
+                }
+            } else {
                 CS_single[i] = {0.0};
                 CS_double[i] = {0.0};
             }
@@ -426,13 +416,12 @@ void BeamStrippingPhysics::crossSection(double Eng){
         NCS_b = NCS_double_all;
         NCS_total = NCS_total_all;
     }
-
 }
 
 
 double BeamStrippingPhysics::csAnalyticFunctionNakai(double Eng, double Eth, int &i) {
 
-    const double E_R = Physics::E_ryd*1e6 * m_h / m_e; //keV
+    const double E_R = Physics::E_ryd*1e6 * Physics::m_h / Physics::m_e; //keV
     const double sigma_0 = 1E-16;
     double sigma = 0.0; //cm2
     if (Eng > Eth) {
@@ -447,8 +436,8 @@ double BeamStrippingPhysics::csAnalyticFunctionNakai(double Eng, double Eth, int
 }
 
 double BeamStrippingPhysics::csAnalyticFunctionTabata(double Eng, double Eth,
-                                                double a1, double a2, double a3, double a4, double a5, double a6) {
-
+                                                      double a1, double a2, double a3,
+                                                      double a4, double a5, double a6) {
     const double sigma_0 = 1E-16;
     double sigma = 0.0; //cm2
     if (Eng > Eth) {
@@ -479,7 +468,7 @@ double BeamStrippingPhysics::csChebyshevFitting(double Eng, double Emin, double
 }
 
 
-bool BeamStrippingPhysics::gasStripping(double &deltas) {
+bool BeamStrippingPhysics::gasStripping(double& deltas) {
 
     double xi = gsl_rng_uniform(r_m);
     double fg = 1-std::exp(-NCS_total*deltas);
@@ -487,7 +476,7 @@ bool BeamStrippingPhysics::gasStripping(double &deltas) {
     return (fg >= xi);
 }
 
-bool BeamStrippingPhysics::lorentzStripping(double &gamma, double &E) {
+bool BeamStrippingPhysics::lorentzStripping(double& gamma, double& E) {
 
     double xi = gsl_rng_uniform(r_m);
 
@@ -497,93 +486,92 @@ bool BeamStrippingPhysics::lorentzStripping(double &gamma, double &E) {
 //      tau = (A1/E) * std::exp(A2/E);
 
     //Theoretical
-    const double eps0 = 0.75419 * q_e;
-    const double hbar = Physics::h_bar*1E9*q_e;
-    const double me = m_e*1E9*q_e/(Physics::c*Physics::c);
+    const double eps0 = 0.75419 * Physics::q_e;
+    const double hbar = Physics::h_bar * 1E9 * Physics::q_e;
+    const double me = Physics::m_e * 1E9 * Physics::q_e / (Physics::c*Physics::c);
     const double p = 0.0126;
     const double S0 = 0.783;
     const double a = 2.01407/Physics::a0;
     const double k0 = std::sqrt(2 * me * eps0)/hbar;
     const double N = (std::sqrt(2 * k0 * (k0+a) * (2*k0+a)))/a;
-    double zT = eps0 / (q_e * E);
+    double zT = eps0 / (Physics::q_e * E);
     double tau = (4 * me * zT)/(S0 * N * N * hbar * (1+p)*(1+p) * (1-1/(2*k0*zT))) * std::exp(4*k0*zT/3);
     double fL = 1 - std::exp( - dT_m / (gamma * tau));
 
     return (fL >= xi);
 }
 
-void BeamStrippingPhysics::secondaryParticles(PartBunchBase<double, 3> *bunch, size_t &i, bool pdead_LS) {
+void BeamStrippingPhysics::secondaryParticles(PartBunchBase<double, 3>* bunch, size_t& i, bool pdead_LS) {
 
     double r = gsl_rng_uniform(r_m);
 
+    const ParticleType& pType = bunch->PType[i];
+
     // change the mass_m and charge_m
-    if (std::abs(mass_m-m_hm) < 1E-6 && charge_m == -q_e) {
-        if (pdead_LS == true)
+    if (pType == ParticleType::HMINUS) {
+        if (pdead_LS == true) {
             transformToHydrogen(bunch, i);
-        else {
+        } else {
             if (r > NCS_b/NCS_total)
                 transformToHydrogen(bunch, i);
             else
                 transformToProton(bunch, i);
         }
-    }
 
-    else if (std::abs(mass_m-m_p) < 1E-6 && charge_m == q_e) {
+    } else if (pType == ParticleType::PROTON) {
         if (r > NCS_b/NCS_total)
             transformToHydrogen(bunch, i);
         else
             transformToHminus(bunch, i);
-    }
 
-    else if (std::abs(mass_m-m_h) < 1E-6 && charge_m == 0.0) {
+    } else if (pType == ParticleType::HYDROGEN) {
         if (r > NCS_b/NCS_total)
             transformToProton(bunch, i);
         else
             transformToHminus(bunch, i);
-    }
 
-    else if (std::abs(mass_m-m_h2p) < 1E-6 && charge_m == q_e) {
-        if (NCS_c>NCS_b && NCS_b>NCS_a){
+    } else if (pType == ParticleType::H2P) {
+        if (NCS_c>NCS_b && NCS_b>NCS_a) {
             if (r > (NCS_a+NCS_b)/NCS_total)
                 transformToH3plus(bunch, i);
             else if (r > NCS_a/NCS_total)
                 transformToHydrogen(bunch, i);
             else
                 transformToProton(bunch, i);
-        }
-        else if (NCS_a>NCS_b && NCS_b>NCS_c) {
+
+        } else if (NCS_a>NCS_b && NCS_b>NCS_c) {
             if (r > (NCS_c+NCS_b)/NCS_total)
                 transformToProton(bunch, i);
             else if (r > NCS_c/NCS_total)
                 transformToHydrogen(bunch, i);
             else
                 transformToH3plus(bunch, i);
-        }
-        else if (NCS_a>NCS_b && NCS_c>NCS_a) {
+
+        } else if (NCS_a>NCS_b && NCS_c>NCS_a) {
             if (r > (NCS_a+NCS_b)/NCS_total)
                 transformToH3plus(bunch, i);
             else if (r > NCS_b/NCS_total)
                 transformToProton(bunch, i);
             else
                 transformToHydrogen(bunch, i);
-        }
-        else if (NCS_a>NCS_c && NCS_c>NCS_b) {
+
+        } else if (NCS_a>NCS_c && NCS_c>NCS_b) {
             if (r > (NCS_c+NCS_b)/NCS_total)
                 transformToProton(bunch, i);
             else if (r > NCS_b/NCS_total)
                 transformToH3plus(bunch, i);
             else
                 transformToHydrogen(bunch, i);
-        }
-        else if (NCS_b>NCS_c && NCS_b>NCS_a && NCS_a>NCS_c) {
+
+        } else if (NCS_b>NCS_c && NCS_b>NCS_a && NCS_a>NCS_c) {
             if (r > (NCS_c+NCS_a)/NCS_total)
                 transformToHydrogen(bunch, i);
             else if (r > NCS_c/NCS_total)
                 transformToProton(bunch, i);
             else
                 transformToH3plus(bunch, i);
-        }
-        else {
+
+        } else {
             if (r > (NCS_c+NCS_a)/NCS_total)
                 transformToHydrogen(bunch, i);
             else if (r > NCS_a/NCS_total)
@@ -593,39 +581,43 @@ void BeamStrippingPhysics::secondaryParticles(PartBunchBase<double, 3> *bunch, s
         }
     }
 
-    bunch->PType[i] = ParticleType::SECONDARY;
+    bunch->POrigin[i] = ParticleOrigin::SECONDARY;
 
     if (bunch->weHaveBins())
         bunch->Bin[bunch->getLocalNum()-1] = bunch->Bin[i];
 }
 
-void BeamStrippingPhysics::transformToProton(PartBunchBase<double, 3> *bunch, size_t &i) {
+void BeamStrippingPhysics::transformToProton(PartBunchBase<double, 3>* bunch, size_t& i) {
     Inform gmsgALL("OPAL", INFORM_ALL_NODES);
     gmsgALL << level4 << getName() << ": Particle " << bunch->ID[i]
             << " is transformed to proton" << endl;
-    bunch->M[i] = m_p;
-    bunch->Q[i] = q_e;
+    bunch->M[i] = Physics::m_p;
+    bunch->Q[i] = Physics::q_e;
+    bunch->PType[i] = ParticleType::PROTON;
 }
-void BeamStrippingPhysics::transformToHydrogen(PartBunchBase<double, 3> *bunch, size_t &i) {
+void BeamStrippingPhysics::transformToHydrogen(PartBunchBase<double, 3>* bunch, size_t& i) {
     Inform gmsgALL("OPAL", INFORM_ALL_NODES);
     gmsgALL << level4 << getName() << ": Particle " << bunch->ID[i]
             << " is transformed to neutral hydrogen" << endl;
-    bunch->M[i] = m_h;
+    bunch->M[i] = Physics::m_h;
     bunch->Q[i] = 0.0;
+    bunch->PType[i] = ParticleType::HYDROGEN;
 }
-void BeamStrippingPhysics::transformToHminus(PartBunchBase<double, 3> *bunch, size_t &i) {
+void BeamStrippingPhysics::transformToHminus(PartBunchBase<double, 3>* bunch, size_t& i) {
     Inform gmsgALL("OPAL", INFORM_ALL_NODES);
     gmsgALL << level4 << getName() << ": Particle " << bunch->ID[i]
             << " is transformed to negative hydrogen ion" << endl;
-    bunch->M[i] = m_hm;
-    bunch->Q[i] = -q_e;
+    bunch->M[i] = Physics::m_hm;
+    bunch->Q[i] = -Physics::q_e;
+    bunch->PType[i] = ParticleType::HMINUS;
 }
-void BeamStrippingPhysics::transformToH3plus(PartBunchBase<double, 3> *bunch, size_t &i) {
+void BeamStrippingPhysics::transformToH3plus(PartBunchBase<double, 3>* bunch, size_t& i) {
     Inform gmsgALL("OPAL", INFORM_ALL_NODES);
     gmsgALL << level4 << getName() << ": Particle " << bunch->ID[i]
             << " is transformed to H3+" << endl;
     bunch->M[i] = Physics::m_h3p;
-    bunch->Q[i] = q_e;
+    bunch->Q[i] = Physics::q_e;
+    bunch->PType[i] = ParticleType::H3P;
 }
 
 void BeamStrippingPhysics::print(Inform& /*msg*/) {
@@ -701,4 +693,4 @@ const double BeamStrippingPhysics::csCoefHydrogenProduction_H2plus_Chebyshev[11]
     2.00E+03, 1.00E+05, -70.670173645, -0.632612288, -0.6065212488, -0.0915143117, -0.0121710282, 0.0168179292, 0.0104796877, 0, 0
 };
 double BeamStrippingPhysics::a_m[9] = {};
-double BeamStrippingPhysics::b_m[3][9] = {};
\ No newline at end of file
+double BeamStrippingPhysics::b_m[3][9] = {};
diff --git a/src/Classic/Solvers/BeamStrippingPhysics.hh b/src/Classic/Solvers/BeamStrippingPhysics.hh
index 8aa88ae3b72cc416dd63bb961fbaa830c633822a..feed19f14f7167f70c862366456572faa2a050cc 100644
--- a/src/Classic/Solvers/BeamStrippingPhysics.hh
+++ b/src/Classic/Solvers/BeamStrippingPhysics.hh
@@ -1,9 +1,9 @@
 //
 // Class BeamStrippingPhysics
-//   This class provides beam stripping physical processes as
-//   particle matter interaction type.
+//   Defines the physical processes of residual gas 
+//   interactions and Lorentz stripping
 //
-// Copyright (c) 2018-2019, Pedro Calvo, CIEMAT, Spain
+// Copyright (c) 2018-2021, Pedro Calvo, CIEMAT, Spain
 // All rights reserved
 //
 // Implemented as part of the PhD thesis
@@ -43,13 +43,13 @@ class BeamStrippingPhysics: public ParticleMatterInteractionHandler {
 
 public:
 
-    BeamStrippingPhysics(const std::string &name, ElementBase *element);
+    BeamStrippingPhysics(const std::string& name, ElementBase* element);
     ~BeamStrippingPhysics();
 
     void setCyclotron(Cyclotron* cycl) { cycl_m = cycl; };
 
-    virtual void apply(PartBunchBase<double, 3> *bunch,
-                       const std::pair<Vector_t, double> &boundingSphere);
+    virtual void apply(PartBunchBase<double, 3>* bunch,
+                       const std::pair<Vector_t, double>& boundingSphere);
 
     virtual const std::string getType() const;
     virtual void print(Inform& msg);
@@ -60,46 +60,47 @@ public:
     virtual size_t getParticlesInMat() {return locPartsInMat_m;}
     virtual unsigned getRediffused() {return rediffusedStat_m;}
     virtual unsigned int getNumEntered() {return bunchToMatStat_m;}
-    inline void doPhysics(PartBunchBase<double, 3> *bunch);
+
+    inline void doPhysics(PartBunchBase<double, 3>* bunch);
 
 private:
 
-    void crossSection(double Eng);
+    void crossSection(PartBunchBase<double, 3>* bunch, size_t& i, double Eng);
 
-    double csAnalyticFunctionNakai(double Eng, double Eth, int &i);
+    double csAnalyticFunctionNakai(double Eng, double Eth, int& i);
     
     double csAnalyticFunctionTabata(double Eng, double Eth,
-                            double a1, double a2, double a3, double a4, double a5, double a6);
+                                    double a1, double a2, double a3,
+                                    double a4, double a5, double a6);
                               
     double csChebyshevFitting(double Eng, double Emin, double Emax);
 
-    bool gasStripping(double &deltas);
-
-    bool lorentzStripping(double &gamma, double &E);
+    bool gasStripping(double& deltas);
+    bool lorentzStripping(double& gamma, double& E);
 
-    void secondaryParticles(PartBunchBase<double, 3> *bunch, size_t &i, bool pdead_LS);
-    void transformToProton(PartBunchBase<double, 3> *bunch, size_t &i);
-    void transformToHydrogen(PartBunchBase<double, 3> *bunch, size_t &i);
-    void transformToHminus(PartBunchBase<double, 3> *bunch, size_t &i);
-    void transformToH3plus(PartBunchBase<double, 3> *bunch, size_t &i);
+    void secondaryParticles(PartBunchBase<double, 3>* bunch, size_t& i, bool pdead_LS);
+    void transformToProton(PartBunchBase<double, 3>* bunch, size_t& i);
+    void transformToHydrogen(PartBunchBase<double, 3>* bunch, size_t& i);
+    void transformToHminus(PartBunchBase<double, 3>* bunch, size_t& i);
+    void transformToH3plus(PartBunchBase<double, 3>* bunch, size_t& i);
 
-    bool computeEnergyLoss(Vector_t &/*P*/, const double /*deltat*/, bool /*includeFluctuations*/) const {
+    bool computeEnergyLoss(PartBunchBase<double, 3>* /*bunch*/,
+                           Vector_t& /*P*/,
+                           const double /*deltat*/,
+                           bool /*includeFluctuations*/) const {
         return false;
     }
 
-    Cyclotron *cycl_m;
-    BeamStripping *bstp_m;
+    Cyclotron* cycl_m;
+    BeamStripping* bstp_m;
     ElementBase::ElementType bstpshape_m;
 
-    gsl_rng * r_m;
-
-    double T_m;    /// s
-    double dT_m;   /// s
+    gsl_rng* r_m;
 
+    double T_m;    // s
+    double dT_m;   // s
     double mass_m;
     double charge_m;
-
-    std::string gas_m;
     double pressure_m;
 
     std::unique_ptr<LossDataSink> lossDs_m;
@@ -136,4 +137,4 @@ private:
     static double b_m[3][9];
 };
 
-#endif //BEAMSTRIPPINGPHYSICS_HH
\ No newline at end of file
+#endif //BEAMSTRIPPINGPHYSICS_HH
diff --git a/src/Classic/Solvers/CollimatorPhysics.cpp b/src/Classic/Solvers/CollimatorPhysics.cpp
index 009b98410387117f9241454f529b1379bca91074..59a43f190b7c2beb912ee410d4eaa582016dc159 100644
--- a/src/Classic/Solvers/CollimatorPhysics.cpp
+++ b/src/Classic/Solvers/CollimatorPhysics.cpp
@@ -1,9 +1,9 @@
 //
 // Class CollimatorPhysics
+//   Defines the physical processes of beam scattering 
+//   and energy loss by heavy charged particles
 //
-// Defines the collimator physics models
-//
-// Copyright (c) 2009 - 2020, Bi, Yang, Stachel, Adelmann
+// Copyright (c) 2009 - 2021, Bi, Yang, Stachel, Adelmann
 //                            Paul Scherrer Institut, Villigen PSI, Switzerland
 // All rights reserved.
 //
@@ -17,7 +17,6 @@
 // You should have received a copy of the GNU General Public License
 // along with OPAL.  If not, see <https://www.gnu.org/licenses/>.
 //
-
 #include "Solvers/CollimatorPhysics.hh"
 #include "Physics/Physics.h"
 #include "Physics/Material.h"
@@ -39,63 +38,65 @@
 
 #include <gsl/gsl_randist.h>
 
+#include <algorithm>
 #include <cmath>
-#include <iostream>
 #include <fstream>
-#include <algorithm>
+#include <iostream>
 
 #include <sys/time.h>
 
 namespace {
     struct DegraderInsideTester: public InsideTester {
-        explicit DegraderInsideTester(ElementBase * el) {
+        explicit DegraderInsideTester(ElementBase* el) {
             deg_m = static_cast<Degrader*>(el);
         }
         virtual
-        bool checkHit(const Vector_t &R) override {
+        bool checkHit(const Vector_t& R) override {
             return deg_m->isInMaterial(R(2));
         }
 
     private:
-        Degrader *deg_m;
+        Degrader* deg_m;
     };
 
     struct CollimatorInsideTester: public InsideTester {
-        explicit CollimatorInsideTester(ElementBase * el) {
+        explicit CollimatorInsideTester(ElementBase* el) {
             col_m = static_cast<CCollimator*>(el);
         }
         virtual
-        bool checkHit(const Vector_t &R)  override {
+        bool checkHit(const Vector_t& R)  override {
             return col_m->checkPoint(R(0), R(1));
         }
 
     private:
-        CCollimator *col_m;
+        CCollimator* col_m;
     };
 
     struct FlexCollimatorInsideTester: public InsideTester {
-        explicit FlexCollimatorInsideTester(ElementBase * el) {
+        explicit FlexCollimatorInsideTester(ElementBase* el) {
             col_m = static_cast<FlexibleCollimator*>(el);
         }
 
         virtual
-        bool checkHit(const Vector_t &R)  override {
+        bool checkHit(const Vector_t& R)  override {
             return col_m->isStopped(R);
         }
 
     private:
-        FlexibleCollimator *col_m;
+        FlexibleCollimator* col_m;
     };
 }
 
-CollimatorPhysics::CollimatorPhysics(const std::string &name,
-                                     ElementBase *element,
-                                     std::string &material,
+CollimatorPhysics::CollimatorPhysics(const std::string& name,
+                                     ElementBase* element,
+                                     std::string& material,
                                      bool enableRutherford,
                                      double lowEnergyThr):
     ParticleMatterInteractionHandler(name, element),
     T_m(0.0),
     dT_m(0.0),
+    mass_m(0.0),
+    charge_m(0.0),
     material_m(material),
     hitTester_m(nullptr),
     Z_m(0),
@@ -103,6 +104,7 @@ CollimatorPhysics::CollimatorPhysics(const std::string &name,
     rho_m(0.0),
     X0_m(0.0),
     I_m(0.0),
+    A1_c(0.0),
     A2_c(0.0),
     A3_c(0.0),
     A4_c(0.0),
@@ -151,8 +153,8 @@ CollimatorPhysics::CollimatorPhysics(const std::string &name,
 
     lossDs_m = std::unique_ptr<LossDataSink>(new LossDataSink(getName(), !Options::asciidump));
 
-    DegraderApplyTimer_m = IpplTimings::getTimer("DegraderApply");
-    DegraderLoopTimer_m = IpplTimings::getTimer("DegraderLoop");
+    DegraderApplyTimer_m   = IpplTimings::getTimer("DegraderApply");
+    DegraderLoopTimer_m    = IpplTimings::getTimer("DegraderLoop");
     DegraderDestroyTimer_m = IpplTimings::getTimer("DegraderDestroy");
 }
 
@@ -177,14 +179,20 @@ void  CollimatorPhysics::configureMaterialParameters() {
     rho_m = material->getMassDensity();
     X0_m = material->getRadiationLength();
     I_m = material->getMeanExcitationEnergy();
+    A1_c = material->getStoppingPowerFitCoefficients(Physics::Material::A1);
     A2_c = material->getStoppingPowerFitCoefficients(Physics::Material::A2);
     A3_c = material->getStoppingPowerFitCoefficients(Physics::Material::A3);
     A4_c = material->getStoppingPowerFitCoefficients(Physics::Material::A4);
     A5_c = material->getStoppingPowerFitCoefficients(Physics::Material::A5);
+    B1_c = material->getStoppingPowerFitCoefficients(Physics::Material::B1);
+    B2_c = material->getStoppingPowerFitCoefficients(Physics::Material::B2);
+    B3_c = material->getStoppingPowerFitCoefficients(Physics::Material::B3);
+    B4_c = material->getStoppingPowerFitCoefficients(Physics::Material::B4);
+    B5_c = material->getStoppingPowerFitCoefficients(Physics::Material::B5);
 }
 
-void CollimatorPhysics::apply(PartBunchBase<double, 3> *bunch,
-                              const std::pair<Vector_t, double> &boundingSphere) {
+void CollimatorPhysics::apply(PartBunchBase<double, 3>* bunch,
+                              const std::pair<Vector_t, double>& boundingSphere) {
     IpplTimings::startTimer(DegraderApplyTimer_m);
 
     /*
@@ -208,6 +216,9 @@ void CollimatorPhysics::apply(PartBunchBase<double, 3> *bunch,
     dT_m = bunch->getdT();
     T_m  = bunch->getT();
 
+    mass_m     = bunch->getM();
+    charge_m   = bunch->getQ();
+
     bool onlyOneLoopOverParticles = ! (allParticleInMat_m);
 
     do {
@@ -215,15 +226,13 @@ void CollimatorPhysics::apply(PartBunchBase<double, 3> *bunch,
         push();
         setTimeStepForLeavingParticles();
 
-        /*
-          if we are not looping copy newly arrived particles
-        */
-        if (onlyOneLoopOverParticles)
+        // if we are not looping copy newly arrived particles
+        if (onlyOneLoopOverParticles) {
             copyFromBunch(bunch, boundingSphere);
-
+        }
         addBackToBunch(bunch);
 
-        computeInteraction();
+        computeInteraction(bunch);
 
         push();
         resetTimeStep();
@@ -244,100 +253,139 @@ void CollimatorPhysics::apply(PartBunchBase<double, 3> *bunch,
     IpplTimings::stopTimer(DegraderApplyTimer_m);
 }
 
-void CollimatorPhysics::computeInteraction() {
-    /***
+void CollimatorPhysics::computeInteraction(PartBunchBase<double, 3>* bunch) {
+    /*
         Do physics if
+        -- correct type of particle
         -- particle not stopped (locParts_m[i].label != -1.0)
 
         Absorbed particle i: locParts_m[i].label = -1.0;
     */
-
-    for (size_t i = 0; i < locParts_m.size(); ++i) {
-        if (locParts_m[i].label != -1) {
-            Vector_t &R = locParts_m[i].Rincol;
-            Vector_t &P = locParts_m[i].Pincol;
-            double &dt  = locParts_m[i].DTincol;
-
-            if (hitTester_m->checkHit(R)) {
-                bool pdead = computeEnergyLoss(P, dt);
-                if (!pdead) {
-                    /*
-                      Now scatter and transport particle in material.
-                      The checkHit call just above will detect if the
-                      particle is rediffused from the material into vacuum.
-                    */
-
-                    computeCoulombScattering(R, P, dt);
-                } else {
-                    // The particle is stopped in the material, set label to -1
-                    locParts_m[i].label = -1.0;
-                    ++ stoppedPartStat_m;
-                    lossDs_m->addParticle(R, P, -locParts_m[i].IDincol);
+    ParticleType pType = bunch->getPType();
+    if (pType == ParticleType::PROTON   ||
+        pType == ParticleType::DEUTERON ||
+        pType == ParticleType::HMINUS   ||
+        pType == ParticleType::MUON     ||
+        pType == ParticleType::H2P      ||
+        pType == ParticleType::ALPHA     ) {
+
+        for (size_t i = 0; i < locParts_m.size(); ++i) {
+            if (locParts_m[i].label != -1) {
+                Vector_t& R = locParts_m[i].Rincol;
+                Vector_t& P = locParts_m[i].Pincol;
+                double& dt  = locParts_m[i].DTincol;
+
+                if (hitTester_m->checkHit(R)) {
+                    bool pdead = computeEnergyLoss(bunch, P, dt);
+                    if (!pdead) {
+                        /*
+                          Now scatter and transport particle in material.
+                          The checkHit call just above will detect if the
+                          particle is rediffused from the material into vacuum.
+                        */
+
+                        computeCoulombScattering(R, P, dt);
+                    } else {
+                        // The particle is stopped in the material, set label to -1
+                        locParts_m[i].label = -1.0;
+                        ++ stoppedPartStat_m;
+                        lossDs_m->addParticle(R, P, -locParts_m[i].IDincol);
+                    }
                 }
             }
         }
+    } else {
+        throw GeneralClassicException(
+                "CollimatorPhysics::computeInteraction",
+                "Particle " + bunch->getPTypeString() +
+                " is not supported for scattering interactions!");    
     }
-
-    /*
-      delete absorbed particles
-    */
+    // delete absorbed particles
     deleteParticleFromLocalVector();
 }
 
-/// Energy Loss:  using the Bethe-Bloch equation.
-/// Energy straggling: For relatively thick absorbers such that the number of collisions is large,
-/// the energy loss distribution is shown to be Gaussian in form.
+/// Energy Loss: using the Bethe-Bloch equation.
+/// In low-energy region use Andersen-Ziegler fitting (only for protons)
+/// Energy straggling: For relatively thick absorbers such that the number of collisions
+/// is large, the energy loss distribution is shown to be Gaussian in form.
 /// See Particle Physics Booklet, chapter 'Passage of particles through matter' or
 /// Review of Particle Physics, DOI: 10.1103/PhysRevD.86.010001, page 329 ff
 // -------------------------------------------------------------------------
-bool CollimatorPhysics::computeEnergyLoss(Vector_t &P,
+bool CollimatorPhysics::computeEnergyLoss(PartBunchBase<double, 3>* bunch, 
+                                          Vector_t& P,
                                           const double deltat,
                                           bool includeFluctuations) const {
 
+    ParticleType pType = bunch->getPType();
     constexpr double m2cm = 1e2;
+    constexpr double eV2keV = 1e-3;
     constexpr double GeV2keV = 1e6;
+
     constexpr double massElectron_keV = Physics::m_e * GeV2keV;
-    constexpr double massProton_keV = Physics::m_p * GeV2keV;
-    constexpr double massProton_amu = Physics::m_p / Physics::amu;
-    constexpr double chargeProton = Physics::z_p;
+
+    const double mass_keV = mass_m * eV2keV;
+
     constexpr double K = 4.0 * Physics::pi * Physics::Avo * Physics::r_e * m2cm * Physics::r_e * m2cm * massElectron_keV;
 
     double gamma = Util::getGamma(P);
     const double gammaSqr = std::pow(gamma, 2);
     const double betaSqr = 1.0 - 1.0 / gammaSqr;
     double beta = std::sqrt(betaSqr);
-    double Ekin = (gamma - 1) * massProton_keV;
+    double Ekin = (gamma - 1) * mass_keV;
     double dEdx = 0.0;
+    double epsilon = 0.0;
 
     const double deltas = deltat * beta * Physics::c;
     const double deltasrho = deltas * m2cm * rho_m;
 
-    if (Ekin >= 600) {
-        constexpr double eV2keV = 1e-3;
-        constexpr double massRatio = Physics::m_e / Physics::m_p;
-        double Tmax = (2.0 * massElectron_keV * betaSqr * gammaSqr /
-                       (std::pow(gamma + massRatio, 2) - (gammaSqr - 1.0)));
-
-        dEdx = (-K * std::pow(chargeProton, 2) * Z_m / (A_m * betaSqr) *
-                (0.5 * std::log(2 * massElectron_keV * betaSqr * gammaSqr * Tmax / std::pow(I_m * eV2keV, 2)) - betaSqr));
-
-        Ekin += deltasrho * dEdx;
-    } else if (Ekin > 10) {
-        const double Ts = Ekin / massProton_amu;
-        const double epsilon_low = A2_c * pow(Ts, 0.45);
-        const double epsilon_high = (A3_c / Ts) * log(1 + (A4_c / Ts) + (A5_c * Ts));
-        const double epsilon = (epsilon_low * epsilon_high) / (epsilon_low + epsilon_high);
-        dEdx = -epsilon / (1e18 * (A_m / Physics::Avo));
-
-        Ekin += deltasrho * dEdx;
+    const double massRatio = massElectron_keV / mass_keV;
+    double Tmax = (2.0 * massElectron_keV * betaSqr * gammaSqr /
+                  (std::pow(gamma + massRatio, 2) - (gammaSqr - 1.0)));
+
+    if (pType != ParticleType::ALPHA) {
+
+        if (Ekin >= 600 && Ekin < 1e7) {
+            dEdx = (-K * std::pow(charge_m, 2) * Z_m / (A_m * betaSqr) *
+                    (0.5 * std::log(2 * massElectron_keV * betaSqr * gammaSqr * Tmax / std::pow(I_m * eV2keV, 2)) - betaSqr));
+        } else if (pType == ParticleType::PROTON && Ekin < 600) {
+            constexpr double massProton_amu = Physics::m_p / Physics::amu;
+            const double Ts = Ekin / massProton_amu;
+            if (Ekin > 10) {
+                const double epsilon_low = A2_c * std::pow(Ts, 0.45);
+                const double epsilon_high = (A3_c / Ts) * std::log(1 + (A4_c / Ts) + (A5_c * Ts));
+                epsilon = (epsilon_low * epsilon_high) / (epsilon_low + epsilon_high);
+            } else if (Ekin > 1) {
+                epsilon = A1_c * std::pow(Ts, 0.5);
+            }
+            dEdx = -epsilon / (1e18 * (A_m / Physics::Avo));
+        } else {
+            INFOMSG(level4 << "Particle energy out of the valid range "
+                              "for energy loss calculation." << endl);
+        }
+    } else {
+        if (Ekin > 10000 && Ekin < 1e6) {
+            dEdx = (-K * std::pow(charge_m, 2) * Z_m / (A_m * betaSqr) *
+                    (0.5 * std::log(2 * massElectron_keV * betaSqr * gammaSqr * Tmax / std::pow(I_m * eV2keV, 2)) - betaSqr));
+        } else if (Ekin > 1 && Ekin <= 10000) {
+            const double T = Ekin * 1e-3; //MeV 
+            const double epsilon_low = B1_c * std::pow(1000*T, B2_c);
+            const double epsilon_high = (B3_c / T) * std::log(1 + (B4_c / T) + (B5_c * T));
+            epsilon = (epsilon_low * epsilon_high) / (epsilon_low + epsilon_high);
+            dEdx = -epsilon / (1e18 * (A_m / Physics::Avo));
+        } else {
+            INFOMSG(level4 << "Particle energy out of the valid range "
+                              "for energy loss calculation." << endl);
+        }
     }
 
+    Ekin += deltasrho * dEdx;
+
     if (includeFluctuations) {
         double sigma_E = std::sqrt(K * massElectron_keV * rho_m * (Z_m / A_m) * deltas * m2cm);
         Ekin += gsl_ran_gaussian(rGen_m, sigma_E);
     }
 
-    gamma = Ekin / massProton_keV + 1.0;
+    gamma = Ekin / mass_keV + 1.0;
     beta = std::sqrt(1.0 - 1.0 / std::pow(gamma, 2));
     P = gamma * beta * P / euclidean_norm(P);
 
@@ -347,38 +395,38 @@ bool CollimatorPhysics::computeEnergyLoss(Vector_t &P,
 
 
 // Implement the rotation in 2 dimensions here
-// For details see:
-//  J. Beringer et al. (Particle Data Group), "Passage of particles through matter"
-//  Phys. Rev. D 86, 010001 (2012),
-void  CollimatorPhysics::applyRotation(Vector_t &P,
-                                       Vector_t &R,
+// For details see: J. Beringer et al. (Particle Data Group),
+// "Passage of particles through matter", Phys. Rev. D 86, 010001 (2012)
+// -------------------------------------------------------------------------
+void  CollimatorPhysics::applyRotation(Vector_t& P,
+                                       Vector_t& R,
                                        double shift,
                                        double thetacou) {
     // Calculate the angle between the transverse and longitudinal component of the momentum
     double Psixz = std::fmod(std::atan2(P(0), P(2)) + Physics::two_pi, Physics::two_pi);
 
-    R(0) = R(0) + shift * cos(Psixz);
-    R(2) = R(2) - shift * sin(Psixz);
+    R(0) = R(0) + shift * std::cos(Psixz);
+    R(2) = R(2) - shift * std::sin(Psixz);
 
     // Apply the rotation about the random angle thetacou
     double Px = P(0);
-    P(0) =  Px * cos(thetacou) + P(2) * sin(thetacou);
-    P(2) = -Px * sin(thetacou) + P(2) * cos(thetacou);
+    P(0) =  Px * std::cos(thetacou) + P(2) * std::sin(thetacou);
+    P(2) = -Px * std::sin(thetacou) + P(2) * std::cos(thetacou);
 }
 
-void CollimatorPhysics::applyRandomRotation(Vector_t &P, double theta0) {
+void CollimatorPhysics::applyRandomRotation(Vector_t& P, double theta0) {
 
     double thetaru = 2.5 / std::sqrt(gsl_rng_uniform(rGen_m)) * 2.0 * theta0;
     double phiru = Physics::two_pi * gsl_rng_uniform(rGen_m);
 
     double normPtrans = std::sqrt(P(0) * P(0) + P(1) * P(1));
     double Theta = std::atan(normPtrans / std::abs(P(2)));
-    double CosT = cos(Theta);
-    double SinT = sin(Theta);
+    double CosT = std::cos(Theta);
+    double SinT = std::sin(Theta);
 
-    Vector_t X(cos(phiru)*sin(thetaru),
-               sin(phiru)*sin(thetaru),
-               cos(thetaru));
+    Vector_t X(std::cos(phiru)*std::sin(thetaru),
+               std::sin(phiru)*std::sin(thetaru),
+               std::cos(thetaru));
     X *= euclidean_norm(P);
 
     Vector_t W(-P(1), P(0), 0.0);
@@ -391,21 +439,18 @@ void CollimatorPhysics::applyRandomRotation(Vector_t &P, double theta0) {
 /// Coulomb Scattering: Including Multiple Coulomb Scattering and large angle Rutherford Scattering.
 /// Using the distribution given in Classical Electrodynamics, by J. D. Jackson.
 //--------------------------------------------------------------------------
-void  CollimatorPhysics::computeCoulombScattering(Vector_t &R,
-                                                  Vector_t &P,
+void  CollimatorPhysics::computeCoulombScattering(Vector_t& R,
+                                                  Vector_t& P,
                                                   double dt) {
 
-    constexpr double GeV2eV = 1e9;
-    constexpr double massProton_eV = Physics::m_p * GeV2eV;
-    constexpr double chargeProton = Physics::z_p;
     constexpr double sqrtThreeInv = 0.57735026918962576451; // sqrt(1.0 / 3.0)
     const double normP = euclidean_norm(P);
     const double gammaSqr = std::pow(normP, 2) + 1.0;
     const double beta = std::sqrt(1.0 - 1.0 / gammaSqr);
     const double deltas = dt * beta * Physics::c;
-    const double theta0 = (13.6e6 / (beta * normP * massProton_eV) *
-                           chargeProton * std::sqrt(deltas / X0_m) *
-                           (1.0 + 0.038 * log(deltas / X0_m)));
+    const double theta0 = (13.6e6 / (beta * normP * mass_m) *
+                           charge_m * std::sqrt(deltas / X0_m) *
+                           (1.0 + 0.038 * std::log(deltas / X0_m)));
 
     double phi = Physics::two_pi * gsl_rng_uniform(rGen_m);
     for (unsigned int i = 0; i < 2; ++ i) {
@@ -438,7 +483,7 @@ void  CollimatorPhysics::computeCoulombScattering(Vector_t &R,
     }
 }
 
-void CollimatorPhysics::addBackToBunch(PartBunchBase<double, 3> *bunch) {
+void CollimatorPhysics::addBackToBunch(PartBunchBase<double, 3>* bunch) {
 
     const size_t nL = locParts_m.size();
     if (nL == 0) return;
@@ -447,7 +492,7 @@ void CollimatorPhysics::addBackToBunch(PartBunchBase<double, 3> *bunch) {
     const double elementLength = element_ref_m->getElementLength();
 
     for (size_t i = 0; i < nL; ++ i) {
-        Vector_t &R = locParts_m[i].Rincol;
+        Vector_t& R = locParts_m[i].Rincol;
 
         if (R[2] >= elementLength) {
 
@@ -457,7 +502,6 @@ void CollimatorPhysics::addBackToBunch(PartBunchBase<double, 3> *bunch) {
               Binincol is still <0, but now the particle is rediffused
               from the material and hence this is not a "lost" particle anymore
             */
-
             bunch->Bin[numLocalParticles] = 1;
             bunch->R[numLocalParticles]   = R;
             bunch->P[numLocalParticles]   = locParts_m[i].Pincol;
@@ -478,14 +522,12 @@ void CollimatorPhysics::addBackToBunch(PartBunchBase<double, 3> *bunch) {
         }
     }
 
-    /*
-      delete particles that went to the bunch
-    */
+    // delete particles that went to the bunch
     deleteParticleFromLocalVector();
 }
 
-void CollimatorPhysics::copyFromBunch(PartBunchBase<double, 3> *bunch,
-                                      const std::pair<Vector_t, double> &boundingSphere)
+void CollimatorPhysics::copyFromBunch(PartBunchBase<double, 3>* bunch,
+                                      const std::pair<Vector_t, double>& boundingSphere)
 {
     const size_t nL = bunch->getLocalNum();
     if (nL == 0) return;
@@ -555,8 +597,8 @@ void CollimatorPhysics::print(Inform &msg) {
     Inform::FmtFlags_t ff = msg.flags();
 
     if (totalPartsInMat_m > 0 ||
-        bunchToMatStat_m > 0 ||
-        rediffusedStat_m > 0 ||
+        bunchToMatStat_m  > 0 ||
+        rediffusedStat_m  > 0 ||
         stoppedPartStat_m > 0) {
 
         OPALTimer::Timer time;
@@ -586,8 +628,8 @@ namespace {
 
 void CollimatorPhysics::deleteParticleFromLocalVector() {
     /*
-      the particle to be deleted (label < 0) are all at the end of
-      the vector.
+      the particle to be deleted (label < 0) are all 
+      at the end of the vector.
     */
     sort(locParts_m.begin(), locParts_m.end(), myCompF);
 
@@ -611,8 +653,8 @@ void CollimatorPhysics::deleteParticleFromLocalVector() {
 
 void CollimatorPhysics::push() {
     for (size_t i = 0; i < locParts_m.size(); ++i) {
-        Vector_t &R  = locParts_m[i].Rincol;
-        Vector_t &P  = locParts_m[i].Pincol;
+        Vector_t& R  = locParts_m[i].Rincol;
+        Vector_t& P  = locParts_m[i].Pincol;
         double gamma = Util::getGamma(P);
 
         R += 0.5 * dT_m * Physics::c * P / gamma;
@@ -629,9 +671,9 @@ void CollimatorPhysics::setTimeStepForLeavingParticles() {
     const double elementLength = element_ref_m->getElementLength();
 
     for (size_t i = 0; i < locParts_m.size(); ++i) {
-        Vector_t &R  = locParts_m[i].Rincol;
-        Vector_t &P  = locParts_m[i].Pincol;
-        double   &dt = locParts_m[i].DTincol;
+        Vector_t& R  = locParts_m[i].Rincol;
+        Vector_t& P  = locParts_m[i].Pincol;
+        double& dt   = locParts_m[i].DTincol;
         double gamma = Util::getGamma(P);
         Vector_t stepLength = dT_m * Physics::c * P / gamma;
 
@@ -651,7 +693,7 @@ void CollimatorPhysics::setTimeStepForLeavingParticles() {
 
 void CollimatorPhysics::resetTimeStep() {
     for (size_t i = 0; i < locParts_m.size(); ++i) {
-        double &dt = locParts_m[i].DTincol;
+        double& dt = locParts_m[i].DTincol;
         dt = dT_m;
     }
 
diff --git a/src/Classic/Solvers/CollimatorPhysics.hh b/src/Classic/Solvers/CollimatorPhysics.hh
index c4a8fa73dbd761f3c5f69d1d00061d3f896a3b82..db5da27a595a1febae2d5e908e1ef5749ab36ae3 100644
--- a/src/Classic/Solvers/CollimatorPhysics.hh
+++ b/src/Classic/Solvers/CollimatorPhysics.hh
@@ -1,9 +1,9 @@
 //
 // Class CollimatorPhysics
+//   Defines the physical processes of beam scattering 
+//   and energy loss by heavy charged particles
 //
-// Defines the collimator physics models
-//
-// Copyright (c) 2009 - 2020, Bi, Yang, Stachel, Adelmann
+// Copyright (c) 2009 - 2021, Bi, Yang, Stachel, Adelmann
 //                            Paul Scherrer Institut, Villigen PSI, Switzerland
 // All rights reserved.
 //
@@ -17,7 +17,6 @@
 // You should have received a copy of the GNU General Public License
 // along with OPAL.  If not, see <https://www.gnu.org/licenses/>.
 //
-
 #ifndef COLLIMATORPHYSICS_HH
 #define COLLIMATORPHYSICS_HH
 
@@ -25,13 +24,14 @@
 
 #include "AbsBeamline/ElementBase.h"
 #include "Algorithms/Vektor.h"
+
 #include <gsl/gsl_rng.h>
 
 #include "Utility/IpplTimings.h"
 
 #include <memory>
-#include <utility>
 #include <string>
+#include <utility>
 #include <vector>
 
 template <class T, unsigned Dim>
@@ -64,15 +64,15 @@ struct InsideTester {
 
 class CollimatorPhysics: public ParticleMatterInteractionHandler {
 public:
-    CollimatorPhysics(const std::string &name,
-                      ElementBase *element,
-                      std::string &mat,
+    CollimatorPhysics(const std::string& name,
+                      ElementBase* element,
+                      std::string& mat,
                       bool enableRutherford,
                       double lowEnergyThr);
     ~CollimatorPhysics();
 
-    virtual void apply(PartBunchBase<double, 3> *bunch,
-                       const std::pair<Vector_t, double> &boundingSphere);
+    virtual void apply(PartBunchBase<double, 3>* bunch,
+                       const std::pair<Vector_t, double>& boundingSphere);
 
     virtual const std::string getType() const;
 
@@ -84,28 +84,29 @@ public:
     virtual size_t getParticlesInMat();
     virtual unsigned getRediffused();
     virtual unsigned int getNumEntered();
-    void computeInteraction();
+    void computeInteraction(PartBunchBase<double, 3>* bunch);
 
-    virtual bool computeEnergyLoss(Vector_t &P,
+    virtual bool computeEnergyLoss(PartBunchBase<double, 3>* bunch,
+                                   Vector_t& P,
                                    const double deltat,
                                    bool includeFluctuations = true) const;
 
 private:
 
     void configureMaterialParameters();
-    void computeCoulombScattering(Vector_t &R,
-                                  Vector_t &P,
+    void computeCoulombScattering(Vector_t& R,
+                                  Vector_t& P,
                                   double dt);
 
-    void applyRotation(Vector_t &P,
-                       Vector_t &R,
+    void applyRotation(Vector_t& P,
+                       Vector_t& R,
                        double xplane,
                        double thetacou);
-    void applyRandomRotation(Vector_t &P, double theta0);
+    void applyRandomRotation(Vector_t& P, double theta0);
 
-    void copyFromBunch(PartBunchBase<double, 3> *bunch,
-                       const std::pair<Vector_t, double> &boundingSphere);
-    void addBackToBunch(PartBunchBase<double, 3> *bunch);
+    void copyFromBunch(PartBunchBase<double, 3>* bunch,
+                       const std::pair<Vector_t, double>& boundingSphere);
+    void addBackToBunch(PartBunchBase<double, 3>* bunch);
 
     void deleteParticleFromLocalVector();
 
@@ -119,6 +120,9 @@ private:
     double  T_m;                               // own time, maybe larger than in the bunch object
     double dT_m;                               // dt from bunch
 
+    double mass_m;                             // mass from bunch (eV)
+    double charge_m;                           // charge from bunch (elementary charges)
+
     gsl_rng *rGen_m;                           // random number generator
 
     std::string material_m;                    // type of material e.g. aluminum
@@ -133,10 +137,21 @@ private:
     double X0_m;                               // the radiation length in [m]
     double I_m;                                // the mean excitation energy [eV]
 
-    double A2_c;                               // coefficients to fit model to measurement data
-    double A3_c;                               // see e.g. page 16-20 in H. H. Andersen, J. F. Ziegler,
-    double A4_c;                               // "Hydrogen Stopping Powers and Ranges in All Elements",
-    double A5_c;                               // Pergamon Press, 1977
+    /* 
+       coefficients to fit model to measurement data according to Andersen-Ziegler formulae.
+       see ICRU-49, "Stopping Powers and Ranges for Protons  and Alpha Particles",
+       chapter 'Electronic (Collision) Stopping Powers in the Low-Energy Region'
+    */
+    double A1_c;
+    double A2_c;
+    double A3_c;
+    double A4_c;
+    double A5_c;
+    double B1_c;
+    double B2_c;
+    double B3_c;
+    double B4_c;
+    double B5_c;
 
     // number of particles that enter the material in current step (count for single step)
     unsigned int bunchToMatStat_m;
diff --git a/src/Classic/Solvers/ParticleMatterInteractionHandler.hh b/src/Classic/Solvers/ParticleMatterInteractionHandler.hh
index af4fc75ad42382060a326fa9746be44156b08d85..ed81c3673fed42642389ffbce508bbf25930c53e 100644
--- a/src/Classic/Solvers/ParticleMatterInteractionHandler.hh
+++ b/src/Classic/Solvers/ParticleMatterInteractionHandler.hh
@@ -1,3 +1,20 @@
+//
+// Class ParticleMatterInteractionHandler
+//   Defines the handler for particle-matter interactions in the elements
+//
+// Copyright (c) 200x - 2021, 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 <https://www.gnu.org/licenses/>.
+//
 #ifndef PARTICLEMATTERINTERACTIONHANDLER_HH
 #define PARTICLEMATTERINTERACTIONHANDLER_HH
 
@@ -11,11 +28,12 @@ class PartBunchBase;
 class Inform;
 
 class ParticleMatterInteractionHandler {
+
 public:
-    ParticleMatterInteractionHandler(std::string name, ElementBase *elref);
+    ParticleMatterInteractionHandler(std::string name, ElementBase* elref);
     virtual ~ParticleMatterInteractionHandler() { };
-    virtual void apply(PartBunchBase<double, 3> *bunch,
-                       const std::pair<Vector_t, double> &boundingSphere) = 0;
+    virtual void apply(PartBunchBase<double, 3>* bunch,
+                       const std::pair<Vector_t, double>& boundingSphere) = 0;
     virtual const std::string getType() const = 0;
     virtual void print(Inform& os) = 0;
     virtual bool stillActive() = 0;
@@ -26,29 +44,30 @@ public:
     virtual unsigned int getNumEntered() = 0;
     void setFlagAllParticlesIn(bool p);
     bool getFlagAllParticlesIn() const;
-    void updateElement(ElementBase *newref);
+    void updateElement(ElementBase* newref);
     ElementBase* getElement();
 
-    virtual bool computeEnergyLoss(Vector_t &P,//double &Eng,
+    virtual bool computeEnergyLoss(PartBunchBase<double, 3>* bunch,
+                                   Vector_t& P,
                                    const double deltat,
                                    bool includeFluctuations = true) const = 0;
 protected:
-    ElementBase *element_ref_m;
+    ElementBase* element_ref_m;
     bool allParticleInMat_m; ///< if all particles are in matter stay inside the particle matter interaction
+
 private:
     const std::string name_m;
-
 };
 
 inline
-ParticleMatterInteractionHandler::ParticleMatterInteractionHandler(std::string name, ElementBase *elref):
+ParticleMatterInteractionHandler::ParticleMatterInteractionHandler(std::string name, ElementBase* elref):
     element_ref_m(elref),
     allParticleInMat_m(false),
     name_m(name)
 {}
 
 inline
-void ParticleMatterInteractionHandler::updateElement(ElementBase *newref) {
+void ParticleMatterInteractionHandler::updateElement(ElementBase* newref) {
     element_ref_m = newref;
 }
 
@@ -66,4 +85,4 @@ inline
 bool ParticleMatterInteractionHandler::getFlagAllParticlesIn() const {
     return allParticleInMat_m;
 }
-#endif // PARTICLEMATTERINTERACTION_HH
\ No newline at end of file
+#endif // PARTICLEMATTERINTERACTION_HH
diff --git a/src/Distribution/Distribution.cpp b/src/Distribution/Distribution.cpp
index 6a720620fd4c5ca9afadea33210e4fee05945a17..d98c1abaf9b580a38bf69dc9bfdd3db883a1606a 100644
--- a/src/Distribution/Distribution.cpp
+++ b/src/Distribution/Distribution.cpp
@@ -1635,7 +1635,8 @@ size_t Distribution::emitParticles(PartBunchBase<double, 3> *beam, double eZ) {
                 beam->Q[numberOfEmittedParticles] = beam->getChargePerParticle();
                 beam->Ef[numberOfEmittedParticles] = Vector_t(0.0);
                 beam->Bf[numberOfEmittedParticles] = Vector_t(0.0);
-                beam->PType[numberOfEmittedParticles] = ParticleType::REGULAR;
+                beam->PType[numberOfEmittedParticles] = beam->getPType();
+                beam->POrigin[numberOfEmittedParticles] = ParticleOrigin::REGULAR;
                 beam->TriID[numberOfEmittedParticles] = 0;
                 numberOfEmittedParticles++;
 
@@ -2751,7 +2752,8 @@ void Distribution::injectBeam(PartBunchBase<double, 3> *beam) {
         beam->Q[partIndex] = beam->getChargePerParticle();
         beam->Ef[partIndex] = Vector_t(0.0);
         beam->Bf[partIndex] = Vector_t(0.0);
-        beam->PType[partIndex] = ParticleType::REGULAR;
+        beam->PType[partIndex] = beam->getPType();
+        beam->POrigin[partIndex] = ParticleOrigin::REGULAR;
         beam->TriID[partIndex] = 0;
 
         if (numberOfEnergyBins_m > 0) {
@@ -4451,4 +4453,4 @@ void Distribution::adjustPhaseSpace(double massIneV) {
         tOrZDist_m[i] -= avrg[4];
         pzDist_m[i] += eps;
     }
-}
\ No newline at end of file
+}
diff --git a/src/Structure/Beam.cpp b/src/Structure/Beam.cpp
index deb647b362b6ba361f154e03ee04f50fff5bebf3..8f4b70171acdadf6e7bd3538605c67700b879aca 100644
--- a/src/Structure/Beam.cpp
+++ b/src/Structure/Beam.cpp
@@ -1,22 +1,24 @@
-// ------------------------------------------------------------------------
-// $RCSfile: Beam.cpp,v $
-// ------------------------------------------------------------------------
-// $Revision: 1.3.4.1 $
-// ------------------------------------------------------------------------
-// Copyright: see Copyright.readme
-// ------------------------------------------------------------------------
 //
-// Class: Beam
+// Class Beam
 //   The class for the OPAL BEAM command.
+//   A BEAM definition is used by most physics commands to define the
+//   particle charge and the reference momentum, together with some other data.
 //
-// ------------------------------------------------------------------------
+// Copyright (c) 200x - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
+// All rights reserved
 //
-// $Date: 2003/08/11 22:09:00 $
-// $Author: dbruhwil $
+// 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/>.
 //
-// ------------------------------------------------------------------------
-
 #include "Structure/Beam.h"
+
 #include "AbstractObjects/Expressions.h"
 #include "AbstractObjects/OpalData.h"
 #include "Attributes/Attributes.h"
@@ -30,72 +32,62 @@
 
 using namespace Expressions;
 
-// Class Beam
-// ------------------------------------------------------------------------
 
 // The attributes of class Beam.
 namespace {
     enum {
-        // DESCRIPTION OF SINGLE PARTICLE:
         PARTICLE,   // The particle name
         MASS,       // The particle rest mass in GeV
         CHARGE,     // The particle charge in proton charges
         ENERGY,     // The particle energy in GeV
         PC,         // The particle momentum in GeV/c
         GAMMA,      // ENERGY / MASS
-
-        // BEAM CURRENT AND EMITTANCES:
         BCURRENT,   // Beam current in A
-
-        // BEAM FREQUENCY
-        BFREQ,  // Beam frequency in MHz
-
-        // DESCRIPTION OF BUNCHES:
+        BFREQ,      // Beam frequency in MHz
         NPART,      // Number of particles per bunch
         SIZE
     };
 }
 
-
 const double Beam::energy_scale = 1.0e9;
 
-
 Beam::Beam():
     Definition(SIZE, "BEAM",
                "The \"BEAM\" statement defines data for the particles "
                "in a beam."),
     reference(1.0, Physics::m_p *energy_scale, 1.0 * energy_scale) {
 
-    // DESCRIPTION OF SINGLE PARTICLE:
     itsAttr[PARTICLE] = Attributes::makeString
                         ("PARTICLE", "Name of particle to be used");
-    itsAttr[MASS] = Attributes::makeReal
-                    ("MASS", "Particle rest mass in GeV");
-    itsAttr[CHARGE] = Attributes::makeReal
-                      ("CHARGE", "Particle charge in proton charges");
-    itsAttr[ENERGY] = Attributes::makeReal
-                      ("ENERGY", "Particle energy in GeV");
-    itsAttr[PC] = Attributes::makeReal
-                  ("PC", "Particle momentum in GeV/c");
+
+    itsAttr[MASS]     = Attributes::makeReal
+                        ("MASS", "Particle rest mass [GeV]");
+
+    itsAttr[CHARGE]   = Attributes::makeReal
+                        ("CHARGE", "Particle charge in proton charges");
+
+    itsAttr[ENERGY]   = Attributes::makeReal
+                        ("ENERGY", "Particle energy [GeV]");
+
+    itsAttr[PC]       = Attributes::makeReal
+                        ("PC", "Particle momentum [GeV/c]");
     PtrToScalar<double> expr = new SRefExpr<double>("P0", "");
     itsAttr[PC].set(new SAutomatic<double>(expr));
-    itsAttr[GAMMA] = Attributes::makeReal
-                     ("GAMMA", "ENERGY / MASS");
 
-    // BEAM CURRENT AND EMITTANCES:
+    itsAttr[GAMMA]    = Attributes::makeReal
+                        ("GAMMA", "ENERGY / MASS");
+
     itsAttr[BCURRENT] = Attributes::makeReal
-                        ("BCURRENT", "Beam current in A (all bunches)");
+                        ("BCURRENT", "Beam current [A] (all bunches)");
 
-    // BEAM FREQUENCY
-    itsAttr[BFREQ] = Attributes::makeReal
-                     ("BFREQ", "Beam frequency in MHz (all bunches)");
+    itsAttr[BFREQ]    = Attributes::makeReal
+                        ("BFREQ", "Beam frequency [MHz] (all bunches)");
 
-    // DESCRIPTION OF BUNCHES:
-    itsAttr[NPART] = Attributes::makeReal
-                     ("NPART", "Number of particles in bunch");
+    itsAttr[NPART]    = Attributes::makeReal
+                        ("NPART", "Number of particles in bunch");
 
     // Set up default beam.
-    Beam *defBeam = clone("UNNAMED_BEAM");
+    Beam* defBeam = clone("UNNAMED_BEAM");
     defBeam->builtin = true;
 
     try {
@@ -109,7 +101,7 @@ Beam::Beam():
 }
 
 
-Beam::Beam(const std::string &name, Beam *parent):
+Beam::Beam(const std::string& name, Beam* parent):
     Definition(name, parent),
     reference(parent->reference)
 {}
@@ -119,13 +111,13 @@ Beam::~Beam()
 {}
 
 
-bool Beam::canReplaceBy(Object *object) {
+bool Beam::canReplaceBy(Object* object) {
     // Can replace only by another BEAM.
-    return dynamic_cast<Beam *>(object) != 0;
+    return dynamic_cast<Beam*>(object) != 0;
 }
 
 
-Beam *Beam::clone(const std::string &name) {
+Beam* Beam::clone(const std::string& name) {
     return new Beam(name, this);
 }
 
@@ -135,10 +127,10 @@ void Beam::execute() {
 }
 
 
-Beam *Beam::find(const std::string &name) {
-    Beam *beam = dynamic_cast<Beam *>(OpalData::getInstance()->find(name));
+Beam* Beam::find(const std::string& name) {
+    Beam* beam = dynamic_cast<Beam*>(OpalData::getInstance()->find(name));
 
-    if(beam == 0) {
+    if (beam == 0) {
         throw OpalException("Beam::find()", "Beam \"" + name + "\" not found.");
     }
 
@@ -149,9 +141,9 @@ size_t Beam::getNumberOfParticles() const {
     return (size_t)Attributes::getReal(itsAttr[NPART]);
 }
 
-const PartData &Beam::getReference() const {
+const PartData& Beam::getReference() const {
     // Cast away const, to allow logically constant Beam to update.
-    const_cast<Beam *>(this)->update();
+    const_cast<Beam*>(this)->update();
     return reference;
 }
 
@@ -187,9 +179,20 @@ double Beam::getMassPerParticle() const {
 
 void Beam::update() {
     // Find the particle name.
-    if(itsAttr[PARTICLE]) {
+    if (itsAttr[PARTICLE]) {
         static const char *names[] = {
-            "ELECTRON", "PROTON", "POSITRON", "ANTIPROTON", "CARBON", "HMINUS", "URANIUM", "MUON", "DEUTERON", "XENON", "H2P"
+            "ELECTRON",
+            "PROTON",
+            "POSITRON",
+            "ANTIPROTON",
+            "CARBON",
+            "HMINUS",
+            "URANIUM",
+            "MUON",
+            "DEUTERON",
+            "XENON",
+            "H2P",
+            "ALPHA"
         };
 
         static const double masses[] = {
@@ -203,17 +206,18 @@ void Beam::update() {
             Physics::m_mu,
             Physics::m_d,
             Physics::m_xe,
-            Physics::m_h2p
+            Physics::m_h2p,
+            Physics::m_alpha
         };
 
         static const double charges[] = {
-            -1.0, 1.0, 1.0, -1.0, 12.0, -1.0, 35.0, -1.0, 1.0, 20.0, 1.0
+            -1.0, 1.0, 1.0, -1.0, 12.0, -1.0, 35.0, -1.0, 1.0, 20.0, 1.0, 2.0
         };
         const unsigned int numParticleNames = std::end(names) - std::begin(names);
 
         std::string pName  = Attributes::getString(itsAttr[PARTICLE]);
-        for(unsigned int i = 0; i < numParticleNames; ++ i) {
-            if(pName == names[i]) {
+        for (unsigned int i = 0; i < numParticleNames; ++ i) {
+            if (pName == names[i]) {
                 Attributes::setReal(itsAttr[MASS], masses[i]);
                 Attributes::setReal(itsAttr[CHARGE], charges[i]);
                 break;
@@ -228,25 +232,25 @@ void Beam::update() {
     reference = PartData(charge, mass, 1.0);
 
     // Checks
-    if(itsAttr[GAMMA]) {
+    if (itsAttr[GAMMA]) {
         double gamma = Attributes::getReal(itsAttr[GAMMA]);
-        if(gamma > 1.0) {
+        if (gamma > 1.0) {
             reference.setGamma(gamma);
         } else {
             throw OpalException("Beam::update()",
                                 "\"GAMMA\" should be greater than 1.");
         }
-    } else if(itsAttr[ENERGY]) {
+    } else if (itsAttr[ENERGY]) {
         double energy = Attributes::getReal(itsAttr[ENERGY]) * energy_scale;
-        if(energy > reference.getM()) {
+        if (energy > reference.getM()) {
             reference.setE(energy);
         } else {
             throw OpalException("Beam::update()",
                                 "\"ENERGY\" should be greater than \"MASS\".");
         }
-    } else if(itsAttr[PC]) {
+    } else if (itsAttr[PC]) {
         double pc = Attributes::getReal(itsAttr[PC]) * energy_scale;
-        if(pc > 0.0) {
+        if (pc > 0.0) {
             reference.setP(pc);
         } else {
             throw OpalException("Beam::update()",
@@ -255,7 +259,7 @@ void Beam::update() {
     }
 
     // Set default name.
-    if(getOpalName().empty()) setOpalName("UNNAMED_BEAM");
+    if (getOpalName().empty()) setOpalName("UNNAMED_BEAM");
 }
 
 
@@ -270,7 +274,7 @@ double Beam::getPC() const { //obtain value for PC
 }
 
 
-void Beam::print(std::ostream &os) const {
+void Beam::print(std::ostream& os) const {
     double charge = Attributes::getReal(itsAttr[CHARGE]);
     os << "* ************* B E A M ************************************************************ " << std::endl;
     os << "* BEAM        " << getOpalName() << '\n'
diff --git a/src/Structure/Beam.h b/src/Structure/Beam.h
index 5f221a50c236208451f6fe61b85e80ffe4a1825c..a5b26b2c2dd35e34e7f44091383184522114866a 100644
--- a/src/Structure/Beam.h
+++ b/src/Structure/Beam.h
@@ -1,22 +1,24 @@
-#ifndef OPAL_Beam_HH
-#define OPAL_Beam_HH
-
-// ------------------------------------------------------------------------
-// $RCSfile: Beam.h,v $
-// ------------------------------------------------------------------------
-// $Revision: 1.1.1.1 $
-// ------------------------------------------------------------------------
-// Copyright: see Copyright.readme
-// ------------------------------------------------------------------------
 //
-// Class: Beam
+// Class Beam
+//   The class for the OPAL BEAM command.
+//   A BEAM definition is used by most physics commands to define the
+//   particle charge and the reference momentum, together with some other data.
+//
+// Copyright (c) 200x - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
+// All rights reserved
 //
-// ------------------------------------------------------------------------
+// This file is part of OPAL.
 //
-// $Date: 2000/03/27 09:33:44 $
-// $Author: Andreas Adelmann $
+// 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 OPAL_Beam_HH
+#define OPAL_Beam_HH
 
 #include "AbstractObjects/Definition.h"
 #include "Algorithms/PartData.h"
@@ -26,12 +28,6 @@
 
 class Inform;
 
-// Class Beam
-// ------------------------------------------------------------------------
-/// The BEAM definition.
-//  A BEAM definition is used by most physics commands to define the
-//  particle charge and the reference momentum, together with some other
-//  data.
 
 class Beam: public Definition {
 
@@ -44,16 +40,16 @@ public:
 
     /// Test if replacement is allowed.
     //  Can replace only by another BEAM.
-    virtual bool canReplaceBy(Object *object);
+    virtual bool canReplaceBy(Object* object);
 
     /// Make clone.
-    virtual Beam *clone(const std::string &name);
+    virtual Beam* clone(const std::string& name);
 
     /// Check the BEAM data.
     virtual void execute();
 
     /// Find named BEAM.
-    static Beam *find(const std::string &name);
+    static Beam* find(const std::string& name);
 
     //ff => get gamma value
     double getGamma() const;
@@ -65,7 +61,7 @@ public:
     size_t getNumberOfParticles() const;
 
     /// Return the embedded CLASSIC PartData.
-    const PartData &getReference() const;
+    const PartData& getReference() const;
 
     /// Return the beam current in A
     double getCurrent() const;
@@ -91,16 +87,16 @@ public:
     /// Update the BEAM data.
     virtual void update();
 
-    void print(std::ostream &os) const;
+    void print(std::ostream& os) const;
 
 private:
 
     // Not implemented.
-    Beam(const Beam &);
-    void operator=(const Beam &);
+    Beam(const Beam&);
+    void operator=(const Beam&);
 
     // Clone constructor.
-    Beam(const std::string &name, Beam *parent);
+    Beam(const std::string& name, Beam* parent);
 
     // The particle reference data.
     PartData reference;
@@ -109,10 +105,9 @@ private:
     static const double energy_scale;
 };
 
-inline std::ostream &operator<<(std::ostream &os, const Beam &b) {
+inline std::ostream &operator<<(std::ostream& os, const Beam& b) {
     b.print(os);
     return os;
 }
 
-
 #endif // OPAL_Beam_HH
diff --git a/src/Structure/H5PartWrapperForPT.cpp b/src/Structure/H5PartWrapperForPT.cpp
index 7215ce182c086856d14e1619615a92cd84f9191a..55756fbb41ef1f17225b6dac595773a7dd5c49b4 100644
--- a/src/Structure/H5PartWrapperForPT.cpp
+++ b/src/Structure/H5PartWrapperForPT.cpp
@@ -1,7 +1,20 @@
 //
-//  Copyright & License: See Copyright.readme in src directory
+// Class H5PartWrapperForPT
+//   A class that manages all calls to H5Part for the Parallel-T tracker.
+//
+// Copyright (c) 200x-2021, 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 <https://www.gnu.org/licenses/>.
 //
-
 #include "Structure/H5PartWrapperForPT.h"
 
 #include "OPALconfig.h"
@@ -14,14 +27,15 @@
 
 #include "h5core/h5_types.h"
 
+#include <cmath>
 #include <sstream>
 #include <set>
 
-H5PartWrapperForPT::H5PartWrapperForPT(const std::string &fileName, h5_int32_t flags):
+H5PartWrapperForPT::H5PartWrapperForPT(const std::string& fileName, h5_int32_t flags):
     H5PartWrapper(fileName, flags)
 { }
 
-H5PartWrapperForPT::H5PartWrapperForPT(const std::string &fileName, int restartStep, std::string sourceFile, h5_int32_t flags):
+H5PartWrapperForPT::H5PartWrapperForPT(const std::string& fileName, int restartStep, std::string sourceFile, h5_int32_t flags):
     H5PartWrapper(fileName, restartStep, sourceFile, flags)
 {
     if (restartStep == -1) {
@@ -73,7 +87,7 @@ void H5PartWrapperForPT::readHeader() {
             H5ReadFileAttribInt64(file_m, "nAutoPhaseCavities", &numAutoPhaseCavities) != H5_SUCCESS) {
             numAutoPhaseCavities = 0;
         } else {
-            for(long i = 0; i < numAutoPhaseCavities; ++ i) {
+            for (long i = 0; i < numAutoPhaseCavities; ++ i) {
                 std::string elementName  = "Cav-" + std::to_string(i + 1) + "-name";
                 std::string elementPhase = "Cav-" + std::to_string(i + 1) + "-value";
 
@@ -123,9 +137,9 @@ void H5PartWrapperForPT::readStepHeader(PartBunchBase<double, 3>* bunch) {
 
     Vector_t TaitBryant;
     READSTEPATTRIB(Float64, file_m, "TaitBryantAngles", (h5_float64_t *)&TaitBryant);
-    Quaternion rotTheta(cos(0.5 * TaitBryant[0]), 0, sin(0.5 * TaitBryant[0]), 0);
-    Quaternion rotPhi(cos(0.5 * TaitBryant[1]), sin(0.5 * TaitBryant[1]), 0, 0);
-    Quaternion rotPsi(cos(0.5 * TaitBryant[2]), 0, 0, sin(0.5 * TaitBryant[2]));
+    Quaternion rotTheta(std::cos(0.5 * TaitBryant[0]), 0, std::sin(0.5 * TaitBryant[0]), 0);
+    Quaternion rotPhi(std::cos(0.5 * TaitBryant[1]), std::sin(0.5 * TaitBryant[1]), 0, 0);
+    Quaternion rotPsi(std::cos(0.5 * TaitBryant[2]), 0, 0, std::sin(0.5 * TaitBryant[2]));
     Quaternion rotation = rotTheta * (rotPhi * rotPsi);
     bunch->toLabTrafo_m = CoordinateSystemTrafo(-rotation.conjugate().rotate(RefPartR), rotation);
 }
@@ -143,47 +157,47 @@ void H5PartWrapperForPT::readStepData(PartBunchBase<double, 3>* bunch, h5_ssize_
 
     std::vector<char> buffer(numParticles * sizeof(h5_float64_t));
     char* buffer_ptr = Util::c_data(buffer);
-    h5_float64_t *f64buffer = reinterpret_cast<h5_float64_t*>(buffer_ptr);
-    h5_int32_t *i32buffer = reinterpret_cast<h5_int32_t*>(buffer_ptr);
+    h5_float64_t* f64buffer = reinterpret_cast<h5_float64_t*>(buffer_ptr);
+    h5_int32_t* i32buffer = reinterpret_cast<h5_int32_t*>(buffer_ptr);
 
     READDATA(Float64, file_m, "x", f64buffer);
-    for(long int n = 0; n < numParticles; ++ n) {
+    for (long int n = 0; n < numParticles; ++ n) {
         bunch->R[n](0) = f64buffer[n];
         bunch->Bin[n] = 0;
     }
 
     READDATA(Float64, file_m, "y", f64buffer);
-    for(long int n = 0; n < numParticles; ++ n) {
+    for (long int n = 0; n < numParticles; ++ n) {
         bunch->R[n](1) = f64buffer[n];
     }
 
     READDATA(Float64, file_m, "z", f64buffer);
-    for(long int n = 0; n < numParticles; ++ n) {
+    for (long int n = 0; n < numParticles; ++ n) {
         bunch->R[n](2) = f64buffer[n];
     }
 
     READDATA(Float64, file_m, "px", f64buffer);
-    for(long int n = 0; n < numParticles; ++ n) {
+    for (long int n = 0; n < numParticles; ++ n) {
         bunch->P[n](0) = f64buffer[n];
     }
 
     READDATA(Float64, file_m, "py", f64buffer);
-    for(long int n = 0; n < numParticles; ++ n) {
+    for (long int n = 0; n < numParticles; ++ n) {
         bunch->P[n](1) = f64buffer[n];
     }
 
     READDATA(Float64, file_m, "pz", f64buffer);
-    for(long int n = 0; n < numParticles; ++ n) {
+    for (long int n = 0; n < numParticles; ++ n) {
         bunch->P[n](2) = f64buffer[n];
     }
 
     READDATA(Float64, file_m, "q", f64buffer);
-    for(long int n = 0; n < numParticles; ++ n) {
+    for (long int n = 0; n < numParticles; ++ n) {
         bunch->Q[n] = f64buffer[n];
     }
 
     READDATA(Int32, file_m, "id", i32buffer);
-    for(long int n = 0; n < numParticles; ++ n) {
+    for (long int n = 0; n < numParticles; ++ n) {
         bunch->ID[n] = i32buffer[n];
     }
 
@@ -206,6 +220,7 @@ void H5PartWrapperForPT::writeHeader() {
     WRITESTRINGFILEATTRIB(file_m, "pzUnit", "#beta#gamma");
 
     WRITESTRINGFILEATTRIB(file_m, "ptypeUnit", "1");
+    WRITESTRINGFILEATTRIB(file_m, "poriginUnit", "1");
     WRITESTRINGFILEATTRIB(file_m, "qUnit", "C");
 
     if (Options::ebDump) {
@@ -273,7 +288,7 @@ void H5PartWrapperForPT::writeHeader() {
     WRITEFILEATTRIB(Float64, file_m, "dPhiGlobal", &dphi, 1);
 }
 
-void H5PartWrapperForPT::writeStep(PartBunchBase<double, 3>* bunch, const std::map<std::string, double> &additionalStepAttributes) {
+void H5PartWrapperForPT::writeStep(PartBunchBase<double, 3>* bunch, const std::map<std::string, double>& additionalStepAttributes) {
     if (bunch->getTotalNum() == 0) return;
 
     open(H5_O_APPENDONLY);
@@ -282,7 +297,7 @@ void H5PartWrapperForPT::writeStep(PartBunchBase<double, 3>* bunch, const std::m
     close();
 }
 
-void H5PartWrapperForPT::writeStepHeader(PartBunchBase<double, 3>* bunch, const std::map<std::string, double> &additionalStepAttributes) {
+void H5PartWrapperForPT::writeStepHeader(PartBunchBase<double, 3>* bunch, const std::map<std::string, double>& additionalStepAttributes) {
     bunch->calcBeamParameters();
 
     double   actPos   = bunch->get_sPos();
@@ -324,26 +339,26 @@ void H5PartWrapperForPT::writeStepHeader(PartBunchBase<double, 3>* bunch, const
 
     REPORTONERROR(H5SetStep(file_m, numSteps_m));
 
-    char const *OPALFlavour = "opal-t";
+    char const* OPALFlavour = "opal-t";
     WRITESTRINGSTEPATTRIB(file_m, "OPAL_flavour", OPALFlavour);
     WRITESTEPATTRIB(Float64, file_m, "SPOS", &actPos, 1);
-    WRITESTEPATTRIB(Float64, file_m, "RefPartR", (h5_float64_t *)&RefPartR, 3);
-    WRITESTEPATTRIB(Float64, file_m, "centroid", (h5_float64_t *)&centroid, 3);
-    WRITESTEPATTRIB(Float64, file_m, "RMSX", (h5_float64_t *)&xsigma, 3);
+    WRITESTEPATTRIB(Float64, file_m, "RefPartR", (h5_float64_t*)&RefPartR, 3);
+    WRITESTEPATTRIB(Float64, file_m, "centroid", (h5_float64_t*)&centroid, 3);
+    WRITESTEPATTRIB(Float64, file_m, "RMSX", (h5_float64_t*)&xsigma, 3);
 
-    WRITESTEPATTRIB(Float64, file_m, "RefPartP", (h5_float64_t *)&RefPartP, 3);
-    WRITESTEPATTRIB(Float64, file_m, "MEANP", (h5_float64_t *)&pmean, 3);
-    WRITESTEPATTRIB(Float64, file_m, "RMSP", (h5_float64_t *)&psigma, 3);
-    WRITESTEPATTRIB(Float64, file_m, "TaitBryantAngles", (h5_float64_t *)&TaitBryant, 3);
+    WRITESTEPATTRIB(Float64, file_m, "RefPartP", (h5_float64_t*)&RefPartP, 3);
+    WRITESTEPATTRIB(Float64, file_m, "MEANP", (h5_float64_t*)&pmean, 3);
+    WRITESTEPATTRIB(Float64, file_m, "RMSP", (h5_float64_t*)&psigma, 3);
+    WRITESTEPATTRIB(Float64, file_m, "TaitBryantAngles", (h5_float64_t*)&TaitBryant, 3);
 
-    WRITESTEPATTRIB(Float64, file_m, "#varepsilon", (h5_float64_t *)&vareps, 3);
-    WRITESTEPATTRIB(Float64, file_m, "#varepsilon-geom", (h5_float64_t *)&geomvareps, 3);
+    WRITESTEPATTRIB(Float64, file_m, "#varepsilon", (h5_float64_t*)&vareps, 3);
+    WRITESTEPATTRIB(Float64, file_m, "#varepsilon-geom", (h5_float64_t*)&geomvareps, 3);
 
-    WRITESTEPATTRIB(Float64, file_m, "minX", (h5_float64_t *)&rmin, 3);
-    WRITESTEPATTRIB(Float64, file_m, "maxX", (h5_float64_t *)&rmax, 3);
+    WRITESTEPATTRIB(Float64, file_m, "minX", (h5_float64_t*)&rmin, 3);
+    WRITESTEPATTRIB(Float64, file_m, "maxX", (h5_float64_t*)&rmax, 3);
 
-    WRITESTEPATTRIB(Float64, file_m, "minP", (h5_float64_t *)&minP, 3);
-    WRITESTEPATTRIB(Float64, file_m, "maxP", (h5_float64_t *)&maxP, 3);
+    WRITESTEPATTRIB(Float64, file_m, "minP", (h5_float64_t*)&minP, 3);
+    WRITESTEPATTRIB(Float64, file_m, "maxP", (h5_float64_t*)&maxP, 3);
 
     WRITESTEPATTRIB(Int64, file_m, "Step", &numSteps_m, 1);
     WRITESTEPATTRIB(Int64, file_m, "LocalTrackStep", &localTrackStep, 1);
@@ -373,8 +388,8 @@ void H5PartWrapperForPT::writeStepHeader(PartBunchBase<double, 3>* bunch, const
                             additionalStepAttributes.at("E-ref_z"),
                             additionalStepAttributes.at("E-ref_y"));
 
-        WRITESTEPATTRIB(Float64, file_m, "B-ref", (h5_float64_t *)&referenceB, 3);
-        WRITESTEPATTRIB(Float64, file_m, "E-ref", (h5_float64_t *)&referenceE, 3);
+        WRITESTEPATTRIB(Float64, file_m, "B-ref", (h5_float64_t*)&referenceB, 3);
+        WRITESTEPATTRIB(Float64, file_m, "E-ref", (h5_float64_t*)&referenceE, 3);
     } catch (std::out_of_range & m) {
         ERRORMSG(m.what() << endl);
 
@@ -392,75 +407,79 @@ void H5PartWrapperForPT::writeStepData(PartBunchBase<double, 3>* bunch) {
 
     std::vector<char> buffer(numLocalParticles * sizeof(h5_float64_t));
     char* buffer_ptr = Util::c_data(buffer);
-    h5_float64_t *f64buffer = reinterpret_cast<h5_float64_t*>(buffer_ptr);
-    h5_int64_t *i64buffer = reinterpret_cast<h5_int64_t*>(buffer_ptr);
-    h5_int32_t *i32buffer = reinterpret_cast<h5_int32_t*>(buffer_ptr);
+    h5_float64_t* f64buffer = reinterpret_cast<h5_float64_t*>(buffer_ptr);
+    h5_int64_t* i64buffer = reinterpret_cast<h5_int64_t*>(buffer_ptr);
+    h5_int32_t* i32buffer = reinterpret_cast<h5_int32_t*>(buffer_ptr);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         f64buffer[i] =  bunch->R[i](0);
     WRITEDATA(Float64, file_m, "x", f64buffer);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         f64buffer[i] =  bunch->R[i](1);
     WRITEDATA(Float64, file_m, "y", f64buffer);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         f64buffer[i] =  bunch->R[i](2);
     WRITEDATA(Float64, file_m, "z", f64buffer);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         f64buffer[i] =  bunch->P[i](0);
     WRITEDATA(Float64, file_m, "px", f64buffer);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         f64buffer[i] =  bunch->P[i](1);
     WRITEDATA(Float64, file_m, "py", f64buffer);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         f64buffer[i] =  bunch->P[i](2);
     WRITEDATA(Float64, file_m, "pz", f64buffer);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         f64buffer[i] =  bunch->Q[i];
     WRITEDATA(Float64, file_m, "q", f64buffer);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         i64buffer[i] =  bunch->ID[i];
     WRITEDATA(Int64, file_m, "id", i64buffer);
 
-    for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
         i32buffer[i] = (h5_int32_t) bunch->PType[i];
     WRITEDATA(Int32, file_m, "ptype", i32buffer);
 
-    if(Options::ebDump) {
-        for(size_t i = 0; i < numLocalParticles; ++ i)
+    for (size_t i = 0; i < numLocalParticles; ++ i)
+        i32buffer[i] = (h5_int32_t) bunch->POrigin[i];
+    WRITEDATA(Int32, file_m, "porigin", i32buffer);
+
+    if (Options::ebDump) {
+        for (size_t i = 0; i < numLocalParticles; ++ i)
             f64buffer[i] =  bunch->Ef[i](0);
         WRITEDATA(Float64, file_m, "Ex", f64buffer);
 
-        for(size_t i = 0; i < numLocalParticles; ++ i)
+        for (size_t i = 0; i < numLocalParticles; ++ i)
             f64buffer[i] =  bunch->Ef[i](1);
         WRITEDATA(Float64, file_m, "Ey", f64buffer);
 
-        for(size_t i = 0; i < numLocalParticles; ++ i)
+        for (size_t i = 0; i < numLocalParticles; ++ i)
             f64buffer[i] =  bunch->Ef[i](2);
         WRITEDATA(Float64, file_m, "Ez", f64buffer);
 
-        for(size_t i = 0; i < numLocalParticles; ++ i)
+        for (size_t i = 0; i < numLocalParticles; ++ i)
             f64buffer[i] =  bunch->Bf[i](0);
         WRITEDATA(Float64, file_m, "Bx", f64buffer);
 
-        for(size_t i = 0; i < numLocalParticles; ++ i)
+        for (size_t i = 0; i < numLocalParticles; ++ i)
             f64buffer[i] =  bunch->Bf[i](1);
         WRITEDATA(Float64, file_m, "By", f64buffer);
 
-        for(size_t i = 0; i < numLocalParticles; ++ i)
+        for (size_t i = 0; i < numLocalParticles; ++ i)
             f64buffer[i] =  bunch->Bf[i](2);
         WRITEDATA(Float64, file_m, "Bz", f64buffer);
 
     }
 
     /// Write space charge field map if asked for.
-    if(Options::rhoDump) {
+    if (Options::rhoDump) {
         NDIndex<3> idx = bunch->getFieldLayout().getLocalNDIndex();
         NDIndex<3> elem;
         h5_err_t herr = H5Block3dSetView(
@@ -476,9 +495,9 @@ void H5PartWrapperForPT::writeStepData(PartBunchBase<double, 3>* bunch) {
         // h5block uses the fortran convention of storing data:
         // INTEGER, DIMENSION(2,3) :: a
         // => {a(1,1), a(2,1), a(1,2), a(2,2), a(1,3), a(2,3)}
-        for(int i = idx[2].min(); i <= idx[2].max(); ++ i) {
-            for(int j = idx[1].min(); j <= idx[1].max(); ++ j) {
-                for(int k = idx[0].min(); k <= idx[0].max(); ++ k) {
+        for (int i = idx[2].min(); i <= idx[2].max(); ++ i) {
+            for (int j = idx[1].min(); j <= idx[1].max(); ++ j) {
+                for (int k = idx[0].min(); k <= idx[0].max(); ++ k) {
                     data[ii] = bunch->getRho(k, j, i);
                     ++ ii;
                 }
@@ -501,4 +520,4 @@ void H5PartWrapperForPT::writeStepData(PartBunchBase<double, 3>* bunch) {
         reportOnError(herr, __FILE__, __LINE__);
 
     }
-}
\ No newline at end of file
+}
diff --git a/src/Structure/H5PartWrapperForPT.h b/src/Structure/H5PartWrapperForPT.h
index 80022896068a7e9569cbd41f25ba52b2f61ecf04..08b9935d5d4266362826cdae3d7ca1802c0b6c93 100644
--- a/src/Structure/H5PartWrapperForPT.h
+++ b/src/Structure/H5PartWrapperForPT.h
@@ -1,13 +1,22 @@
-#ifndef OPAL_H5PARTWRAPPERFORPT_H
-#define OPAL_H5PARTWRAPPERFORPT_H
-
 //
-//  Copyright & License: See Copyright.readme in src directory
+// Class H5PartWrapperForPT
+//   A class that manages all calls to H5Part for the Parallel-T tracker.
 //
-
-/*!
-  H5PartWrapperForPT: a class that manages all calls to H5Part for the Parallel-T tracker
-*/
+// Copyright (c) 200x-2021, 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 <https://www.gnu.org/licenses/>.
+//
+#ifndef OPAL_H5PARTWRAPPERFORPT_H
+#define OPAL_H5PARTWRAPPERFORPT_H
 
 #include "Structure/H5PartWrapper.h"
 
@@ -15,15 +24,15 @@
 
 class H5PartWrapperForPT: public H5PartWrapper {
 public:
-    H5PartWrapperForPT(const std::string &fileName, h5_int32_t flags = H5_O_WRONLY);
-    H5PartWrapperForPT(const std::string &fileName, int restartStep, std::string sourceFile, h5_int32_t flags = H5_O_RDWR);
+    H5PartWrapperForPT(const std::string& fileName, h5_int32_t flags = H5_O_WRONLY);
+    H5PartWrapperForPT(const std::string& fileName, int restartStep, std::string sourceFile, h5_int32_t flags = H5_O_RDWR);
     virtual ~H5PartWrapperForPT();
 
     virtual void readHeader();
     virtual void readStep(PartBunchBase<double, 3>*, h5_ssize_t firstParticle, h5_ssize_t lastParticle);
 
     virtual void writeHeader();
-    virtual void writeStep(PartBunchBase<double, 3>*, const std::map<std::string, double> &additionalStepAttributes);
+    virtual void writeStep(PartBunchBase<double, 3>*, const std::map<std::string, double>& additionalStepAttributes);
 
     virtual bool predecessorIsSameFlavour() const;
 
@@ -31,7 +40,7 @@ private:
     void readStepHeader(PartBunchBase<double, 3>*);
     void readStepData(PartBunchBase<double, 3>*, h5_ssize_t, h5_ssize_t);
 
-    void writeStepHeader(PartBunchBase<double, 3>*, const std::map<std::string, double> &);
+    void writeStepHeader(PartBunchBase<double, 3>*, const std::map<std::string, double>&);
     void writeStepData(PartBunchBase<double, 3>*);
 };
 
@@ -40,4 +49,4 @@ bool H5PartWrapperForPT::predecessorIsSameFlavour() const {
     return (predecessorOPALFlavour_m == "opal-t");
 }
 
-#endif //OPAL_H5PARTWRAPPERFORPT_H
\ No newline at end of file
+#endif //OPAL_H5PARTWRAPPERFORPT_H
diff --git a/src/Track/TrackRun.cpp b/src/Track/TrackRun.cpp
index fc046a22974beb346340e05494acf6a561010e17..ef3b14ed560a0d5cb8947642247789df97985d97 100644
--- a/src/Track/TrackRun.cpp
+++ b/src/Track/TrackRun.cpp
@@ -323,6 +323,8 @@ void TrackRun::setupTTracker(){
     Beam *beam = Beam::find(Attributes::getString(itsAttr[BEAM]));
     Track::block->bunch->setBeamFrequency(beam->getFrequency() * 1e6);
 
+    Track::block->bunch->setPType(beam->getParticleName());
+
     if (Attributes::getString(itsAttr[BOUNDARYGEOMETRY]) != "NONE") {
         // Ask the dictionary if BoundaryGeometry is allocated.
         // If it is allocated use the allocated BoundaryGeometry
@@ -436,7 +438,8 @@ void TrackRun::setupCyclotronTracker(){
 
     setupFieldsolver();
 
-    Track::block->bunch->PType = ParticleType::REGULAR;
+    Track::block->bunch->setPType(beam->getParticleName());
+    Track::block->bunch->POrigin = ParticleOrigin::REGULAR;
 
     std::vector<std::string> distr_str = Attributes::getStringArray(itsAttr[DISTRIBUTION]);
     if (distr_str.size() == 0) {