diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc
index f98b65a3b2fc262ba14d26f71fe01ccc7dbde65b..fd6055f837736cb4ab1bf75757e044f654015904 100644
--- a/Documentation/Examples/cascade_example.cc
+++ b/Documentation/Examples/cascade_example.cc
@@ -125,6 +125,14 @@ public:
         is_inv = true;
         break;
 
+      case Code::Neutron:
+        is_inv = true;
+        break;
+
+      case Code::AntiNeutron:
+        is_inv = true;
+        break;
+
       default:
         break;
     }
@@ -235,33 +243,39 @@ int main() {
   stack_inspector::StackInspector<setup::Stack> p0(true);
 
   corsika::random::RNGManager::GetInstance().RegisterRandomStream("s_rndm");
-  //  corsika::process::sibyll::Interaction sibyll(env);
-  corsika::process::sibyll::NuclearInteraction sibyll(env);
+  corsika::process::sibyll::Interaction sibyll(env);
+  corsika::process::sibyll::NuclearInteraction sibyllNuc(env);
   corsika::process::sibyll::Decay decay;
   ProcessCut cut(8_GeV);
 
-  corsika::random::RNGManager::GetInstance().RegisterRandomStream("HadronicElasticModel");
-  corsika::process::HadronicElasticModel::HadronicElasticInteraction hadronicElastic(env);
+  // corsika::random::RNGManager::GetInstance().RegisterRandomStream("HadronicElasticModel");
+  // corsika::process::HadronicElasticModel::HadronicElasticInteraction hadronicElastic(env);
 
   corsika::process::TrackWriter::TrackWriter trackWriter("tracks.dat");
 
   // assemble all processes into an ordered process list
-  auto sequence = p0 << sibyll << decay << hadronicElastic << cut << trackWriter;
-
+  //auto sequence = p0 << sibyll << decay << hadronicElastic << cut << trackWriter;
+  auto sequence = p0 << sibyll << sibyllNuc << decay << cut << trackWriter;
+  
   // cout << "decltype(sequence)=" << type_id_with_cvr<decltype(sequence)>().pretty_name()
   // << "\n";
 
   // setup particle stack, and add primary particle
   setup::Stack stack;
   stack.Clear();
-  const HEPEnergyType E0 =
-      100_TeV; // 1_PeV crashes with bad COMboost in second interaction (crash later)
+  const Code beamCode = Code::Carbon;
+  const HEPEnergyType E0 = 100_TeV;
+    //      100_TeV; // 1_PeV crashes with bad COMboost in second interaction (crash later)
   double theta = 0.;
   double phi = 0.;
+  
   {
     auto particle = stack.NewParticle();
-    particle.SetPID(Code::Helium);
-    HEPMomentumType P0 = sqrt(E0 * E0 - Helium::GetMass() * Helium::GetMass());
+    particle.SetPID(beamCode);
+    auto elab2plab = []( HEPEnergyType Elab, HEPMassType m){
+		       return sqrt(Elab * Elab - m * m);
+		     };
+    HEPMomentumType P0 = elab2plab( E0, corsika::particles::GetMass( beamCode ) );
     auto momentumComponents = [](double theta, double phi, HEPMomentumType ptot) {
       return std::make_tuple(ptot * sin(theta) * cos(phi), ptot * sin(theta) * sin(phi),
                              -ptot * cos(theta));
diff --git a/Framework/Particles/NuclearData.xml b/Framework/Particles/NuclearData.xml
index 930a3565a1156689df02552b9e82e0cc7c9dfec2..a1c35c85eafa071fefa62ad21b5b6c4adfeea82f 100644
--- a/Framework/Particles/NuclearData.xml
+++ b/Framework/Particles/NuclearData.xml
@@ -45,6 +45,9 @@
 <particle id="1000100220" name="neon" A="22" Z="10" >
 </particle> 
 
+<particle id="1000160330" name="sulphur" A="33" Z="16" >
+</particle> 
+
 <particle id="1000180400" name="argon" A="40" Z="18" >
 </particle> 
 
diff --git a/Processes/Sibyll/NuclearInteraction.h b/Processes/Sibyll/NuclearInteraction.h
index 90a194e85911c8f459f0baa170671655f557392c..d7f926fd8fdfaf23a81efbdbe0b6d51ca988c9ed 100644
--- a/Processes/Sibyll/NuclearInteraction.h
+++ b/Processes/Sibyll/NuclearInteraction.h
@@ -46,7 +46,7 @@ namespace corsika::process::sibyll {
       using std::endl;
 
       // initialize hadronic interaction module
-      sibyll_ini_();
+      //sibyll_ini_();
       
       // initialize nuclib
       nuc_nuc_ini_();
@@ -185,6 +185,9 @@ namespace corsika::process::sibyll {
     template <typename Particle, typename Stack>
     corsika::process::EProcessReturn DoInteraction(Particle& p, Stack& s) {
 
+      // this routine superimposes different nucleon-nucleon interactions
+      // in a nucleus-nucleus interaction, based the SIBYLL routine SIBNUC 
+
       using namespace corsika::units;
       using namespace corsika::utl;
       using namespace corsika::units::si;
@@ -192,13 +195,19 @@ namespace corsika::process::sibyll {
       using std::cout;
       using std::endl;
 
-      const auto corsikaBeamId = p.GetPID();
-      cout << "NuclearInteraction: DoInteraction: called with:" << corsikaBeamId
+      const auto corsikaProjId = p.GetPID();
+      cout << "NuclearInteraction: DoInteraction: called with:" << corsikaProjId << endl
+	   << "NuclearInteraction: projectile mass: " << corsika::particles::GetMass(corsikaProjId) / 1_GeV
 	   << endl;
-	      
-      if(!IsNucleus(corsikaBeamId))
+      
+      if(!IsNucleus(corsikaProjId)){
+	// this should not happen
+	throw std::runtime_error("Non nuclear projectile in NUCLIB!");
 	return process::EProcessReturn::eOk;
+      }
 
+      fCount++;
+      
       const CoordinateSystem& rootCS =
 	RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
       
@@ -206,43 +215,75 @@ namespace corsika::process::sibyll {
       Point pOrig = p.GetPosition();
       TimeType tOrig = p.GetTime();
 
-      // beam nucleon number
-      const int kABeam = GetNucleusA(corsikaBeamId);
-      // TODO: verify this number !!!
-      if(kABeam>56)
-	throw std::runtime_error("Beam nucleus too large for SIBYLL!");
+      cout << "Interaction: position of interaction: " << pOrig.GetCoordinates()
+	   << endl;
+      cout << "Interaction: time: " << tOrig << endl;      
+      
+      // projectile nucleon number
+      const int kAProj = GetNucleusA(corsikaProjId);
+      if(kAProj>56)
+	throw std::runtime_error("Projectile nucleus too large for NUCLIB!");
       
       // kinematics
-      // define projectile NUCLEON
-      HEPEnergyType const eProjectileLab = p.GetEnergy() / kABeam;
-      auto const pProjectileLab = p.GetMomentum() / kABeam;
+      // define projectile nucleus
+      HEPEnergyType const eProjectileLab = p.GetEnergy();
+      auto const pProjectileLab = p.GetMomentum();
       const FourVector PprojLab(eProjectileLab, pProjectileLab);
 
-      cout << "NuclearInteraction: ebeam lab: " << eProjectileLab / 1_GeV << endl
-	   << "NuclearInteraction: pbeam lab: " << pProjectileLab.GetComponents() / 1_GeV
+      cout << "NuclearInteraction: eProj lab: " << eProjectileLab / 1_GeV << endl
+	   << "NuclearInteraction: pProj lab: " << pProjectileLab.GetComponents() / 1_GeV
 	   << endl;
 
+      // define projectile nucleon
+      HEPEnergyType const eProjectileNucLab = p.GetEnergy() / kAProj;
+      auto const pProjectileNucLab = p.GetMomentum() / kAProj;
+      const FourVector PprojNucLab(eProjectileNucLab, pProjectileNucLab);
+
+      cout << "NuclearInteraction: eProjNucleon lab: " << eProjectileNucLab / 1_GeV << endl
+	   << "NuclearInteraction: pProjNucleon lab: " << pProjectileNucLab.GetComponents() / 1_GeV
+	   << endl;
+
+
       // define target
       // always a nucleon
       // for Sibyll is always a single nucleon
       auto constexpr nucleon_mass = 0.5 * (corsika::particles::Proton::GetMass() +
 					   corsika::particles::Neutron::GetMass());
       // target is always at rest
-      const auto eTargetLab = 0_GeV + nucleon_mass;
-      const auto pTargetLab = MomentumVector(rootCS, 0_GeV, 0_GeV, 0_GeV);
-      const FourVector PtargLab(eTargetLab, pTargetLab);
+      const auto eTargetNucLab = 0_GeV + nucleon_mass;
+      const auto pTargetNucLab = MomentumVector(rootCS, 0_GeV, 0_GeV, 0_GeV);
+      const FourVector PtargNucLab(eTargetNucLab, pTargetNucLab);
       
-      cout << "NuclearInteraction: etarget lab: " << eTargetLab / 1_GeV << endl
-	   << "NuclearInteraction: ptarget lab: " << pTargetLab.GetComponents() / 1_GeV
+      cout << "NuclearInteraction: etarget lab: " << eTargetNucLab / 1_GeV << endl
+	   << "NuclearInteraction: ptarget lab: " << pTargetNucLab.GetComponents() / 1_GeV
 	   << endl;
 
       // center-of-mass energy in nucleon-nucleon frame
-      auto const Ptot4 = PtargLab + PprojLab;
-      HEPEnergyType Ecm = Ptot4.GetNorm();
-      cout << "NuclearInteraction: nuc-nuc cm energy: " << Ecm / 1_GeV << endl;
+      auto const PtotNN4 = PtargNucLab + PprojNucLab;
+      HEPEnergyType EcmNN = PtotNN4.GetNorm();
+      cout << "NuclearInteraction: nuc-nuc cm energy: " << EcmNN / 1_GeV << endl;
+
+      // define boost to NUCLEON-NUCLEON frame
+      COMBoost const boost(PprojNucLab, nucleon_mass);
+      // boost projecticle
+      auto const PprojNucCoM = boost.toCoM(PprojNucLab);
+
+      // boost target
+      auto const PtargNucCoM = boost.toCoM(PtargNucLab);
+
+      cout << "Interaction: ebeam CoM: " << PprojNucCoM.GetTimeLikeComponent() / 1_GeV
+	   << endl
+	   << "Interaction: pbeam CoM: "
+	   << PprojNucCoM.GetSpaceLikeComponents().GetComponents() / 1_GeV << endl;
+      cout << "Interaction: etarget CoM: " << PtargNucCoM.GetTimeLikeComponent() / 1_GeV
+	   << endl
+	   << "Interaction: ptarget CoM: "
+	   << PtargNucCoM.GetSpaceLikeComponents().GetComponents() / 1_GeV << endl;
 
-      const auto beamId = corsika::particles::Proton::GetCode();
       // sample target nucleon number
+      //
+      // proton stand-in for nucleon
+      const auto beamId = corsika::particles::Proton::GetCode();
       const auto currentNode = fEnvironment.GetUniverse()->GetContainingNode(pOrig);
       const auto& mediumComposition =
 	currentNode->GetModelProperties().GetNuclearComposition();
@@ -256,7 +297,7 @@ namespace corsika::process::sibyll {
 
       for (size_t i = 0; i < compVec.size(); ++i) {
 	auto const targetId = compVec[i];
-	const auto [sigProd, nNuc] = GetCrossSection(beamId,targetId,Ecm);
+	const auto [sigProd, nNuc] = GetCrossSection(beamId,targetId,EcmNN);
 	cross_section_of_components[i] = sigProd;
       }
 
@@ -282,59 +323,207 @@ namespace corsika::process::sibyll {
       cout << "NuclearInteraction: sampling nuc. multiple interaction structure.. "<< endl;
       // get nucleon-nucleon cross section
       // (needed to determine number of scatterings)
-      double sigProd, sigEla, dum1, dum2, dum3, dum4;
+      //
+      // TODO: this is an explicit dependence on sibyll
+      //       should be changed to a call to GetCrossSection() of the had. int. implementation
+      //       this also means GetCrossSection has to return the elastic cross section as well
+      double sigProd, sigEla, dum1, dum2, dum3;
       double dumdif[3];
-      const double sqsnuc = Ecm / 1_GeV;
+      const double sqsnuc = EcmNN / 1_GeV;
       const int iBeam = 1;
-      sib_sigma_hp_(iBeam, sqsnuc, dum1, sigEla, sigProd, dumdif, dum3, dum4);	
+      // read hadron-proton cross section table (input: hadron id, CoMenergy, output: cross sections)
+      sib_sigma_hp_(iBeam, sqsnuc, dum1, sigEla, sigProd, dumdif, dum2, dum3);	
       
-      // sample number of interactions (output in common cnucms)
-      // nuclear multiple scattering according to glauber (r.i.p.)
-      int_nuc_( kATarget, kABeam, sigProd, sigEla);
+      // sample number of interactions (only input variables, output in common cnucms)
+      // nuclear multiple scattering according to glauber (r.i.p.)      
+      int_nuc_( kATarget, kAProj, sigProd, sigEla);
 
-      cout << "number of wounded nucleons in target   : " << cnucms_.na << endl
+      cout << "number of nucleons in target           : " << kATarget << endl
+	   << "number of wounded nucleons in target   : " << cnucms_.na << endl
+	   << "number of nucleons in projectile       : " << kAProj << endl
 	   << "number of wounded nucleons in project. : " << cnucms_.nb << endl
 	   << "number of inel. nuc.-nuc. interactions : " << cnucms_.ni << endl
 	   << "number of elastic nucleons in target   : " << cnucms_.nael << endl
-	   << "number of elastic nucleons in project. : " << cnucms_.nbel << endl;
+	   << "number of elastic nucleons in project. : " << cnucms_.nbel << endl
+	   << "impact parameter: " << cnucms_.b << endl;      
       
-      throw std::runtime_error(" end now");      
-
       // calculate fragmentation
-      // call FRAGM (IAT,IAP, NW,B, NF, IAF)
-      // fragm_(kATarget, kABeam, NBT, B, NF, IAF)
+      cout << "calculating nuclear fragments.." << endl;
+      // number of interactions
+      // include elastic
+      const int nElasticNucleons = cnucms_.nbel;
+      const int nInelNucleons = cnucms_.nb;
+      const int nIntProj = nInelNucleons + nElasticNucleons;
+      const double impactPar = cnucms_.b; // only needed to avoid passing common var.
+      int nFragments;
+      // number of fragments is limited to 60      
+      int AFragments[60];
+      // call fragmentation routine
+      // input: target A, projectile A, number of int. nucleons in projectile, impact parameter (fm)
+      // output: nFragments, AFragments
+      // in addition the momenta ar stored in pf in common fragments, neglected
+      fragm_(kATarget, kAProj, nIntProj, impactPar, nFragments, AFragments);
+
+      // this should not occur but well :)
+      if(nFragments>60)
+	throw std::runtime_error("Number of nuclear fragments in NUCLIB exceeded!");
+
+      cout << "number of fragments: " << nFragments << endl;
+      for(int j=0; j<nFragments; ++j)	
+	cout << "fragment: " << j << " A=" << AFragments[j]
+	     << " px=" << fragments_.ppp[j][0]
+	     << " py=" << fragments_.ppp[j][1]
+	     << " pz=" << fragments_.ppp[j][2] 
+	     << endl;
+      
+      // bookeeping accross nucleon-nucleon interactions
+      MomentumVector Plab_all(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV});
+      HEPEnergyType Elab_all = 0_GeV;
 
-      /*
-C.  INPUT: IAP = mass of incident nucleus
-C.         IAT = mass of target   nucleus
-C.         NW = number of wounded nucleons in the beam nucleus
-C.         B  = impact parameter in the interaction
-C.     
-C.  OUTPUT : NF = number of fragments  of the spectator nucleus
-C.           IAF(1:NF) = mass number of each fragment
-C.           PF(3,60) in common block /FRAGMENTS/ contains
-C.           the three momentum components (MeV/c) of each
-C.           fragment in the projectile frame
-C..............................................................
-       */
       
-      // put spectators on intermediate stack
-      //Stack nucs;
+      auto Nucleus = []( int iA ){
+		       //		       int znew = iA / 2.15 + 0.7;
+		       corsika::particles::Code pCode;		       
+		       switch( iA ){
+		       case 2:
+			 pCode = corsika::particles::Deuterium::GetCode();
+			 break;
+			 
+		       case 3:
+			 pCode = corsika::particles::Tritium::GetCode();
+			 break;
+
+		       case 4:
+			 pCode = corsika::particles::Helium::GetCode();
+			 break;
+			 
+		       case 12:
+			 pCode = corsika::particles::Carbon::GetCode();
+			 break;
+
+		       case 14:
+			 pCode = corsika::particles::Nitrogen::GetCode();
+			 break;
+
+		       case 16:
+			 pCode = corsika::particles::Oxygen::GetCode();
+			 break;
+
+		       case 33:
+			 pCode = corsika::particles::Sulphur::GetCode();
+			 break;
+			 
+		       case 40:
+			 pCode = corsika::particles::Argon::GetCode();
+			 break;
+			 
+		       default:
+			 pCode = corsika::particles::Proton::GetCode();
+		       }
+		       return pCode;
+		     };
       
-      // add elastic nucleons to stack
-
-      // add inelastic interactions
+      // put nuclear fragments on corsika stack
+      for(int j=0; j<nFragments; ++j){
+	auto pnew = s.NewParticle();
+	// here we need the nucleonNumber to corsika Id conversion
+	// A =  AFragments[j]
+	// pnew.SetPID( corsika::particles::GetCode( corsika::particles::Nucleus(A,Z) ) );
+	auto pCode = Nucleus( AFragments[j] );
+	pnew.SetPID(pCode);
+	
+	// CORSIKA 7 way
+	// spectators inherit momentum from original projectile
+	const double mass_ratio = corsika::particles::GetMass( pCode ) / corsika::particles::GetMass( corsikaProjId );
+	auto const Plab = PprojLab * mass_ratio;
+	  
+	pnew.SetEnergy(Plab.GetTimeLikeComponent());
+	pnew.SetMomentum(Plab.GetSpaceLikeComponents());
+	pnew.SetPosition(pOrig);
+	pnew.SetTime(tOrig);
+
+	Plab_all += Plab.GetSpaceLikeComponents();
+	Elab_all += Plab.GetTimeLikeComponent();
+      }
       
+      // add elastic nucleons to corsika stack
+      for(int j=0; j<nElasticNucleons; ++j){
+	auto pnew = s.NewParticle();
+	// TODO: sample proton or neutron
+	auto pCode = corsika::particles::Proton::GetCode();
+	pnew.SetPID( pCode );
+
+	// CORSIKA 7 way
+	// elastic nucleons inherit momentum from original projectile
+	// neglecting momentum transfer in interaction
+	const double mass_ratio = corsika::particles::GetMass( pCode ) / corsika::particles::GetMass( corsikaProjId );
+	auto const Plab = PprojLab * mass_ratio;
+
+	pnew.SetEnergy(Plab.GetTimeLikeComponent());
+	pnew.SetMomentum(Plab.GetSpaceLikeComponents());
+	pnew.SetPosition(pOrig);
+	pnew.SetTime(tOrig);
+
+	Plab_all += Plab.GetSpaceLikeComponents();
+	Elab_all += Plab.GetTimeLikeComponent();
+      }
 
-      // move particles to corsika stack
-      // boost
-
+      // add inelastic interactions
+      for(int j=0; j<nInelNucleons; ++j){
+
+	// create nucleon-nucleus inelastic interaction
+	// TODO: switch to DoInteraction() of had. interaction implementation
+	// for now use SIBYLL directly
+	const int kBeamCode = process::sibyll::ConvertToSibyllRaw(corsika::particles::Proton::GetCode());
+	cout << "creating interaction no. "<< j << endl;
+	sibyll_( kBeamCode, kATarget, sqsnuc );
+	decsib_();
+	// print final state
+	int print_unit = 6;
+	sib_list_(print_unit);
+
+	// add particles from sibyll to stack
+	// link to sibyll stack
+	SibStack ss;
+
+	MomentumVector Plab_final(rootCS, {0.0_GeV, 0.0_GeV, 0.0_GeV});
+	HEPEnergyType Elab_final = 0_GeV, Ecm_final = 0_GeV;
+	for (auto& psib : ss) {
+
+	  // skip particles that have decayed in Sibyll
+	  if (psib.HasDecayed()) continue;
+
+	  // // transform energy to lab. frame
+	  auto const pCoM = psib.GetMomentum();
+	  HEPEnergyType const eCoM = psib.GetEnergy();
+	  auto const Plab = boost.fromCoM(FourVector(eCoM, pCoM));
+	  
+	  // add to corsika stack
+	  auto pnew = s.NewParticle();
+	  pnew.SetPID(process::sibyll::ConvertFromSibyll(psib.GetPID()));
+	  pnew.SetEnergy(Plab.GetTimeLikeComponent());
+	  pnew.SetMomentum(Plab.GetSpaceLikeComponents());
+	  pnew.SetPosition(pOrig);
+	  pnew.SetTime(tOrig);
+
+	  Plab_final += pnew.GetMomentum();
+	  Elab_final += pnew.GetEnergy();
+	  Ecm_final += psib.GetEnergy();
+
+	  Plab_all += Plab.GetSpaceLikeComponents();
+	  Elab_all += Plab.GetTimeLikeComponent();
+	}
+	cout << "conservation (all GeV): Ecm_final=" << Ecm_final / 1_GeV
+		  << endl
+		  << "Elab_final=" << Elab_final / 1_GeV
+		  << ", Plab_final=" << (Plab_final / 1_GeV).GetComponents()
+		  << endl;	
+      }
+      cout << "accross all nucleon interactions: Etot lab: " << Elab_all / 1_GeV << endl
+	   << "accross all nucleon interactions: Ptot lab: " << (Plab_all / 1_GeV).GetComponents()
+	   << endl;
       
-      // add proton instead
-      auto pnew = s.NewParticle();
-      pnew.SetPID( corsika::particles::Proton::GetCode() );
-      pnew.SetMomentum( p.GetMomentum() );
-      pnew.SetEnergy( p.GetEnergy() );	
+      //throw std::runtime_error(" stop here");
 
       // delete current particle
       p.Delete();
diff --git a/Processes/Sibyll/sibyll2.3c.h b/Processes/Sibyll/sibyll2.3c.h
index 42d715f698b95a3add3215a8dd3bca85066900ed..639c5a6002b3a1bc6c60e9d701e7d38f7a658971 100644
--- a/Processes/Sibyll/sibyll2.3c.h
+++ b/Processes/Sibyll/sibyll2.3c.h
@@ -83,8 +83,15 @@ extern struct {
     int jja[56], jjb[56], jjint[56][56], jjael[56], jjbel[56];
   } cnucms_;
 
+  /*
+    nuclib common, nuclear FRAGMENTS
 
-
+    COMMON /FRAGMENTS/ PPP(3,60)
+  */
+  extern struct {
+    double ppp[60][3];
+  } fragments_;
+  
   
 // lund random generator setup
 // extern struct {int mrlu[6]; float rrlu[100]; }ludatr_;
@@ -94,16 +101,7 @@ void sibyll_(const int&, const int&, const double&);
 
 // subroutine to initiate sibyll
 void sibyll_ini_();
-
-// subroutine to initiate nuclib  
-void nuc_nuc_ini_();
-
-// subroutine to sample nuclear interaction structure
-  void int_nuc_( const int&, const int&, const double&, const double&);
-
-// subroutine to sample nuclear fragments  
-  void fragm_(const int&, const int&, int&, double&, int&, int&);
-  
+ 
 // subroutine to SET DECAYS
 void dec_ini_();
 
@@ -130,5 +128,19 @@ double get_sibyll_mass2(int&);
 
 // phojet random generator setup
 void pho_rndin_(int&, int&, int&, int&);
+
+
+// NUCLIB
+  
+// subroutine to initiate nuclib  
+void nuc_nuc_ini_();
+
+// subroutine to sample nuclear interaction structure
+void int_nuc_( const int&, const int&, const double&, const double&);
+
+// subroutine to sample nuclear fragments  
+void fragm_(const int&, const int&, const int&, const double&, int&, int*);
+
+  
 }
 #endif