G4QString.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // ------------------------------------------------------------
00030 //      GEANT 4 class implementation file
00031 //
00032 //      ---------------- G4QString ----------------
00033 //      by Mikhail Kossov Oct, 2006
00034 //      class for excited string used by Parton String Models
00035 //   For comparison mirror member functions are taken from G4 classes:
00036 //   G4FragmentingString
00037 //   G4ExcitedStringDecay
00038 // ---------------------------------------------------------------------
00039 // Short description: If partons from the G4QPartonPair are close in
00040 // rapidity, they create Quasmons, but if they are far in the rapidity
00041 // space, they can not interact directly. Say the bottom parton (quark)
00042 // has rapidity 0, and the top parton (antiquark) has rapidity 8, then
00043 // the top quark splits in two by radiating gluon, and each part has
00044 // rapidity 4, then the gluon splits in quark-antiquark pair (rapidity
00045 // 2 each), and then the quark gadiates anothe gluon and reachs rapidity
00046 // 1. Now it can interact with the bottom antiquark, creating a Quasmon
00047 // or a hadron. The intermediate partons is the string ladder.
00048 // ---------------------------------------------------------------------
00049 
00050 //#define debug
00051 //#define pdebug
00052 //#define edebug
00053 
00054 #include <algorithm>
00055 
00056 #include "G4QString.hh"
00057 #include "G4PhysicalConstants.hh"
00058 #include "G4SystemOfUnits.hh"
00059 
00060 // Static parameters definition
00061 G4double G4QString::MassCut=350.*MeV;     // minimum mass cut for the string
00062 G4double G4QString::SigmaQT=0.5*GeV;      // quarkTransverseMomentum distribution parameter
00063 G4double G4QString::DiquarkSuppress=0.1;  // is Diquark suppression parameter  
00064 G4double G4QString::DiquarkBreakProb=0.1; // is Diquark breaking probability 
00065 G4double G4QString::SmoothParam=0.9;      // QGS model parameter
00066 G4double G4QString::StrangeSuppress=0.435;// Strangeness suppression (u:d:s=1:1:0.3 ?M.K.)
00067 G4double G4QString::widthOfPtSquare=-0.72*GeV*GeV; // pt -width2 forStringExcitation
00068 
00069 G4QString::G4QString() : theDirection(0), thePosition(G4ThreeVector(0.,0.,0.)),
00070                          theStableParton(0), theDecayParton(0){}
00071 
00072 G4QString::G4QString(G4QParton* Color, G4QParton* AntiColor, G4int Direction)
00073   : SideOfDecay(0)
00074 {
00075 #ifdef debug
00076   G4cout<<"G4QString::PPD-Constructor: Direction="<<Direction<<G4endl;
00077 #endif
00078   ExciteString(Color, AntiColor, Direction);
00079 #ifdef debug
00080   G4cout<<"G4QString::PPD-Constructor: ------>> String is excited"<<G4endl;
00081 #endif
00082 }
00083 
00084 G4QString::G4QString(G4QPartonPair* CAC): SideOfDecay(0)
00085 {
00086 #ifdef debug
00087   G4cout<<"G4QString::PartonPair-Constructor: Is CALLED"<<G4endl;
00088 #endif
00089   ExciteString(CAC->GetParton1(), CAC->GetParton2(), CAC->GetDirection());
00090 #ifdef debug
00091   G4cout<<"G4QString::PartonPair-Constructor: ------>> String is excited"<<G4endl;
00092 #endif
00093 }
00094 
00095 G4QString::G4QString(G4QParton* QCol,G4QParton* Gluon,G4QParton* QAntiCol,G4int Direction)
00096  : theDirection(Direction), thePosition(QCol->GetPosition()), SideOfDecay(0)
00097 {
00098   thePartons.push_back(QCol);
00099   G4LorentzVector sum=QCol->Get4Momentum();
00100   thePartons.push_back(Gluon);
00101   sum+=Gluon->Get4Momentum();
00102   thePartons.push_back(QAntiCol);
00103   sum+=QAntiCol->Get4Momentum();
00104   Pplus =sum.e() + sum.pz();
00105   Pminus=sum.e() - sum.pz();
00106   decaying=None;
00107 }
00108 
00109 G4QString::G4QString(const G4QString &right) : theDirection(right.GetDirection()),
00110                                                thePosition(right.GetPosition()), SideOfDecay(0)
00111 {
00112   //LeftParton=right.LeftParton;
00113   //RightParton=right.RightParton;
00114   Ptleft=right.Ptleft;
00115   Ptright=right.Ptright;
00116   Pplus=right.Pplus;
00117   Pminus=right.Pminus;
00118   decaying=right.decaying;
00119 }
00120 
00121 G4QString::~G4QString()
00122 {if(thePartons.size()) std::for_each(thePartons.begin(),thePartons.end(),DeleteQParton());}
00123 
00124 G4LorentzVector G4QString::Get4Momentum() const
00125 {
00126   G4LorentzVector momentum(0.,0.,0.,0.);
00127   for(unsigned i=0; i<thePartons.size(); i++) momentum += thePartons[i]->Get4Momentum();
00128   return momentum;
00129 }
00130 
00131 void G4QString::LorentzRotate(const G4LorentzRotation & rotation)
00132 {
00133   for(unsigned i=0; i<thePartons.size(); i++)
00134      thePartons[i]->Set4Momentum(rotation*thePartons[i]->Get4Momentum());
00135 }
00136 
00137 //void G4QString::InsertParton(G4QParton* aParton, const G4QParton* addafter)
00138 //{
00139 //  G4QPartonVector::iterator insert_index;   // Begin by default (? M.K.)
00140 //  if(addafter != NULL) 
00141 //  {
00142 //    insert_index=std::find(thePartons.begin(), thePartons.end(), addafter);
00143 //    if (insert_index == thePartons.end())  // No object addafter in thePartons
00144 //    {
00145 //      G4cerr<<"***G4QString::InsertParton: Addressed Parton is not found"<<G4endl;
00146 //      G4Exception("G4QString::InsertParton:","72",FatalException,"NoAddressParton");
00147 //    }
00148 //  }
00149 //  thePartons.insert(insert_index+1, aParton);
00150 //} 
00151 
00152 void G4QString::Boost(G4ThreeVector& Velocity)
00153 {
00154   for(unsigned cParton=0; cParton<thePartons.size(); cParton++)
00155   {
00156     G4LorentzVector Mom = thePartons[cParton]->Get4Momentum();
00157     Mom.boost(Velocity);
00158     thePartons[cParton]->Set4Momentum(Mom);
00159   }
00160 }
00161 
00162 //G4QParton* G4QString::GetColorParton(void) const
00163 //{
00164 //  G4QParton* start = *(thePartons.begin());
00165 //  G4QParton* end = *(thePartons.end()-1);
00166 //  G4int Encoding = start->GetPDGCode();
00167 //  if (Encoding<-1000 || (Encoding  < 1000 && Encoding > 0)) return start;
00168 //  return end; 
00169 //}
00170 
00171 //G4QParton* G4QString::GetAntiColorParton(void) const
00172 //{
00173 //  G4QParton* start = *(thePartons.begin());
00174 //  G4QParton* end = *(thePartons.end()-1);
00175 //  G4int Encoding = start->GetPDGCode();
00176 //  if (Encoding < -1000 || (Encoding  < 1000 && Encoding > 0)) return end; 
00177 //  return start; 
00178 //}
00179 
00180 // Fill parameters
00181 void G4QString::SetParameters(G4double mCut, G4double sigQT, G4double DQSup, G4double DQBU,
00182                               G4double smPar, G4double SSup, G4double SigPt)
00183 {
00184   MassCut         = mCut;           // minimum mass cut for the string
00185   SigmaQT         = sigQT;          // quark transverse momentum distribution parameter 
00186   DiquarkSuppress = DQSup;          // is Diquark suppression parameter  
00187   DiquarkBreakProb= DQBU;           // is Diquark breaking probability 
00188   SmoothParam     = smPar;          // QGS model parameter
00189   StrangeSuppress = SSup;           // Strangeness suppression parameter
00190   widthOfPtSquare = -2*SigPt*SigPt; // width^2 of pt for string excitation
00191 }
00192 
00193 // Pt distribution @@ one can use 1/(1+A*Pt^2)^B
00194 G4ThreeVector G4QString::GaussianPt(G4double widthSquare, G4double maxPtSquare) const
00195 {
00196   G4double pt2; do{pt2=widthSquare*std::log(G4UniformRand());} while (pt2>maxPtSquare);
00197   pt2=std::sqrt(pt2);
00198   G4double phi=G4UniformRand()*twopi;
00199   return G4ThreeVector(pt2*std::cos(phi),pt2*std::sin(phi),0.);    
00200 } // End of GaussianPt
00201 
00202 // Diffractively excite the string
00203 //void G4QString::DiffString(G4QHadron* hadron, G4bool isProjectile)
00204 //{
00205 //  hadron->SplitUp();
00206 //  G4QParton* start = hadron->GetNextParton();
00207 //  if( start==NULL) 
00208 //  {
00209 //    G4cerr<<"***G4QString::DiffString: No start parton found, nothing is done"<<G4endl;
00210 //    return;
00211 //  }
00212 //  G4QParton* end = hadron->GetNextParton();
00213 //  if( end==NULL) 
00214 //  {
00215 //    G4cerr<<"***G4QString::DiffString: No end parton found, nothing is done"<<G4endl;
00216 //    return;
00217 //  }
00218 //  if(isProjectile) ExciteString(end, start, 1); //  1 = Projectile
00219 //  else             ExciteString(start, end,-1); // -1 = Target
00220 //  SetPosition(hadron->GetPosition());
00221 //  // momenta of string ends
00222 //  G4double ptSquared= hadron->Get4Momentum().perp2();
00223 //  G4double hmins=hadron->Get4Momentum().minus();
00224 //  G4double hplus=hadron->Get4Momentum().plus();
00225 //  G4double transMassSquared=hplus*hmins;
00226 //  G4double maxMomentum = std::sqrt(transMassSquared) - std::sqrt(ptSquared);
00227 //  G4double maxAvailMomentumSquared = maxMomentum * maxMomentum;
00228 //  G4ThreeVector pt=GaussianPt(widthOfPtSquare,maxAvailMomentumSquared);
00229 //  G4LorentzVector Pstart(G4LorentzVector(pt,0.));
00230 //  G4LorentzVector Pend(hadron->Get4Momentum().px(), hadron->Get4Momentum().py(), 0.);
00231 //  Pend-=Pstart;
00232 //  G4double tm1=hmins+(Pend.perp2()-Pstart.perp2())/hplus;
00233 //  G4double tm2=std::sqrt( std::max(0., tm1*tm1-4*Pend.perp2()*hmins/hplus ) );
00234 //  G4int Sign= isProjectile ? TARGET : PROJECTILE;
00235 //  G4double endMinus  = 0.5 * (tm1 + Sign*tm2);
00236 //  G4double startMinus= hmins - endMinus;
00237 //  G4double startPlus = Pstart.perp2() / startMinus;
00238 //  G4double endPlus   = hplus - startPlus;
00239 //  Pstart.setPz(0.5*(startPlus - startMinus));
00240 //  Pstart.setE (0.5*(startPlus + startMinus));
00241 //  Pend.setPz  (0.5*(endPlus - endMinus));
00242 //  Pend.setE   (0.5*(endPlus + endMinus));
00243 //  start->Set4Momentum(Pstart);
00244 //  end->Set4Momentum(Pend);
00245 //#ifdef debug
00246 //  G4cout<<"G4QString::DiffString: StartQ="<<start->GetPDGCode()<<start->Get4Momentum()<<"("
00247 //        <<start->Get4Momentum().mag()<<"), EndQ="<<end->GetPDGCode()<<end ->Get4Momentum()
00248 //        <<"("<<end->Get4Momentum().mag()<<"), sumOfEnds="<<Pstart+Pend<<", H4M(original)="
00249 //        <<hadron->Get4Momentum()<<G4endl;
00250 //#endif
00251 //} // End of DiffString (The string is excited diffractively)
00252 
00253 // Excite the string by two partons
00254 void G4QString::ExciteString(G4QParton* Color, G4QParton* AntiColor, G4int Direction)
00255 {
00256 #ifdef debug
00257   G4cout<<"G4QString::ExciteString: **Called**, direction="<<Direction<<G4endl;
00258 #endif
00259   if(thePartons.size()) std::for_each(thePartons.begin(),thePartons.end(),DeleteQParton());
00260   thePartons.clear();
00261   theDirection = Direction;
00262   thePosition  = Color->GetPosition();
00263 #ifdef debug
00264   G4cout<<"G4QString::ExciteString: ColourPosition = "<<thePosition<<", beg="<<Color->GetPDGCode()
00265           <<",end="<<AntiColor->GetPDGCode()<<G4endl;
00266 #endif
00267   thePartons.push_back(Color);
00268   G4LorentzVector sum=Color->Get4Momentum();
00269   thePartons.push_back(AntiColor); // @@ Complain of Valgrind
00270   sum+=AntiColor->Get4Momentum();
00271   Pplus =sum.e() + sum.pz();
00272   Pminus=sum.e() - sum.pz();
00273   decaying=None;
00274 #ifdef debug
00275   G4cout<<"G4QString::ExciteString: ***Done***, beg="<<(*thePartons.begin())->GetPDGCode()
00276           <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00277 #endif
00278 } // End of ExciteString
00279 
00280 // LUND Longitudinal fragmentation
00281 G4double G4QString::GetLundLightConeZ(G4double zmin, G4double zmax, G4int , // @@ ? M.K.
00282                                       G4QHadron* pHadron, G4double Px, G4double Py)
00283 {
00284   static const G4double  alund = 0.7/GeV/GeV; 
00285   // If blund get restored, you MUST adapt the calculation of zOfMaxyf.
00286   //static const G4double  blund = 1;
00287   G4double z, yf;
00288   G4double Mt2 = Px*Px + Py*Py + pHadron->GetMass2();
00289   G4double zOfMaxyf=alund*Mt2/(alund*Mt2+1.);
00290   G4double maxYf=(1.-zOfMaxyf)/zOfMaxyf * std::exp(-alund*Mt2/zOfMaxyf);
00291   do
00292   {
00293      z = zmin + G4UniformRand()*(zmax-zmin);
00294      // yf = std::pow(1. - z, blund)/z*std::exp(-alund*Mt2/z);
00295      yf = (1-z)/z * std::exp(-alund*Mt2/z);
00296   } while (G4UniformRand()*maxYf>yf); 
00297   return z;
00298 } // End of GetLundLightConeZ
00299 
00300 
00301 // QGSM Longitudinal fragmentation
00302 G4double G4QString::GetQGSMLightConeZ(G4double zmin, G4double zmax, G4int PartonEncoding,
00303                                       G4QHadron* , G4double, G4double) // @@ M.K.
00304 {
00305   static const G4double arho=0.5;
00306   static const G4double aphi=0.;
00307   static const G4double an=-0.5;
00308   static const G4double ala=-0.75;
00309   static const G4double aksi=-1.;
00310   static const G4double alft=0.5;
00311   G4double z;    
00312   G4double theA(0), d2, yf;
00313   G4int absCode = std::abs(PartonEncoding);
00314   // @@ Crazy algorithm is used for simple power low...
00315   if (absCode < 10)                            // Quarks (@@ 9 can be a gluon)
00316   { 
00317     if(absCode == 1 || absCode == 2) theA = arho;
00318     else if(absCode == 3)            theA = aphi;
00319     else
00320     {
00321      G4cerr<<"***G4QString::GetQGSMLightConeZ: CHIPS is SU(3), quakCode="<<absCode<<G4endl;
00322      G4Exception("G4QString::GetQGSMLightConeZ:","72",FatalException,"WrongQuark");
00323     }
00324     do  
00325     {
00326       z  = zmin + G4UniformRand()*(zmax - zmin);
00327       d2 = alft - theA;
00328       yf = std::pow( 1.-z, d2);
00329     } 
00330     while (G4UniformRand()>yf);
00331   }
00332   else                                     // Di-quarks (@@ Crazy codes are not checked)
00333   {       
00334     if (absCode==3101||absCode==3103||absCode==3201||absCode==3203)   d2=alft-ala-ala+arho;
00335     else if(absCode==1103||absCode==2101||absCode==2203||absCode==2103) d2=alft-an-an+arho;
00336     else                                                            d2=alft-aksi-aksi+arho;
00337     do  
00338     {
00339       z = zmin + G4UniformRand()*(zmax - zmin);
00340       yf = std::pow(1.-z, d2);
00341     } 
00342     while (G4UniformRand()>yf); 
00343   }
00344   return z;
00345 } // End of GetQGSMLightConeZ
00346 
00347 // Diffractively excite the string (QL=true - QGS Light Cone, =false - Lund Light Cone)
00348 G4QHadronVector* G4QString::FragmentString(G4bool QL)
00349 {
00350   // Can no longer modify Parameters for Fragmentation.
00351 #ifdef edebug
00352   G4LorentzVector string4M=Get4Momentum();         // Just for Energy-Momentum ConservCheck
00353 #endif 
00354 #ifdef debug
00355   G4cout<<"G4QString::FragmentString:-->Called,QL="<<QL<<", M="<<Get4Momentum().m()<<", L="
00356         <<GetLeftParton()->Get4Momentum()<<",R="<<GetRightParton()->Get4Momentum()<<G4endl;
00357 #endif 
00358   //  check if string has enough mass to fragment. If not, convert to one or two hadrons
00359   G4QHadronVector* LeftVector = LightFragmentationTest();
00360   if(LeftVector)
00361   {
00362 #ifdef edebug
00363     G4LorentzVector sL=string4M;
00364     for(unsigned L = 0; L < LeftVector->size(); L++)
00365     {
00366       G4QHadron* LH = (*LeftVector)[L];
00367       G4LorentzVector L4M=LH->Get4Momentum();
00368       sL-=L4M;
00369       G4cout<<"-EMC-G4QStr::FragStr:L#"<<L<<",PDG="<<LH->GetPDGCode()<<",4M="<<L4M<<G4endl;
00370     }
00371     G4cout<<"-EMC-G4QString::FragmentString:---LightFragmentation---> Res4M="<<sL<<G4endl;
00372 #endif 
00373     return LeftVector; //@@ Just decay in 2 or 1 (?) hadron, if below theCut
00374   }
00375 #ifdef debug
00376   G4cout<<"G4QString::FragmentString:OUTPUT is not yet defined, define Left/Right"<<G4endl;
00377 #endif  
00378   LeftVector = new G4QHadronVector; // Valgrind complain to LeftVector
00379   G4QHadronVector* RightVector = new G4QHadronVector;
00380   // Remember 4-momenta of the string ends (@@ only for the two-parton string, no gluons)
00381   G4LorentzVector left4M=GetLeftParton()->Get4Momentum(); // For recovery when failed
00382   G4LorentzVector right4M=GetRightParton()->Get4Momentum();
00383 #ifdef debug
00384   G4cout<<"G4QString::FragmString: ***Remember*** L4M="<<left4M<<", R4M="<<right4M<<G4endl;
00385 #endif
00386   G4int leftPDG=GetLeftParton()->GetPDGCode();
00387   G4int rightPDG=GetRightParton()->GetPDGCode();
00388   // Transform string to CMS
00389   G4LorentzVector momentum=Get4Momentum();
00390   G4LorentzRotation toCms(-(momentum.boostVector()));
00391   momentum= toCms * thePartons[0]->Get4Momentum();
00392   toCms.rotateZ(-1*momentum.phi());
00393   toCms.rotateY(-1*momentum.theta());
00394   for(unsigned index=0; index<thePartons.size(); index++)
00395   {
00396     momentum = toCms * thePartons[index]->Get4Momentum(); // @@ reuse of the momentum
00397     thePartons[index]->Set4Momentum(momentum);
00398   }
00399   // Copy the string for independent attempts
00400   G4QParton* LeftParton = new G4QParton(GetLeftParton());
00401   G4QParton* RightParton= new G4QParton(GetRightParton());
00402   G4QString* theStringInCMS = new G4QString(LeftParton,RightParton,GetDirection());
00403 #ifdef debug
00404   G4cout<<"G4QString::FragmentString: Copy with nP="<<theStringInCMS->thePartons.size()
00405         <<", beg="<<(*(theStringInCMS->thePartons.begin()))->GetPDGCode()
00406         <<", end="<<(*(theStringInCMS->thePartons.end()-1))->GetPDGCode()<<G4endl;
00407 #endif 
00408   G4bool success=false;
00409   G4bool inner_sucess=true;
00410   G4int attempt=0;
00411   G4int StringLoopInterrupt=27;  // String fragmentation LOOP limit 
00412 #ifdef debug
00413   G4cout<<"G4QString::FragmentString: BeforeWhileLOOP, max = "<<StringLoopInterrupt
00414         <<", nP="<<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
00415         <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00416 #endif
00417 #ifdef edebug
00418   G4LorentzVector cmS4M=theStringInCMS->Get4Momentum();
00419   G4cout<<"-EMC-G4QString::FragmString: c4M="<<cmS4M<<",Max="<<StringLoopInterrupt<<G4endl;
00420 #endif
00421   while (!success && attempt++ < StringLoopInterrupt) // Try fragment String till success
00422   {
00423     // Recover the CMS String
00424     LeftParton = new G4QParton(theStringInCMS->GetLeftParton());
00425     RightParton= new G4QParton(theStringInCMS->GetRightParton());
00426     ExciteString(LeftParton, RightParton, theStringInCMS->GetDirection());
00427 #ifdef edebug
00428     G4LorentzVector cm4M=cmS4M;    // Copy the full momentum for the reduction and check
00429     G4cout<<"-EMC-.G4QString::FragmentString: CHEK "<<cm4M<<" ?= "<<Get4Momentum()<<G4endl;
00430 #endif 
00431 #ifdef debug
00432     G4cout<<"G4QString::FragmentString:===>LOOP, attempt = "<<attempt<<", nP="
00433           <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
00434           <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00435 #endif 
00436     // Now clean up all hadrons in the Left and Right vectors for the new attempt
00437     if(LeftVector->size())
00438     {
00439       std::for_each(LeftVector->begin(), LeftVector->end(), DeleteQHadron());
00440       LeftVector->clear();
00441     }
00442     //delete LeftVector; // @@ Valgrind ?
00443     if(RightVector->size())
00444     {
00445       std::for_each(RightVector->begin(), RightVector->end(), DeleteQHadron());
00446       RightVector->clear();
00447     }
00448     //delete RightVector; // @@ Valgrind ?
00449     inner_sucess=true;                                           // set false on failure
00450     while (!StopFragmentation())                                 // LOOP with break
00451     {  // Split current string into hadron + new string state
00452 #ifdef debug
00453       G4cout<<"G4QString::FragmentString:-->Begin LOOP/LOOP, decaying="<<decaying<<G4endl;
00454 #endif 
00455       G4QHadron* Hadron=Splitup(QL); // MAIN: where the hadron is split from the string
00456 #ifdef edebug
00457       cm4M-=Hadron->Get4Momentum();
00458       G4cout<<"-EMC-G4QString::FragmentString:LOOP/LOOP,d4M="<<cm4M-Get4Momentum()<<G4endl;
00459 #endif
00460       G4bool canBeFrag=IsFragmentable();
00461 #ifdef debug
00462       G4cout<<"G4QString::FragmentString: LOOP/LOOP, canBeFrag="<<canBeFrag<<", decay="
00463             <<decaying<<", H="<<Hadron<<", newStringMass="<<Get4Momentum().m()<<G4endl;
00464 #endif 
00465       if(Hadron && canBeFrag)
00466       {
00467 #ifdef debug
00468         G4cout<<">>G4QString::FragmentString: LOOP/LOOP-NO FRAGM-, dec="<<decaying<<G4endl;
00469 #endif 
00470         if(GetDecayDirection()>0) LeftVector->push_back(Hadron);
00471         else RightVector->push_back(Hadron);
00472       }
00473       else
00474       {
00475         // @@ Try to convert to the resonance and decay, abandon if M<mGS+mPI0
00476         // abandon ... start from the beginning
00477 #ifdef debug
00478         G4cout<<"G4QString::FragmentString: LOOP/LOOP, Start from scratch"<<G4endl;
00479 #endif 
00480         if (Hadron) delete Hadron;
00481         inner_sucess=false;
00482         break;
00483       }
00484 #ifdef debug
00485       G4cout<<"G4QString::FragmentString: LOOP/LOOP End, nP="
00486             <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
00487             <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00488 #endif 
00489     } 
00490 #ifdef edebug
00491     G4LorentzVector fLR=cmS4M-Get4Momentum();
00492     for(unsigned L = 0; L < LeftVector->size(); L++)
00493     {
00494       G4QHadron* LH = (*LeftVector)[L];
00495       G4LorentzVector L4M=LH->Get4Momentum();
00496       fLR-=L4M;
00497       G4cout<<"-EMC-G4QStr::FrStr:L#"<<L<<",PDG="<<LH->GetPDGCode()<<",4M="<<L4M<<G4endl;
00498     }
00499     for(unsigned R = 0; R < RightVector->size(); R++)
00500     {
00501       G4QHadron* RH = (*RightVector)[R];
00502       G4LorentzVector R4M=RH->Get4Momentum();
00503       fLR-=R4M;
00504       G4cout<<"-EMC-G4QStr::FrStr:R#"<<R<<",PDG="<<RH->GetPDGCode()<<",4M="<<R4M<<G4endl;
00505     }
00506     G4cout<<"-EMC-G4QString::FragmentString:L/R_BeforLast->r4M/M2="<<fLR<<fLR.m2()<<G4endl;
00507 #endif 
00508     // Split current string into 2 final Hadrons
00509 #ifdef debug
00510     G4cout<<"G4QString::FragmentString: inner_success = "<<inner_sucess<<G4endl;
00511 #endif
00512     if(inner_sucess)
00513     {
00514       success=true;                                      // Default prototype
00515       //... perform last cluster decay
00516       G4LorentzVector tot4M = Get4Momentum();
00517       G4double totM    = tot4M.m(); 
00518 #ifdef debug
00519       G4cout<<"G4QString::FragmString: string4M="<<tot4M<<totM<<G4endl;
00520 #endif 
00521       G4QHadron* LeftHadron;
00522       G4QHadron* RightHadron;
00523       G4QParton* RQuark = 0;
00524       SetLeftPartonStable();              // to query quark contents
00525       if(DecayIsQuark() && StableIsQuark()) // There're quarks on clusterEnds
00526       {
00527 #ifdef debug
00528         G4cout<<"G4QString::FragmentString: LOOP Quark Algorithm"<<G4endl;
00529 #endif 
00530         LeftHadron= QuarkSplitup(GetLeftParton(), RQuark);
00531       }
00532       else
00533       {
00534 #ifdef debug
00535         G4cout<<"G4QString::FragmentString: LOOP Di-Quark Algorithm"<<G4endl;
00536 #endif 
00537         //... there is a Diquark on cluster ends
00538         G4int IsParticle;
00539         if(StableIsQuark()) IsParticle=(GetLeftParton()->GetPDGCode()>0)?-1:1;
00540         else                IsParticle=(GetLeftParton()->GetPDGCode()>0)?1:-1;
00541         G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks
00542         RQuark = QuarkPair.GetParton2();
00543         G4QParton* LQuark = QuarkPair.GetParton1();
00544         LeftHadron = CreateHadron(LQuark, GetLeftParton()); // Create Left Hadron
00545         delete LQuark;                                      // Delete the temporaryParton
00546       }
00547       RightHadron = CreateHadron(GetRightParton(), RQuark); // Create Right Hadron
00548       delete RQuark;                                        // Delete the temporaryParton
00549       //... repeat procedure, if mass of cluster is too low to produce hadrons
00550       G4double LhM=LeftHadron->GetMass();
00551       G4double RhM=RightHadron->GetMass();
00552 #ifdef debug
00553       G4cout<<"G4QStr::FrSt:L="<<LeftHadron->GetPDGCode()<<",R="<<RightHadron->GetPDGCode()
00554             <<",ML="<<LhM<<",MR="<<RhM<<",SumM="<<LhM+RhM<<",tM="<<totM<<G4endl;
00555 #endif
00556       if(totM < LhM + RhM) success=false;
00557       //... compute hadron momenta and energies   
00558       if(success)
00559       {
00560         G4ThreeVector    Pos=GetPosition();
00561         G4LorentzVector  Lh4M(0.,0.,0.,LhM);
00562         G4LorentzVector  Rh4M(0.,0.,0.,RhM);
00563         if(G4QHadron(tot4M).DecayIn2(Lh4M,Rh4M))
00564         {
00565           LeftVector->push_back(new G4QHadron(LeftHadron, 0, Pos, Lh4M));
00566           delete LeftHadron;
00567           RightVector->push_back(new G4QHadron(RightHadron, 0, Pos, Rh4M));
00568           delete RightHadron;
00569         }
00570 #ifdef debug
00571         G4cout<<"->>G4QStr::FragString:HFilled (L) PDG="<<LeftHadron->GetPDGCode()<<", 4M="
00572               <<Lh4M<<", (R) PDG="<<RightHadron->GetPDGCode()<<", 4M="<<Rh4M<<G4endl;
00573 #endif
00574 #ifdef edebug
00575           G4cout<<"-EMC-G4QString::FragmentString: Residual4M="<<tot4M-Lh4M-Rh4M<<G4endl;
00576 #endif
00577       }
00578       else
00579       {
00580         if(LeftHadron)  delete LeftHadron;
00581         if(RightHadron) delete RightHadron;
00582       }
00583     } // End of inner success
00584   } // End of while
00585   delete theStringInCMS;
00586 #ifdef debug
00587   G4cout<<"G4QString::FragmentString: LOOP/LOOP, success="<<success<<G4endl;
00588 #endif 
00589   if (!success)
00590   {
00591     if(RightVector->size())
00592     {
00593       std::for_each(RightVector->begin(), RightVector->end(), DeleteQHadron());
00594       RightVector->clear();
00595     }
00596     delete RightVector;
00597     if(LeftVector->size())
00598     {
00599       std::for_each(LeftVector->begin(), LeftVector->end(), DeleteQHadron());
00600       LeftVector->clear();
00601     }
00602     delete LeftVector;
00603 #ifdef debug
00604     G4cout<<"G4QString::FragmString:StringNotFragm,L4M="<<left4M<<",R4M="<<right4M<<G4endl;
00605 #endif
00606     // Recover the Left/Right partons 4-moms of the String in ZLS
00607     GetLeftParton()->SetPDGCode(leftPDG);
00608     GetRightParton()->SetPDGCode(rightPDG);
00609     GetLeftParton()->Set4Momentum(left4M);
00610     GetRightParton()->Set4Momentum(right4M);
00611     return 0;                         // The string can not be fragmented
00612   }
00613   // @@@@@ Print collected Left and Right Hadrons (decay resonances!)
00614 #ifdef edebug
00615   G4LorentzVector sLR=cmS4M;
00616   for(unsigned L = 0; L < LeftVector->size(); L++)
00617   {
00618     G4QHadron* LH = (*LeftVector)[L];
00619     G4LorentzVector L4M=LH->Get4Momentum();
00620     sLR-=L4M;
00621     G4cout<<"-EMC-G4QStr::FragmStri:L#"<<L<<",PDG="<<LH->GetPDGCode()<<",4M="<<L4M<<G4endl;
00622   }
00623   for(unsigned R = 0; R < RightVector->size(); R++)
00624   {
00625     G4QHadron* RH = (*RightVector)[R];
00626     G4LorentzVector R4M=RH->Get4Momentum();
00627     sLR-=R4M;
00628     G4cout<<"-EMC-G4QStr::FragmStri:R#"<<R<<",PDG="<<RH->GetPDGCode()<<",4M="<<R4M<<G4endl;
00629   }
00630   G4cout<<"-EMC-G4QString::FragmentString:---L/R_BeforeMerge---> Res4M="<<sLR<<G4endl;
00631 #endif 
00632   // Join Left and Right Vectors into LeftVector in correct order.
00633   while(!RightVector->empty())
00634   {
00635      LeftVector->push_back(RightVector->back());
00636      RightVector->erase(RightVector->end()-1);
00637   }
00638   delete RightVector;
00639   // @@ A trick, the real bug should be found !!
00640   G4QHadronVector::iterator ilv;                                           // @@
00641   for(ilv = LeftVector->begin(); ilv < LeftVector->end(); ilv++)           // @@
00642   {
00643     G4ThreeVector CV=(*ilv)->Get4Momentum().vect();                        // @@
00644     if(CV.x()==0. && CV.y()==0. && CV.z()==0.) LeftVector->erase(ilv);     // @@
00645   }
00646   // Calculate time and position of hadrons with @@ very rough formation time
00647   G4double StringMass=Get4Momentum().mag();
00648   static const G4double dkappa = 2.0 * GeV/fermi; // @@ 2*kappa kappa=1 GeV/fermi (?)
00649   for(unsigned c1 = 0; c1 < LeftVector->size(); c1++)
00650   {
00651     G4double SumPz = 0; 
00652     G4double SumE  = 0;
00653     for(unsigned c2 = 0; c2 < c1; c2++)
00654     {
00655       G4LorentzVector hc2M=(*LeftVector)[c2]->Get4Momentum();
00656       SumPz += hc2M.pz();
00657       SumE  += hc2M.e();   
00658     }
00659     G4QHadron* hc1=(*LeftVector)[c1];
00660     G4LorentzVector hc1M=hc1->Get4Momentum();
00661     G4double HadronE = hc1M.e();
00662     G4double HadronPz= hc1M.pz();
00663     hc1->SetFormationTime((StringMass-SumPz-SumPz+HadronE-HadronPz)/dkappa);
00664     hc1->SetPosition(G4ThreeVector(0,0,(StringMass-SumE-SumE-HadronE+HadronPz)/dkappa));
00665   } 
00666   G4LorentzRotation toObserverFrame(toCms.inverse());
00667 #ifdef debug
00668   G4cout<<"G4QString::FragmentString: beforeLoop LVsize = "<<LeftVector->size()<<G4endl;
00669 #endif 
00670   for(unsigned C1 = 0; C1 < LeftVector->size(); C1++)
00671   {
00672     G4QHadron* Hadron = (*LeftVector)[C1];
00673     G4LorentzVector Momentum = Hadron->Get4Momentum();
00674     Momentum = toObserverFrame*Momentum;
00675     Hadron->Set4Momentum(Momentum);
00676     G4LorentzVector Coordinate(Hadron->GetPosition(), Hadron->GetFormationTime());
00677     Momentum = toObserverFrame*Coordinate;
00678     Hadron->SetFormationTime(Momentum.e());
00679     Hadron->SetPosition(GetPosition()+Momentum.vect());
00680   }
00681 #ifdef edebug
00682   G4LorentzVector sLA=string4M;
00683   for(unsigned L = 0; L < LeftVector->size(); L++)
00684   {
00685     G4QHadron* LH = (*LeftVector)[L];
00686     G4LorentzVector L4M=LH->Get4Momentum();
00687     sLA-=L4M;
00688     G4cout<<"-EMC-G4QStr::FragmStri:L#"<<L<<",PDG="<<LH->GetPDGCode()<<",4M="<<L4M<<G4endl;
00689   }
00690   G4cout<<"-EMC-G4QString::FragmentString:---LSAfterMerge&Conv---> Res4M="<<sLA<<G4endl;
00691 #endif 
00692 #ifdef debug
00693   G4cout<<"G4QString::FragmentString: *** Done *** "<<G4endl;
00694 #endif 
00695   return LeftVector; // Should be deleted by user (@@ Valgrind complain ?)
00696 } // End of FragmentString
00697 
00698 // Simple decay of the string if the excitation mass is too small for HE fragmentation
00699 // !! If the mass is below the single hadron threshold, make warning (improve) and convert
00700 // the string to the single S-hadron breaking energy conservation (temporary) and improve,
00701 // taking the threshold into account on the level of the String creation (merge strings) !!
00702 G4QHadronVector* G4QString::LightFragmentationTest()
00703 {
00704   // Check string decay threshold
00705   G4LorentzVector tot4M=Get4Momentum();
00706 #ifdef debug
00707   G4cout<<"G4QString::LightFragmentationTest: ***Called***, string4M="<<tot4M<<G4endl;
00708 #endif 
00709   G4QHadronVector* result=0;  // return 0 when string exceeds the mass cut or below mh1+mh2
00710  
00711   G4QHadronPair hadrons((G4QHadron*)0, (G4QHadron*)0); // pair of hadrons for output of FrM
00712   G4double fragMass = FragmentationMass(0,&hadrons);   // Minimum mass to decay the string
00713 #ifdef debug
00714   G4cout<<"G4QString::LightFragTest: before check nP="<<thePartons.size()<<", MS2="
00715         <<Mass2()<<", MCut="<<MassCut<<", beg="<<(*thePartons.begin())->GetPDGCode()
00716         <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<", fM="<<fragMass<<G4endl;
00717 #endif  
00718   if(Mass2() > sqr(fragMass+MassCut))// Big enough to fragment in a lader (avoid the decay)
00719   {
00720     if(hadrons.first) delete hadrons.first;
00721     if(hadrons.second) delete hadrons.second;
00722 #ifdef debug
00723     G4cout<<"G4QString::LightFragTest:NO,M2="<<Mass2()<<">"<<sqr(fragMass+MassCut)<<G4endl;
00724 #endif  
00725     return result;                          // =0. Depends on the parameter of the Mass Cut
00726   }
00727   G4double totM= tot4M.m();
00728   G4QHadron* h1=hadrons.first;
00729   G4QHadron* h2=hadrons.second;
00730   if(h1 && h2)
00731   {
00732     G4double h1M = h1->GetMass();
00733     G4double h2M = h2->GetMass();
00734 #ifdef debug
00735     G4cout<<"G4QString::LightFragTest:tM="<<totM<<","<<h1M<<"+"<<h2M<<"+"<<h1M+h2M<<G4endl;
00736 #endif
00737     if(h1M + h2M <= totM)                   // The string can decay in these two hadrons
00738     {  
00739       // Create two stable hadrons
00740       G4LorentzVector  h4M1(0.,0.,0.,h1M);
00741       G4LorentzVector  h4M2(0.,0.,0.,h2M);
00742       if(G4QHadron(tot4M).DecayIn2(h4M1,h4M2))
00743       {
00744         result = new G4QHadronVector;        
00745         result->push_back(new G4QHadron(hadrons.first, 0, GetPosition(), h4M1));
00746         result->push_back(new G4QHadron(hadrons.second,0, GetPosition(), h4M2));
00747       }
00748 #ifdef edebug
00749       G4int L=result->size(); if(L) for(G4int i=0; i<L; i++) 
00750       {
00751         tot4M-=(*result)[i]->Get4Momentum();
00752         G4cout<<"-EMC-G4QString::LightFragTest: i="<<i<<", residual4M="<<tot4M<<G4endl;
00753       }
00754 #endif
00755     }
00756 #ifdef debug
00757     else G4cout<<"-Warning-G4QString::LightFragTest: TooBigHadronMasses to decay"<<G4endl;
00758 #endif
00759   }
00760 #ifdef debug
00761   else G4cout<<"-Warning-G4QString::LightFragTest: No Hadrons have been proposed"<<G4endl;
00762 #endif
00763   delete hadrons.first;
00764   delete hadrons.second;
00765   return result;
00766 } // End of LightFragmentationTest
00767 
00768 // Calculate Fragmentation Mass (if pdefs # 0, returns two hadrons)
00769 G4double G4QString::FragmentationMass(G4int HighSpin, G4QHadronPair* pdefs)
00770 {
00771   G4double mass=0.;
00772 #ifdef debug
00773   G4cout<<"G4QString::FragmMass: ***Called***, s4M="<<Get4Momentum()<<G4endl;
00774 #endif 
00775   // Example how to use an interface to different member functions
00776   G4QHadron* Hadron1 = 0;
00777   G4QHadron* Hadron2 = 0;
00778 #ifdef debug
00779   G4cout<<"G4QString::FragmentationMass: Create spin-0 or spin-1/2 hadron: nP="
00780         <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
00781         <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00782 #endif 
00783   G4int iflc = (G4UniformRand() < 0.5) ? 1 : 2; // Create additional Q-antiQ pair @@ No S
00784   G4int LPDG= GetLeftParton()->GetPDGCode();
00785   G4int LT  = GetLeftParton()->GetType();
00786   if ( (LPDG > 0 && LT == 1)  || (LPDG < 0 && LT == 2) ) iflc = -iflc; // anti-quark
00787   G4QParton* piflc = new G4QParton( iflc);
00788   G4QParton* miflc = new G4QParton(-iflc);
00789   if(HighSpin)
00790   {
00791     Hadron1 = CreateHighSpinHadron(GetLeftParton(),piflc);
00792     Hadron2 = CreateHighSpinHadron(GetRightParton(),miflc);
00793 #ifdef debug
00794     G4cout<<"G4QString::FragmentationMass: High, PDG1="<<Hadron1->GetPDGCode()
00795           <<", PDG2="<<Hadron2->GetPDGCode()<<G4endl;
00796 #endif 
00797   }
00798   else
00799   {
00800     Hadron1 = CreateLowSpinHadron(GetLeftParton(),piflc);
00801     Hadron2 = CreateLowSpinHadron(GetRightParton(),miflc);
00802 #ifdef debug
00803     G4cout<<"G4QString::FragmentationMass: Low, PDG1="<<Hadron1->GetPDGCode()
00804           <<", PDG2="<<Hadron2->GetPDGCode()<<G4endl;
00805 #endif 
00806   }
00807   mass    = Hadron1->GetMass() + Hadron2->GetMass();
00808   if(pdefs) // need to return hadrons as well as the mass estimate 
00809   {
00810     pdefs->first  = Hadron1;  // To be deleted by the calling program if not zero
00811     pdefs->second = Hadron2;  // To be deleted by the calling program if not zero
00812   }
00813   else      // Forget about the hadrons
00814   {
00815     if(Hadron1) delete Hadron1;
00816     if(Hadron2) delete Hadron2;
00817   }
00818   delete piflc;
00819   delete miflc;
00820 #ifdef debug
00821   G4cout<<"G4QString::FragmentationMass: ***Done*** mass="<<mass<<G4endl;
00822 #endif 
00823   return mass;
00824 } // End of FragmentationMass
00825 
00826 void G4QString::SetLeftPartonStable()
00827 {
00828   theStableParton=GetLeftParton();
00829   theDecayParton=GetRightParton();
00830   decaying=Right;
00831 }
00832 
00833 void G4QString::SetRightPartonStable()
00834 {
00835   theStableParton=GetRightParton();
00836   theDecayParton=GetLeftParton();
00837   decaying=Left;
00838 }
00839 
00840 G4int G4QString::GetDecayDirection() const
00841 {
00842   if      (decaying == Left ) return +1;
00843   else if (decaying == Right) return -1;
00844   else
00845   {
00846     G4cerr<<"***G4QString::GetDecayDirection: wrong DecayDirection="<<decaying<<G4endl;
00847     G4Exception("G4QString::GetDecayDirection:","72",FatalException,"WrongDecayDirection");
00848   }
00849   return 0;
00850 }
00851 
00852 //G4ThreeVector G4QString::StablePt()
00853 //{
00854 //  if (decaying == Left ) return Ptright;
00855 //  else if (decaying == Right ) return Ptleft;
00856 //  else
00857 //  {
00858 //    G4cerr<<"***G4QString::StablePt: wrong DecayDirection="<<decaying<<G4endl;
00859 //    G4Exception("G4QString::StablePt:","72",FatalException,"WrongDecayDirection");
00860 //  }
00861 //  return G4ThreeVector();
00862 //}
00863 
00864 G4ThreeVector G4QString::DecayPt()
00865 {
00866   if      (decaying == Left  ) return Ptleft;
00867   else if (decaying == Right ) return Ptright;
00868   else
00869   {
00870     G4cerr<<"***G4QString::DecayPt: wrong DecayDirection="<<decaying<<G4endl;
00871     G4Exception("G4QString::DecayPt:","72",FatalException,"WrongDecayDirection");
00872   }
00873   return G4ThreeVector();
00874 }
00875 
00876 // Random choice of string end to use it for creating the hadron (decay)   
00877 G4QHadron* G4QString::Splitup(G4bool QL)
00878 {
00879   SideOfDecay = (G4UniformRand() < 0.5) ? 1: -1;
00880 #ifdef debug
00881   G4cout<<"G4QString::Splitup:**Called**,s="<<SideOfDecay<<",s4M="<<Get4Momentum()<<G4endl;
00882 #endif
00883   if(SideOfDecay<0) SetLeftPartonStable();  // Decay Right parton
00884   else              SetRightPartonStable(); // Decay Left parton
00885   G4QParton* newStringEnd;
00886   G4QHadron* Hadron;
00887   if(DecayIsQuark()) Hadron= QuarkSplitup(theDecayParton, newStringEnd);   // Split Quark
00888   else               Hadron= DiQuarkSplitup(theDecayParton, newStringEnd); // Split DiQuark
00889 #ifdef debug
00890   G4cout<<"G4QString::Splitup: newStringEndPDG="<<newStringEnd->GetPDGCode()<<", nP="
00891           <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
00892           <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00893 #endif
00894   // create new String from the old one: keep Left and Right order, but replace decay
00895   G4LorentzVector* HadronMomentum=SplitEandP(Hadron, QL);//The decayed parton isn't changed
00896 #ifdef debug
00897   G4cout<<"G4QString::Splitup: HM="<<HadronMomentum<<", nP="
00898           <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
00899           <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00900 #endif
00901   if(HadronMomentum) // The decay succeeded, now the new 4-mon can be set to NewStringEnd
00902   {    
00903 #ifdef pdebug
00904     G4cout<<"---->>G4QString::Splitup: HFilled 4M="<<*HadronMomentum<<",PDG="
00905           <<Hadron->GetPDGCode()<<",s4M-h4M="<<Get4Momentum()-*HadronMomentum<<G4endl;
00906 #endif 
00907     newStringEnd->Set4Momentum(theDecayParton->Get4Momentum()-*HadronMomentum);
00908     Hadron->Set4Momentum(*HadronMomentum);
00909     Hadron->SetPosition(GetPosition());
00910     if(decaying == Left)
00911     {
00912       G4QParton* theFirst = thePartons[0];            // Substitute for the First Parton
00913       delete theFirst;                                // The OldParton instance is deleted
00914       thePartons[0] = newStringEnd;                   // Delete equivalent for newStringEnd
00915 #ifdef debug
00916       G4cout<<"G4QString::Splitup:  theFirstPDG="<<theFirst->GetPDGCode()<<G4endl;
00917 #endif 
00918       Ptleft  -= HadronMomentum->vect();
00919       Ptleft.setZ(0.);                                // @@ (Z is anyway ignored) M.K. (?)
00920     }
00921     else if (decaying == Right)
00922     {
00923       G4QParton* theLast = thePartons[thePartons.size()-1]; // Substitute for theLastParton
00924       delete theLast;                                 // The OldParton instance is deleted
00925       thePartons[thePartons.size()-1] = newStringEnd; // Delete equivalent for newStringEnd
00926 #ifdef debug
00927       G4cout<<"G4QString::Splitup:  theLastPDG="<<theLast->GetPDGCode()<<", nP="
00928             <<thePartons.size()<<", beg="<<thePartons[0]->GetPDGCode()<<",end="
00929             <<thePartons[thePartons.size()-1]->GetPDGCode()<<",P="<<theLast
00930             <<"="<<thePartons[thePartons.size()-1]<<G4endl;
00931 #endif 
00932       Ptright -= HadronMomentum->vect();
00933       Ptright.setZ(0.);                               // @@ (Z is anyway ignored) M.K. (?)
00934     }
00935     else
00936     {
00937       G4cerr<<"***G4QString::Splitup: wrong oldDecay="<<decaying<<G4endl;
00938       G4Exception("G4QString::Splitup","72",FatalException,"WrongDecayDirection");
00939     }
00940     Pplus  -= HadronMomentum->e() + HadronMomentum->pz();// Reduce Pplus ofTheString (Left)
00941     Pminus -= HadronMomentum->e() - HadronMomentum->pz();// Reduce Pminus ofTheString(Rite)
00942 #ifdef debug
00943     G4cout<<"G4QString::Splitup:  P+="<<Pplus<<",P-="<<Pminus<<", nP="
00944           <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
00945           <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00946     G4cout<<">...>G4QString::Splitup: NewString4M="<<Get4Momentum()<<G4endl;
00947 #endif 
00948     delete HadronMomentum;
00949   }      
00950 #ifdef debug
00951   G4cout<<"G4QString::Splitup: ***Done*** H4M="<<Hadron->Get4Momentum()<<", nP="
00952           <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
00953           <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
00954 #endif 
00955   return Hadron;
00956 } // End of Splitup
00957 
00958 // QL=true for QGSM and QL=false for Lund fragmentation
00959 G4LorentzVector* G4QString::SplitEandP(G4QHadron* pHadron, G4bool QL)
00960 {
00961   G4double HadronMass = pHadron->GetMass();
00962 #ifdef debug
00963   G4cout<<"G4QString::SplitEandP: ***Called*** HMass="<<HadronMass<<G4endl;
00964 #endif 
00965   // calculate and assign hadron transverse momentum component HadronPx andHadronPy
00966   G4ThreeVector HadronPt = SampleQuarkPt() + DecayPt(); // @@ SampleQuarkPt & DecayPt once
00967   HadronPt.setZ(0.);
00968   //...  sample z to define hadron longitudinal momentum and energy
00969   //... but first check the available phase space
00970   G4double HadronMass2T = HadronMass*HadronMass + HadronPt.mag2();
00971   if (HadronMass2T >= SmoothParam*Mass2() )  return 0;  // restart!
00972   //... then compute allowed z region  z_min <= z <= z_max 
00973   G4double zMin = HadronMass2T/Mass2();
00974   G4double zMax = 1.;
00975 #ifdef debug
00976   G4cout<<"G4QString::SplitEandP: zMin="<<zMin<<", zMax"<<zMax<<G4endl;
00977 #endif 
00978   if (zMin >= zMax) return 0;  // have to start all over!  
00979   G4double z=0;
00980   if(QL) z = GetQGSMLightConeZ(zMin, zMax, theDecayParton->GetPDGCode(), pHadron,
00981                                HadronPt.x(), HadronPt.y());      
00982   else   z = GetLundLightConeZ(zMin, zMax, theDecayParton->GetPDGCode(), pHadron,
00983                                HadronPt.x(), HadronPt.y());      
00984   //... now compute hadron longitudinal momentum and energy
00985   // longitudinal hadron momentum component HadronPz
00986   G4double zl= z;
00987   if      (decaying == Left  ) zl*=Pplus;
00988   else if (decaying == Right ) zl*=Pminus;
00989   else                                                // @@ Is that possible?
00990   {
00991     G4cerr<<"***G4QString::SplitEandP: wrong DecayDirection="<<decaying<<G4endl;
00992     G4Exception("G4QString::SplitEandP:","72",FatalException,"WrongDecayDirection");
00993   }
00994   G4double HadronE = (zl + HadronMass2T/zl)/2;
00995   HadronPt.setZ( GetDecayDirection() * (zl - HadronE) );
00996   G4LorentzVector* a4Momentum= new G4LorentzVector(HadronPt,HadronE);
00997   return a4Momentum;
00998 }
00999 
01000 G4ThreeVector G4QString::SampleQuarkPt()
01001 {
01002    G4double Pt = SigmaQT * std::sqrt( -std::log(G4UniformRand()));
01003    G4double phi = twopi*G4UniformRand();
01004    return G4ThreeVector(Pt * std::cos(phi),Pt * std::sin(phi),0);
01005 }
01006 
01007 G4QHadron* G4QString::QuarkSplitup(G4QParton* decay, G4QParton* &created)// VGComplTo decay
01008 {
01009   G4int IsParticle=(decay->GetPDGCode()>0) ? -1 : +1; // a quark needs antiquark or diquark
01010   G4QPartonPair QuarkPair = CreatePartonPair(IsParticle);
01011   created = QuarkPair.GetParton2();                   // New Parton after splitting
01012 #ifdef debug
01013   G4cout<<"G4QString::QuarkSplitup: ***Called*** crP="<<created->GetPDGCode()<<G4endl;
01014 #endif
01015   G4QParton* P1=QuarkPair.GetParton1();
01016   G4QHadron* result=CreateHadron(P1, decay);         // New Hadron after splitting
01017   delete P1;                                         // Clean up the temporary parton
01018   return result; 
01019 } // End of QuarkSplitup
01020 
01021 //
01022 G4QHadron* G4QString::DiQuarkSplitup(G4QParton* decay, G4QParton* &created)
01023 {
01024   //... can Diquark break or not? 
01025   if (G4UniformRand() < DiquarkBreakProb )
01026   {
01027     //... Diquark break
01028     G4int stableQuarkEncoding = decay->GetPDGCode()/1000;
01029     G4int decayQuarkEncoding = (decay->GetPDGCode()/100)%10;
01030     if (G4UniformRand() < 0.5)
01031     {
01032       G4int Swap = stableQuarkEncoding;
01033       stableQuarkEncoding = decayQuarkEncoding;
01034       decayQuarkEncoding = Swap;
01035     }
01036     G4int IsParticle=(decayQuarkEncoding>0) ? -1 : +1;// Diquark is equivalent to antiquark
01037     G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false);  // no diquarks wanted
01038     G4QParton* P2=QuarkPair.GetParton2();
01039     G4int QuarkEncoding=P2->GetPDGCode();
01040     delete P2;
01041     G4int i10  = std::max(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
01042     G4int i20  = std::min(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
01043     G4int spin = (i10 != i20 && G4UniformRand() <= 0.5) ? 1 : 3;
01044     G4int NewDecayEncoding = -1*IsParticle*(i10 * 1000 + i20 * 100 + spin);
01045     created = new G4QParton(NewDecayEncoding);
01046 #ifdef debug
01047     G4cout<<"G4QString::DiQuarkSplitup: inside, crP="<<created->GetPDGCode()<<G4endl;
01048 #endif 
01049     G4QParton* decayQuark= new G4QParton(decayQuarkEncoding);
01050     G4QParton* P1=QuarkPair.GetParton1();
01051     G4QHadron* newH=CreateHadron(P1, decayQuark);
01052     delete P1;
01053     delete decayQuark;
01054     return newH;
01055   }
01056   else
01057   {
01058     //... Diquark does not break
01059     G4int IsParticle=(decay->GetPDGCode()>0) ? +1 : -1; 
01060     G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false);  // no diquarks wanted
01061     created = QuarkPair.GetParton2();
01062 #ifdef debug
01063     G4cout<<"G4QString::DiQuarkSplitup: diQ not break, crP="<<created->GetPDGCode()<<G4endl;
01064 #endif 
01065     G4QParton* P1=QuarkPair.GetParton1();
01066     G4QHadron* newH=CreateHadron(P1, decay);
01067     delete P1;
01068     return newH;
01069  }
01070 } // End of DiQuarkSplitup
01071 
01072 G4QPartonPair G4QString::CreatePartonPair(G4int NeedParticle, G4bool AllowDiquarks)
01073 {
01074 #ifdef debug
01075                 G4cout<<"G4QString::CreatePartonPair: ***Called***, P="<<NeedParticle<<", ALLOWdQ="
01076         <<AllowDiquarks<<G4endl;
01077 #endif 
01078   //  NeedParticle = {+1 for Particle, -1 for AntiParticle}
01079   if(AllowDiquarks && G4UniformRand() < DiquarkSuppress)
01080   {
01081     // Create a Diquark - AntiDiquark pair , first in pair is anti to IsParticle
01082     G4int q1  = SampleQuarkFlavor();
01083     G4int q2  = SampleQuarkFlavor();
01084     G4int spin = (q1 != q2 && G4UniformRand() <= 0.5) ? 1 : 3; // @@ 0.5 M.K.?
01085     // Convention: quark with higher PDG number is first
01086     G4int PDGcode = (std::max(q1,q2) * 1000 + std::min(q1,q2) * 100 + spin) * NeedParticle;
01087 #ifdef debug
01088                   G4cout<<"G4QString::CreatePartonPair: Created dQ-AdQ, PDG="<<PDGcode<<G4endl;
01089 #endif 
01090     return G4QPartonPair(new G4QParton(-PDGcode), new G4QParton(PDGcode));
01091   }
01092   else
01093   {
01094     // Create a Quark - AntiQuark pair, first in pair is a Particle
01095     G4int PDGcode=SampleQuarkFlavor()*NeedParticle;
01096 #ifdef debug
01097                 G4cout<<"G4QString::CreatePartonPair: Created Q-aQ, PDG="<<PDGcode<<G4endl;
01098 #endif 
01099     return G4QPartonPair(new G4QParton(PDGcode), new G4QParton(-PDGcode));
01100   }
01101 } // End of CreatePartonPair
01102 
01103 // Creation of the Meson out of two partons (q, anti-q) 
01104 G4QHadron* G4QString::CreateMeson(G4QParton* black, G4QParton* white, Spin theSpin)
01105 {
01106   static G4double scalarMesonMixings[6]={0.5, 0.25, 0.5, 0.25, 1.0, 0.5}; 
01107   static G4double vectorMesonMixings[6]={0.5, 0.0, 0.5, 0.0, 1.0, 1.0};
01108   G4int id1= black->GetPDGCode();
01109   G4int id2= white->GetPDGCode();
01110 #ifdef debug
01111   G4cout<<"G4QString::CreateMeson: bT="<<black->GetType()<<"("<<id1<<"), wT="
01112         <<white->GetType()<<"("<<id2<<")"<<G4endl;
01113 #endif 
01114   if (std::abs(id1) < std::abs(id2))     // exchange black and white
01115   {
01116     G4int xchg = id1; 
01117     id1 = id2;  
01118     id2 = xchg;
01119   }
01120   if(std::abs(id1)>3) 
01121   {
01122     G4cerr<<"***G4QString::CreateMeson: q1="<<id1<<", q2="<<id2
01123           <<" while CHIPS is only SU(3)"<<G4endl;
01124     G4Exception("G4QString::CreateMeson:","72",FatalException,"HeavyQuarkFound");
01125   } 
01126   G4int PDGEncoding=0;
01127   if(!(id1+id2))                      // annihilation case (neutral)
01128   {     
01129     G4double rmix = G4UniformRand();
01130     G4int    imix = 2*std::abs(id1) - 1;
01131     if(theSpin == SpinZero)
01132        PDGEncoding = 110*(1 + G4int(rmix + scalarMesonMixings[imix - 1])
01133                             + G4int(rmix + scalarMesonMixings[imix]    ) ) +  theSpin;
01134     else
01135        PDGEncoding = 110*(1 + G4int(rmix + vectorMesonMixings[imix - 1])
01136                             + G4int(rmix + vectorMesonMixings[imix]    ) ) +  theSpin;
01137   }
01138   else
01139   {
01140     PDGEncoding = 100 * std::abs(id1) + 10 * std::abs(id2) +  theSpin;  
01141     G4bool IsUp = (std::abs(id1)&1) == 0; // quark 1 is up type quark (u or c?)
01142     G4bool IsAnti = id1 < 0;              // quark 1 is an antiquark?
01143     if( (IsUp && IsAnti) || (!IsUp && !IsAnti) )  PDGEncoding = - PDGEncoding;
01144     // Correction for the true neutral mesons
01145     if( PDGEncoding == -111 || PDGEncoding == -113 || PDGEncoding == -223 || 
01146         PDGEncoding == -221 || PDGEncoding == -331 || PDGEncoding == -333 )
01147                                                                PDGEncoding = - PDGEncoding;
01148   }
01149   G4QHadron* Meson= new G4QHadron(PDGEncoding);
01150 #ifdef debug
01151   G4cout<<"G4QString::CreateBaryon: Meson is created with PDG="<<PDGEncoding<<G4endl;
01152 #endif
01153   //delete black;                          // It is better to delete here and consider  
01154   //delete white;                          // the hadron creation as a delete equivalent
01155   return Meson;
01156 }
01157 
01158 // Creation of the Baryon out of two partons (q, di-q), (anti-q, anti-di-q) 
01159 G4QHadron* G4QString::CreateBaryon(G4QParton* black, G4QParton* white, Spin theSpin)
01160 {
01161   G4int id1= black->GetPDGCode();
01162   G4int id2= white->GetPDGCode();
01163 #ifdef debug
01164   G4cout<<"G4QString::CreateBaryon: bT="<<black->GetType()<<"("<<id1<<"), wT="
01165         <<white->GetType()<<"("<<id2<<")"<<G4endl;
01166 #endif 
01167   if(std::abs(id1) < std::abs(id2))
01168   {
01169     G4int xchg = id1; 
01170     id1 = id2;  
01171     id2 = xchg;
01172   }
01173   if(std::abs(id1)<1000 || std::abs(id2)> 3) 
01174   {
01175     G4cerr<<"***G4QString::CreateBaryon: q1="<<id1<<", q2="<<id2
01176           <<" can't create a Baryon"<<G4endl;
01177     G4Exception("G4QString::CreateBaryon:","72",FatalException,"WrongQdQSequence");
01178   }
01179   G4int ifl1= std::abs(id1)/1000;
01180   G4int ifl2 = (std::abs(id1) - ifl1 * 1000)/100;
01181   G4int diquarkSpin = std::abs(id1)%10; 
01182   G4int ifl3 = id2;
01183   if (id1 < 0) {ifl1 = - ifl1; ifl2 = - ifl2;}
01184   //... Construct baryon, distinguish Lambda and Sigma baryons.
01185   G4int kfla = std::abs(ifl1);
01186   G4int kflb = std::abs(ifl2);
01187   G4int kflc = std::abs(ifl3);
01188   G4int kfld = std::max(kfla,kflb);
01189         kfld = std::max(kfld,kflc);
01190   G4int kflf = std::min(kfla,kflb);
01191         kflf = std::min(kflf,kflc);
01192   G4int kfle = kfla + kflb + kflc - kfld - kflf;
01193   //... baryon with content uuu or ddd or sss has always spin = 3/2
01194   if(kfla==kflb && kflb==kflc) theSpin=SpinThreeHalf;   
01195 
01196   G4int kfll = 0;
01197   if(theSpin == SpinHalf && kfld > kfle && kfle > kflf)
01198   { 
01199     // Spin J=1/2 and all three quarks different
01200     // Two states exist: (uds -> lambda or sigma0)
01201     //   -  lambda: s(ud)0 s : 3122; ie. reverse the two lighter quarks
01202     //   -  sigma0: s(ud)1 s : 3212
01203     if(diquarkSpin == 1 )
01204     {
01205        if ( kfla == kfld) kfll = 1; // heaviest quark in diquark
01206        else kfll = G4int(0.25 + G4UniformRand());
01207     }   
01208     if(diquarkSpin==3 && kfla!=kfld) kfll = G4int(0.75+G4UniformRand());
01209   }
01210   G4int PDGEncoding=0;
01211   if (kfll == 1) PDGEncoding = 1000 * kfld + 100 * kflf + 10 * kfle + theSpin;
01212   else           PDGEncoding = 1000 * kfld + 100 * kfle + 10 * kflf + theSpin;
01213   if (id1 < 0) PDGEncoding = -PDGEncoding;
01214   G4QHadron* Baryon= new G4QHadron(PDGEncoding);
01215 #ifdef debug
01216   G4cout<<"G4QString::CreateBaryon: Baryon is created with PDG="<<PDGEncoding<<G4endl;
01217 #endif 
01218   //delete black;                          // It is better to delete here and consider  
01219   //delete white;                          // the hadron creation as a delete equivalent
01220   return Baryon;
01221 } // End of CreateBaryon
01222 
01223 G4QHadron* G4QString::CreateHadron(G4QParton* black, G4QParton* white)
01224 {
01225   //static G4double mesonLowSpin = 0.25;      // probability to create scalar meson (2s+1) 
01226   //static G4double baryonLowSpin= 1./3.;     // probability to create 1/2 baryon  (2s+1)
01227   static G4double mesonLowSpin = 0.5;      // probability to create scalar meson (spFlip)
01228   static G4double baryonLowSpin= 0.5;      // probability to create 1/2 baryon (spinFlip)
01229   G4int bT=black->GetType();
01230   G4int wT=white->GetType();
01231 #ifdef debug
01232   G4cout<<"G4QString::CreateHadron: bT="<<bT<<"("<<black->GetPDGCode()<<"), wT="<<wT<<"("
01233         <<white->GetPDGCode()<<")"<<G4endl;
01234 #endif 
01235   if(bT==2 || wT==2)
01236   {
01237     // Baryon consists of quark and at least one di-quark
01238     Spin spin = (G4UniformRand() < baryonLowSpin) ? SpinHalf : SpinThreeHalf;
01239 #ifdef debug
01240     G4cout<<"G4QString::CreateHadron: ----> Baryon is under creation"<<G4endl;
01241 #endif 
01242     return CreateBaryon(black, white, spin);
01243   }
01244   else
01245   { 
01246     // Meson consists of quark and abnti-quark
01247     Spin spin = (G4UniformRand() < mesonLowSpin) ? SpinZero : SpinOne;
01248 #ifdef debug
01249     G4cout<<"G4QString::CreateHadron: ----> Meson is under creation"<<G4endl;
01250 #endif 
01251     return CreateMeson(black, white, spin);
01252   }
01253 } // End of Create Hadron
01254 
01255 // Creation of only High Spin (2,3/2) hadrons
01256 G4QHadron* G4QString::CreateLowSpinHadron(G4QParton* black, G4QParton* white)
01257 {
01258   G4int bT=black->GetType();
01259   G4int wT=white->GetType();
01260 #ifdef debug
01261   G4cout<<"G4QString::CreateLowSpinHadron: ***Called***, bT="<<bT<<"("<<black->GetPDGCode()
01262         <<"), wT="<<wT<<"("<<white->GetPDGCode()<<")"<<G4endl;
01263 #endif 
01264   if(bT == 1 && wT == 1)
01265   {
01266 #ifdef debug
01267     G4cout<<"G4QString::CreateLowSpinHadron: ----> Meson is under creation"<<G4endl;
01268 #endif 
01269     return CreateMeson(black, white, SpinZero);
01270   }
01271   else                  // returns a SpinThreeHalf Baryon if all quarks are the same
01272   {
01273 #ifdef debug
01274     G4cout<<"G4QString::CreateLowSpinHadron: ----> Baryon is under creation"<<G4endl;
01275 #endif 
01276     return CreateBaryon(black, white, SpinHalf);
01277   }
01278 } // End of CreateLowSpinHadron
01279 
01280 // Creation of only High Spin (2,3/2) hadrons
01281 G4QHadron* G4QString::CreateHighSpinHadron(G4QParton* black, G4QParton* white)
01282 {
01283   G4int bT=black->GetType();
01284   G4int wT=white->GetType();
01285 #ifdef debug
01286   G4cout<<"G4QString::CreateHighSpinHadron:***Called***, bT="<<bT<<"("<<black->GetPDGCode()
01287         <<"), wT="<<wT<<"("<<white->GetPDGCode()<<")"<<G4endl;
01288 #endif 
01289   if(bT == 1 && wT == 1)
01290   {
01291 #ifdef debug
01292     G4cout<<"G4QString::CreateHighSpinHadron: ----> Meson is created"<<G4endl;
01293 #endif 
01294     return CreateMeson(black,white, SpinOne);
01295   }
01296   else
01297   {
01298 #ifdef debug
01299     G4cout<<"G4QString::CreateHighSpinHadron: ----> Baryon is created"<<G4endl;
01300 #endif 
01301     return CreateBaryon(black,white,SpinThreeHalf);
01302   }
01303 } // End of CreateHighSpinHadron

Generated on Mon May 27 17:49:39 2013 for Geant4 by  doxygen 1.4.7