Ignore:
Timestamp:
Apr 6, 2009, 12:30:29 PM (17 years ago)
Author:
garnier
Message:

update processes

Location:
trunk/source/processes/hadronic/models/rpg
Files:
60 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/processes/hadronic/models/rpg/History

    r819 r962  
    1414   * Please list in reverse chronological order (last date on top)
    1515   ---------------------------------------------------------------
     16
     17 9 June 2008 - Dennis Wright (hadr-rpg-V09-01-03)
     18-------------------------------------------------
     19Remove unused variable ekIncident in G4RPGFragmentation.cc and
     20G4RPGTwoCluster.cc
     21
     22 5 May 2008 - Dennis Wright (hadr-rpg-V09-01-02)
     23------------------------------------------------
     24Fixed gcc-4.3 compiler warnings for unused variables in
     25G4RPGNeutronInelastic.hh, cc
     26G4RPGPiMinusInelastic.hh, cc
     27G4RPGPiPlusInelastic.hh, cc
     28G4RPGProtonInelastic.hh, cc
     29G4RPGReaction.hh, cc
     30G4RPGFragmentation.cc
     31G4RPGTwoBody.cc
     32G4RPGTwoCluster.cc
     33
     3421 March 2008 - Dennis Wright (hadr-rpg-V09-01-01)
     35--------------------------------------------------
     36Fixed gcc-4.3 compiler warning in G4RPGInelastic.cc
     37
     3821 February 2008 - Dennis Wright (hadr-rpg-V09-01-00)
     39-----------------------------------------------------
     40G4RPGInelastic: remove Rotate method, fix K0 ID problem
     41G4RPGFragmentation: fix energy non-conservation
     42G4RPGReaction.cc: add GenerateNBodyEventT method, fix energy non-conservation
     43                  in AddBlackTrackParticles
     44G4RPGProtonInelastic.cc, G4RPGNeutronInelastic.cc, G4RPGPiPlusInelastic.cc,
     45  G4RPGPiMinusInelastic.cc: remove quasi-elastic flag, remove MeV units
     46
    1647
    17485 December 2007 - Dennis Wright (hadr-rpg-V09-00-02)
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiKZeroInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiKZeroInelastic.hh,v 1.1 2007/07/18 20:51:36 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiLambdaInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiLambdaInelastic.hh,v 1.1 2007/07/18 20:51:36 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiNeutronInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiNeutronInelastic.hh,v 1.1 2007/07/18 20:51:36 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiOmegaMinusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiOmegaMinusInelastic.hh,v 1.1 2007/07/18 20:51:36 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiProtonInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiProtonInelastic.hh,v 1.1 2007/07/18 20:51:36 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiSigmaMinusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiSigmaMinusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiSigmaPlusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiSigmaPlusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiXiMinusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiXiMinusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGAntiXiZeroInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiXiZeroInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929//
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGFragmentation.hh

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGFragmentation.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGFragmentation.hh,v 1.2 2008/02/22 22:02:13 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D.H. Wright
     
    7373 private:
    7474
     75   void
     76   ReduceEnergiesOfSecondaries(G4int /*startingIndex*/,
     77                               G4double& /*forwardKinetic*/,
     78                               G4double& /*backwardKinetic*/,
     79                               G4FastVector<G4ReactionProduct,256>& /*vec*/,
     80                               G4int& /*vecLen*/,
     81                               G4ReactionProduct& /*forwardPseudoParticle*/,
     82                               G4ReactionProduct& /*backwardPseudoParticle*/,
     83                               G4double& /*pt*/);
     84
    7585   G4double dndl[20];   
    7686 };
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGInelastic.hh

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGInelastic.hh,v 1.3 2008/02/22 22:17:25 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
     
    3939
    4040#include "globals.hh"
     41#include <vector>
    4142#include "G4FastVector.hh"
    4243#include "G4HadronicInteraction.hh"
     
    7677                   G4int &vecLen);
    7778   
    78    void Rotate(G4FastVector<G4ReactionProduct,256> &vec, G4int &vecLen);
     79   //   void Rotate(G4FastVector<G4ReactionProduct,256> &vec, G4int &vecLen);
    7980
    8081   void GetNormalizationConstant(const G4double availableEnergy,
     
    110111   G4RPGTwoBody twoBody;
    111112
     113   std::pair<G4int, G4double> interpolateEnergy(G4double ke) const;
     114
     115   G4int sampleFlat(std::vector<G4double> sigma) const;
     116
     117   void CheckQnums(G4FastVector<G4ReactionProduct,256> &vec,
     118                   G4int &vecLen,
     119                   G4ReactionProduct &currentParticle,
     120                   G4ReactionProduct &targetParticle,
     121                   G4double Q, G4double B, G4double S);
     122
     123   enum {pi0, pip, pim, kp, km, k0, k0b, pro, neu,
     124         lam, sp, s0, sm, xi0, xim, om, ap, an};
     125
     126   static G4ParticleDefinition* particleDef[18];
     127
    112128 private:
    113129   
     
    115131   G4ThreeVector what;
    116132
     133   static const G4double energyScale[30];
     134
    117135 };
    118136 
    119137#endif
    120  
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGKLongInelastic.hh

    r819 r962  
    2626//
    2727// $Id: G4RPGKLongInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    28 // GEANT4 tag $Name: $
     28// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2929//
    3030// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGKMinusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGKMinusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGKPlusInelastic.hh

    r819 r962  
    2626//
    2727// $Id: G4RPGKPlusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    28 // GEANT4 tag $Name: $
     28// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2929//
    3030// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGKShortInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGKShortInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGKZeroInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGKZeroInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGLambdaInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGLambdaInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGNeutronInelastic.hh

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGNeutronInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGNeutronInelastic.hh,v 1.3 2008/05/05 21:21:54 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
    30 // Date:   18 June 2007
     30// Date:   28 December 2007
    3131//
    3232
    3333// Class Description:
    34 //
    3534// Final state production model for neutron inelastic scattering
    36 // using the re-parameterized Gheisha model.
     35// using the re-parameterized Gheisha model
    3736 
    3837#ifndef G4RPGNeutronInelastic_h
     
    4039 
    4140
    42 #include "G4RPGInelastic.hh"
     41#include "G4RPGNucleonInelastic.hh"
    4342
    4443 
    45  class G4RPGNeutronInelastic : public G4RPGInelastic
     44 class G4RPGNeutronInelastic : public G4RPGNucleonInelastic
    4645 {
    47  public:  // with description
     46 public:
    4847   
    49    G4RPGNeutronInelastic() : G4RPGInelastic("G4RPGNeutronInelastic")
    50    {
    51      SetMinEnergy(0.0);
    52      SetMaxEnergy(35.*GeV);
    53    }
     48   G4RPGNeutronInelastic() : G4RPGNucleonInelastic("RPGNeutronInelastic")
     49   {}
    5450   
    5551   ~G4RPGNeutronInelastic()
    56    { }
     52   {}
    5753   
    5854   G4HadFinalState* ApplyYourself(const G4HadProjectile& aTrack,
     
    6056   
    6157 private:
    62    
    63    void Cascade(
    64      G4FastVector<G4ReactionProduct,GHADLISTSIZE> &vec,
     58
     59   void InitialCollision(
     60     G4FastVector<G4ReactionProduct,256>& vec,
    6561     G4int& vecLen,
    66      const G4HadProjectile* originalIncident,
    6762     G4ReactionProduct& currentParticle,
    6863     G4ReactionProduct& targetParticle,
    69      G4bool& incidentHasChanged,
    70      G4bool& targetHasChanged,
    71      G4bool& quasiElastic);
     64     G4bool& incidentHasChanged,
     65     G4bool& targetHasChanged);
    7266   
    7367   void SlowNeutron(
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGOmegaMinusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGOmegaMinusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGPiMinusInelastic.hh

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGPiMinusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGPiMinusInelastic.hh,v 1.3 2008/05/05 21:21:54 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    29 // Author: D.H. Wright
    30 // Date:   26 May 2007
     29// Author: D. H. Wright
     30// Date:   23 November 2007
    3131//
    32  
     32
    3333#ifndef G4RPGPiMinusInelastic_h
    3434#define G4RPGPiMinusInelastic_h 1
    3535 
    36 // Class Description
     36// Class Description:
    3737// Final state production model for pi- inelastic scattering
    38 // using the re-parameterized Gheisha model.
     38// using the re-parameterized Gheisha model
    3939
    40 #include "G4RPGInelastic.hh"
     40#include "G4RPGPionInelastic.hh"
    4141 
    42  class G4RPGPiMinusInelastic : public G4RPGInelastic
     42 class G4RPGPiMinusInelastic : public G4RPGPionInelastic
    4343 {
    4444 public:
    4545   
    46     G4RPGPiMinusInelastic() : G4RPGInelastic("G4RPGPiMinusInelastic")
    47     {
    48       SetMinEnergy( 0.0 );
    49       SetMaxEnergy( 55.*GeV );
    50     }
     46   G4RPGPiMinusInelastic() : G4RPGPionInelastic("RPGPiMinusInelastic")
     47   {}
    5148   
    52     ~G4RPGPiMinusInelastic() { }
     49   ~G4RPGPiMinusInelastic()
     50   {}
    5351   
    54     G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack,
    55                                       G4Nucleus &targetNucleus );
     52   G4HadFinalState* ApplyYourself(const G4HadProjectile& aTrack,
     53                                        G4Nucleus& targetNucleus);
    5654   
    5755 private:
    5856   
    59     void Cascade(                               // derived from CASPIM
    60       G4FastVector<G4ReactionProduct,256> &vec,
    61       G4int &vecLen,
    62       const G4HadProjectile *originalIncident,
    63       G4ReactionProduct &currentParticle,
    64       G4ReactionProduct &targetParticle,
    65       G4bool &incidentHasChanged,
    66       G4bool &targetHasChanged,
    67       G4bool &quasiElastic );
    68    
     57   void InitialCollision(
     58     G4FastVector<G4ReactionProduct,256>& vec,
     59     G4int& vecLen,
     60     G4ReactionProduct& currentParticle,
     61     G4ReactionProduct& targetParticle,
     62     G4bool& incidentHasChanged,
     63     G4bool& targetHasChanged);
     64
    6965 };
    70  
    7166#endif
    7267 
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGPiPlusInelastic.hh

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGPiPlusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGPiPlusInelastic.hh,v 1.3 2008/05/05 21:21:54 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
     
    3838// using the re-parameterized Gheisha model
    3939
    40 #include "G4RPGInelastic.hh"
     40#include "G4RPGPionInelastic.hh"
    4141 
    42  class G4RPGPiPlusInelastic : public G4RPGInelastic
     42 class G4RPGPiPlusInelastic : public G4RPGPionInelastic
    4343 {
    4444 public:
    4545   
    46     G4RPGPiPlusInelastic() : G4RPGInelastic("G4RPGPiPlusInelastic")
    47     {
    48       SetMinEnergy( 0.0 );
    49       SetMaxEnergy( 55.*GeV );
    50     }
     46   G4RPGPiPlusInelastic() : G4RPGPionInelastic("RPGPiPlusInelastic")
     47   {}
    5148   
    52     ~G4RPGPiPlusInelastic() { }
     49   ~G4RPGPiPlusInelastic()
     50   {}
    5351   
    54     G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack,
    55                                       G4Nucleus &targetNucleus );
     52   G4HadFinalState* ApplyYourself(const G4HadProjectile& aTrack,
     53                                        G4Nucleus& targetNucleus);
    5654   
    5755 private:
    5856   
    59     void Cascade(                               // derived from CASPIP
    60       G4FastVector<G4ReactionProduct,256> &vec,
    61       G4int &vecLen,
    62       const G4HadProjectile *originalIncident,
    63       G4ReactionProduct &currentParticle,
    64       G4ReactionProduct &targetParticle,
    65       G4bool &incidentHasChanged,
    66       G4bool &targetHasChanged,
    67       G4bool &quasiElastic );
    68    
     57   void InitialCollision(
     58     G4FastVector<G4ReactionProduct,256>& vec,
     59     G4int& vecLen,
     60     G4ReactionProduct& currentParticle,
     61     G4ReactionProduct& targetParticle,
     62     G4bool& incidentHasChanged,
     63     G4bool& targetHasChanged);
     64
    6965 };
    7066#endif
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGPionSuppression.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGPionSuppression.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D.H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGProtonInelastic.hh

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGProtonInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGProtonInelastic.hh,v 1.3 2008/05/05 21:21:54 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
    30 // Date:   26 May 2007
     30// Date:   28 December 2007
    3131//
    3232
    3333// Class Description:
    34 //
    3534// Final state production model for proton inelastic scattering
    36 // using the re-parameterized Gheisha model.
     35// using the re-parameterized Gheisha model
    3736
    3837#ifndef G4RPGProtonInelastic_h
     
    4039 
    4140
    42 #include "G4RPGInelastic.hh"
     41#include "G4RPGNucleonInelastic.hh"
    4342
    4443 
    45  class G4RPGProtonInelastic : public G4RPGInelastic
     44 class G4RPGProtonInelastic : public G4RPGNucleonInelastic
    4645 {
    47  public:  // with description
     46 public:
    4847   
    49    G4RPGProtonInelastic() : G4RPGInelastic("G4RPGProtonInelastic")
    50    {
    51      SetMinEnergy(0.0);
    52      SetMaxEnergy(35.*GeV);
    53    }
     48   G4RPGProtonInelastic() : G4RPGNucleonInelastic("RPGProtonInelastic")
     49   {}
    5450   
    5551   ~G4RPGProtonInelastic()
    56    { }
     52   {}
    5753   
    58    G4HadFinalState * ApplyYourself(const G4HadProjectile& aTrack,
    59                                    G4Nucleus& targetNucleus);
     54   G4HadFinalState* ApplyYourself(const G4HadProjectile& aTrack,
     55                                  G4Nucleus& targetNucleus);
    6056
    6157 private:
    6258   
    63    void Cascade(G4FastVector<G4ReactionProduct,GHADLISTSIZE> &vec,
    64                 G4int& vecLen,
    65                 const G4HadProjectile* originalIncident,
    66                 G4ReactionProduct& currentParticle,
    67                 G4ReactionProduct& targetParticle,
    68                 G4bool& incidentHasChanged,
    69                 G4bool& targetHasChanged,
    70                 G4bool& quasiElastic);
     59   void InitialCollision(
     60     G4FastVector<G4ReactionProduct,256>& vec,
     61     G4int& vecLen,
     62     G4ReactionProduct& currentParticle,
     63     G4ReactionProduct& targetParticle,
     64     G4bool& incidentHasChanged,
     65     G4bool& targetHasChanged);
    7166
    7267   void SlowProton(const G4HadProjectile* originalIncident,
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGReaction.hh

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGReaction.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGReaction.hh,v 1.3 2008/05/05 21:21:54 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
     
    7272                              const G4double /*edta*/,
    7373                              const G4int /*ndta*/,
    74                               const G4double /*sprob*/,
    75                               const G4double /*kineticMinimum*/,
    76                               const G4double /*kineticFactor*/,
    7774                              const G4ReactionProduct& /*modifiedOriginal*/,
    7875                              G4int /*PinNucleus*/,
     
    8784                              G4FastVector<G4ReactionProduct,256> &vec,
    8885                              G4int& vecLen);
     86   
     87  G4double GenerateNBodyEventT(const G4double totalEnergy,
     88                               const G4bool constantCrossSection,
     89                               std::vector<G4ReactionProduct*>& list);
    8990   
    9091  void NuclearReaction(G4FastVector<G4ReactionProduct,4> &vec,
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGSigmaMinusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGSigmaMinusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGSigmaPlusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGSigmaPlusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGStrangeProduction.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGStrangeProduction.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D.H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGTwoBody.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGTwoBody.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D.H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGTwoCluster.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGTwoCluster.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D.H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGXiMinusInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGXiMinusInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929// Author: D. H. Wright
  • trunk/source/processes/hadronic/models/rpg/include/G4RPGXiZeroInelastic.hh

    r819 r962  
    2525//
    2626// $Id: G4RPGXiZeroInelastic.hh,v 1.1 2007/07/18 20:51:37 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929//
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiKZeroInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiKZeroInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiLambdaInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiLambdaInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiNeutronInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiNeutronInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiOmegaMinusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiOmegaMinusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929//
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiProtonInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiProtonInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiSigmaMinusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiSigmaMinusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiSigmaPlusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiSigmaPlusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiXiMinusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiXiMinusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929//
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGAntiXiZeroInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGAntiXiZeroInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929//
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGFragmentation.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGFragmentation.cc,v 1.3 2007/12/06 01:13:14 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGFragmentation.cc,v 1.6 2008/06/09 18:13:16 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
     
    7676{
    7777  //
    78   // Derived from H. Fesefeldt's original FORTRAN code GENXPT
     78  // Based on H. Fesefeldt's original FORTRAN code GENXPT
    7979  //
    8080  // Generation of x- and pT- values for incident, target, and all secondary
     
    8989  // two-body scattering
    9090  //
    91     if(vecLen == 0) return false;
    92 
    93     G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
    94     G4ParticleDefinition *aProton = G4Proton::Proton();
    95     G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
    96     G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
    97     G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
    98 
    99     G4int i, l;
    100     G4bool veryForward = false;
    101    
    102     const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/GeV;
    103     const G4double etOriginal = modifiedOriginal.GetTotalEnergy()/GeV;
    104     const G4double mOriginal = modifiedOriginal.GetMass()/GeV;
    105     const G4double pOriginal = modifiedOriginal.GetMomentum().mag()/GeV;
    106     G4double targetMass = targetParticle.GetDefinition()->GetPDGMass()/GeV;
    107     G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
    108                                         targetMass*targetMass +
    109                                         2.0*targetMass*etOriginal );  // GeV
    110     G4double currentMass = currentParticle.GetMass()/GeV;
     91  if (vecLen == 0) return false;
     92
     93  G4ParticleDefinition* aPiMinus = G4PionMinus::PionMinus();
     94  G4ParticleDefinition* aProton = G4Proton::Proton();
     95  G4ParticleDefinition* aNeutron = G4Neutron::Neutron();
     96  G4ParticleDefinition* aPiPlus = G4PionPlus::PionPlus();
     97  G4ParticleDefinition* aPiZero = G4PionZero::PionZero();
     98
     99  G4int i, l;
     100  G4bool veryForward = false;
     101   
     102  const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/GeV;
     103  const G4double etOriginal = modifiedOriginal.GetTotalEnergy()/GeV;
     104  const G4double mOriginal = modifiedOriginal.GetMass()/GeV;
     105  const G4double pOriginal = modifiedOriginal.GetMomentum().mag()/GeV;
     106  G4double targetMass = targetParticle.GetDefinition()->GetPDGMass()/GeV;
     107  G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
     108                                      targetMass*targetMass +
     109                                      2.0*targetMass*etOriginal );  // GeV
     110  G4double currentMass = currentParticle.GetMass()/GeV;
     111  targetMass = targetParticle.GetMass()/GeV;
     112
     113  // Randomize the order of the secondary particles.
     114  // Note that the current and target particles are not affected.
     115
     116  for (i=0; i<vecLen; ++i) {
     117    G4int itemp = G4int( G4UniformRand()*vecLen );
     118    G4ReactionProduct pTemp = *vec[itemp];
     119    *vec[itemp] = *vec[i];
     120    *vec[i] = pTemp;
     121  }
     122
     123  if (currentMass == 0.0 && targetMass == 0.0) {
     124    // Target and projectile have annihilated.  Replace them with the first
     125    // two secondaries in the list.  Current particle KE is maintained.
     126 
     127    G4double ek = currentParticle.GetKineticEnergy();
     128    G4ThreeVector m = currentParticle.GetMomentum();
     129    currentParticle = *vec[0];
     130    currentParticle.SetSide(1);
     131    targetParticle = *vec[1];
     132    targetParticle.SetSide(-1);
     133    for( i=0; i<(vecLen-2); ++i )*vec[i] = *vec[i+2];
     134    G4ReactionProduct *temp = vec[vecLen-1];
     135    delete temp;
     136    temp = vec[vecLen-2];
     137    delete temp;
     138    vecLen -= 2;
     139    currentMass = currentParticle.GetMass()/GeV;
    111140    targetMass = targetParticle.GetMass()/GeV;
     141    incidentHasChanged = true;
     142    targetHasChanged = true;
     143    currentParticle.SetKineticEnergy( ek );
     144    currentParticle.SetMomentum( m );
     145    veryForward = true;
     146  }
     147  const G4double atomicWeight = targetNucleus.GetN();
     148  const G4double atomicNumber = targetNucleus.GetZ();
     149  const G4double protonMass = aProton->GetPDGMass();
     150
     151  if (originalIncident->GetDefinition()->GetParticleSubType() == "kaon"
     152      && G4UniformRand() >= 0.7) {
     153    G4ReactionProduct temp = currentParticle;
     154    currentParticle = targetParticle;
     155    targetParticle = temp;
     156    incidentHasChanged = true;
     157    targetHasChanged = true;
     158    currentMass = currentParticle.GetMass()/GeV;
     159    targetMass = targetParticle.GetMass()/GeV;
     160  }
     161  const G4double afc = std::min( 0.75,
     162        0.312+0.200*std::log(std::log(centerofmassEnergy*centerofmassEnergy))+
     163        std::pow(centerofmassEnergy*centerofmassEnergy,1.5)/6000.0 );
     164   
     165  G4double freeEnergy = centerofmassEnergy-currentMass-targetMass;
     166  G4double forwardEnergy = freeEnergy/2.;
     167  G4int forwardCount = 1;         // number of particles in forward hemisphere
     168   
     169  G4double backwardEnergy = freeEnergy/2.;
     170  G4int backwardCount = 1;        // number of particles in backward hemisphere
     171
     172  if(veryForward) {
     173    if(currentParticle.GetSide()==-1)
     174    {
     175      forwardEnergy += currentMass;
     176      forwardCount --;
     177      backwardEnergy -= currentMass;
     178      backwardCount ++;
     179    }
     180    if(targetParticle.GetSide()!=-1)
     181    {
     182      backwardEnergy += targetMass;
     183      backwardCount --;
     184      forwardEnergy -= targetMass;
     185      forwardCount ++;
     186    }
     187  }
     188
     189  for (i=0; i<vecLen; ++i) {
     190    if( vec[i]->GetSide() == -1 )
     191    {
     192      ++backwardCount;
     193      backwardEnergy -= vec[i]->GetMass()/GeV;
     194    } else {
     195      ++forwardCount;
     196      forwardEnergy -= vec[i]->GetMass()/GeV;
     197    }
     198  }
     199
     200  // Check that sum of forward particle masses does not exceed forwardEnergy,
     201  // and similarly for backward particles.  If so, move particles from one
     202  // hemisphere to another.
     203
     204  if (backwardEnergy < 0.0) {
     205    for (i = 0; i < vecLen; ++i) {
     206      if (vec[i]->GetSide() == -1) {
     207        backwardEnergy += vec[i]->GetMass()/GeV;
     208        --backwardCount;
     209        vec[i]->SetSide(1);
     210        forwardEnergy -= vec[i]->GetMass()/GeV;
     211        ++forwardCount;
     212        if (backwardEnergy > 0.0) break;
     213      }
     214    }
     215  }
     216
     217  if (forwardEnergy < 0.0) {
     218    for (i = 0; i < vecLen; ++i) {
     219      if (vec[i]->GetSide() == 1) {
     220        forwardEnergy += vec[i]->GetMass()/GeV;
     221        --forwardCount;
     222        vec[i]->SetSide(-1);
     223        backwardEnergy -= vec[i]->GetMass()/GeV;
     224        ++backwardCount;
     225        if (forwardEnergy > 0.0) break;
     226      }
     227    }
     228  }
     229 
     230  // Special cases for reactions near threshold
     231
     232  // 1. There is only one secondary
     233  if (forwardEnergy > 0.0 && backwardEnergy < 0.0) {
     234    forwardEnergy += backwardEnergy;
     235    backwardEnergy = 0;
     236  }
     237
     238  // 2. Nuclear binding energy is large
     239  if (forwardEnergy + backwardEnergy < 0.0) return false;
     240
     241
     242  // forwardEnergy now represents the total energy in the forward reaction
     243  // hemisphere which is available for kinetic energy and particle creation.
     244  // Similarly for backwardEnergy.
     245
     246  // Add particles from the intranuclear cascade.
     247  // nuclearExcitationCount = number of new secondaries produced by nuclear
     248  // excitation
     249  // extraCount = number of nucleons within these new secondaries
     250  //
     251  // Note: eventually have to make sure that enough nucleons are available
     252  // in the case of small target nuclei
     253
     254  G4double xtarg;
     255  if( centerofmassEnergy < (2.0+G4UniformRand()) )
     256    xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount+vecLen+2)/2.0;
     257  else
     258    xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount);
     259  if( xtarg <= 0.0 )xtarg = 0.01;
     260  G4int nuclearExcitationCount = G4Poisson( xtarg );
     261  // To do: try reducing nuclearExcitationCount with increasing energy
     262  //        to simulate cut-off of cascade
     263  if(atomicWeight<1.0001) nuclearExcitationCount = 0;
     264  G4int extraNucleonCount = 0;
     265  G4double extraNucleonMass = 0.0;
     266
     267  if (nuclearExcitationCount > 0) {
     268    const G4double nucsup[] = { 1.00, 0.7, 0.5, 0.4, 0.35, 0.3 };
     269    const G4double psup[] = { 3., 6., 20., 50., 100., 1000. };
     270    G4int momentumBin = 0;
     271    while( (momentumBin < 6) &&
     272           (modifiedOriginal.GetTotalMomentum()/GeV > psup[momentumBin]) )
     273      ++momentumBin;
     274    momentumBin = std::min( 5, momentumBin );
     275
     276    //  NOTE: in GENXPT, these new particles were given negative codes
     277    //        here I use  NewlyAdded = true  instead
    112278    //
    113     //  randomize the order of the secondary particles
    114     //  note that the current and target particles are not affected
     279
     280    for (i = 0; i < nuclearExcitationCount; ++i) {
     281      G4ReactionProduct * pVec = new G4ReactionProduct();
     282      if (G4UniformRand() < nucsup[momentumBin]) {
     283
     284        if (G4UniformRand() > 1.0-atomicNumber/atomicWeight)
     285          pVec->SetDefinition( aProton );
     286        else
     287          pVec->SetDefinition( aNeutron );
     288
     289        // nucleon comes from nucleus -
     290        // do not subtract its mass from backward energy
     291        pVec->SetSide( -2 );                // -2 means backside nucleon
     292        ++extraNucleonCount;
     293        extraNucleonMass += pVec->GetMass()/GeV;
     294        // To do: Remove chosen nucleon from target nucleus
     295        pVec->SetNewlyAdded( true );
     296        vec.SetElement( vecLen++, pVec );   
     297        ++backwardCount;
     298
     299      } else {
     300
     301        G4double ran = G4UniformRand();
     302        if( ran < 0.3181 )
     303          pVec->SetDefinition( aPiPlus );
     304        else if( ran < 0.6819 )
     305          pVec->SetDefinition( aPiZero );
     306        else
     307          pVec->SetDefinition( aPiMinus );
     308
     309        if (backwardEnergy > pVec->GetMass()/GeV) {
     310          backwardEnergy -= pVec->GetMass()/GeV;    // pion mass comes from free energy
     311          ++backwardCount;
     312          pVec->SetSide( -1 );         // backside particle, but not a nucleon
     313          pVec->SetNewlyAdded( true );
     314          vec.SetElement( vecLen++, pVec );
     315        }
     316
     317        // To do: Change proton to neutron (or vice versa) in target nucleus depending
     318        //        on pion charge
     319      }
     320    }
     321  }
     322
     323  // Define initial state vectors for Lorentz transformations
     324  // The pseudoParticles have non-standard masses, hence the "pseudo"
     325
     326  G4ReactionProduct pseudoParticle[8];
     327  for (i = 0; i < 8; ++i) pseudoParticle[i].SetZero();
     328   
     329  pseudoParticle[0].SetMass( mOriginal*GeV );
     330  pseudoParticle[0].SetMomentum( 0.0, 0.0, pOriginal*GeV );
     331  pseudoParticle[0].SetTotalEnergy(
     332   std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
     333
     334  pseudoParticle[1].SetMass(protonMass);     // this could be targetMass
     335  pseudoParticle[1].SetTotalEnergy(protonMass);
     336   
     337  pseudoParticle[3].SetMass(protonMass*(1+extraNucleonCount) );
     338  pseudoParticle[3].SetTotalEnergy(protonMass*(1+extraNucleonCount) );
     339   
     340  pseudoParticle[2] = pseudoParticle[0] + pseudoParticle[1];
     341  pseudoParticle[3] = pseudoParticle[3] + pseudoParticle[0];
     342   
     343  pseudoParticle[0].Lorentz( pseudoParticle[0], pseudoParticle[2] );
     344  pseudoParticle[1].Lorentz( pseudoParticle[1], pseudoParticle[2] );
     345   
     346  // Main loop for 4-momentum generation
     347  // See Pitha-report (Aachen) for a detailed description of the method
     348
     349  G4double aspar, pt, et, x, pp, pp1, wgt;
     350  G4int    innerCounter, outerCounter;
     351  G4bool   eliminateThisParticle, resetEnergies, constantCrossSection;
     352   
     353  G4double forwardKinetic = 0.0;
     354  G4double backwardKinetic = 0.0;
     355
     356  // Process the secondary particles in reverse order
     357  // The incident particle is done after the secondaries
     358  // Nucleons, including the target, in the backward hemisphere are also
     359  // done later
     360
     361  G4int backwardNucleonCount = 0;  // number of nucleons in backward hemisphere
     362  G4double totalEnergy, kineticEnergy, vecMass;
     363  G4double phi;
     364
     365  for (i = vecLen-1; i >= 0; --i) {
     366
     367    if (vec[i]->GetNewlyAdded()) {         // added from intranuclear cascade
     368      if (vec[i]->GetSide() == -2) {       // its a nucleon
     369        if (backwardNucleonCount < 18) {
     370          if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
     371            for(G4int i=0; i<vecLen; i++) delete vec[i];
     372            vecLen = 0;
     373            throw G4HadReentrentException(__FILE__, __LINE__,
     374            "G4RPGFragmentation::ReactionStage : a pion has been counted as a backward nucleon");
     375          }
     376          vec[i]->SetSide(-3);
     377          ++backwardNucleonCount;
     378          continue;     // Don't generate momenta for the first 17 backward
     379                        // cascade nucleons. This gets done by the cluster
     380                        // model later on.
     381        }
     382      }
     383    }
     384
     385    // Set pt and phi values, they are changed somewhat in the iteration loop
     386    // Set mass parameter for lambda fragmentation model
     387
     388    vecMass = vec[i]->GetMass()/GeV;
     389    G4double ran = -std::log(1.0-G4UniformRand())/3.5;
     390
     391    if (vec[i]->GetSide() == -2) {  // backward nucleon
     392      aspar = 0.20;
     393      pt = std::sqrt( std::pow( ran, 1.2 ) );
     394
     395    } else {                        // not a backward nucleon
     396      if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
     397        aspar = 0.75;
     398        pt = std::sqrt( std::pow( ran, 1.7 ) );
     399      } else if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
     400        aspar = 0.70;
     401        pt = std::sqrt( std::pow( ran, 1.7 ) );
     402      } else {                        // vec[i] must be a baryon or ion
     403        aspar = 0.65;
     404        pt = std::sqrt( std::pow( ran, 1.5 ) );
     405      }
     406    }
     407
     408    pt = std::max( 0.001, pt );
     409    phi = G4UniformRand()*twopi;
     410    vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
     411    if (vec[i]->GetSide() > 0)
     412      et = pseudoParticle[0].GetTotalEnergy()/GeV;
     413    else
     414      et = pseudoParticle[1].GetTotalEnergy()/GeV;
     415
    115416    //
    116     for( i=0; i<vecLen; ++i )
    117     {
    118       G4int itemp = G4int( G4UniformRand()*vecLen );
    119       G4ReactionProduct pTemp = *vec[itemp];
    120       *vec[itemp] = *vec[i];
    121       *vec[i] = pTemp;
    122       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    123     }
    124 
    125     if( currentMass == 0.0 && targetMass == 0.0 )
    126     {
    127       // Target and projectile have annihilated.  Replace them with the first
    128       // two secondaries in the list.  Current particle KE is maintained.
    129  
    130       G4double ek = currentParticle.GetKineticEnergy();
    131       G4ThreeVector m = currentParticle.GetMomentum();
    132       currentParticle = *vec[0];
    133       targetParticle = *vec[1];
    134       for( i=0; i<(vecLen-2); ++i )*vec[i] = *vec[i+2];
    135       G4ReactionProduct *temp = vec[vecLen-1];
    136       delete temp;
    137       temp = vec[vecLen-2];
    138       delete temp;
    139       vecLen -= 2;
    140       currentMass = currentParticle.GetMass()/GeV;
    141       targetMass = targetParticle.GetMass()/GeV;
    142       incidentHasChanged = true;
    143       targetHasChanged = true;
    144       currentParticle.SetKineticEnergy( ek );
    145       currentParticle.SetMomentum( m );
    146       veryForward = true;
    147     }
    148     const G4double atomicWeight = targetNucleus.GetN();
    149     const G4double atomicNumber = targetNucleus.GetZ();
    150     const G4double protonMass = aProton->GetPDGMass()/MeV;
    151 
    152     if (originalIncident->GetDefinition()->GetParticleSubType() == "kaon"
    153         && G4UniformRand() >= 0.7) {
    154       G4ReactionProduct temp = currentParticle;
    155       currentParticle = targetParticle;
    156       targetParticle = temp;
    157       incidentHasChanged = true;
    158       targetHasChanged = true;
    159       currentMass = currentParticle.GetMass()/GeV;
    160       targetMass = targetParticle.GetMass()/GeV;
    161     }
    162     const G4double afc = std::min( 0.75,
    163           0.312+0.200*std::log(std::log(centerofmassEnergy*centerofmassEnergy))+
    164           std::pow(centerofmassEnergy*centerofmassEnergy,1.5)/6000.0 );
    165    
    166     G4double freeEnergy = centerofmassEnergy-currentMass-targetMass;
    167     G4double forwardEnergy = freeEnergy/2.;
    168     G4int forwardCount = 1;         // number of particles in forward hemisphere
    169    
    170     G4double backwardEnergy = freeEnergy/2.;
    171     G4int backwardCount = 1;        // number of particles in backward hemisphere
    172 
    173     if(veryForward)
    174     {
    175       if(currentParticle.GetSide()==-1)
    176       {
    177         forwardEnergy += currentMass;
    178         forwardCount --;
    179         backwardEnergy -= currentMass;
    180         backwardCount ++;
    181       }
    182       if(targetParticle.GetSide()!=-1)
    183       {
    184         backwardEnergy += targetMass;
    185         backwardCount --;
    186         forwardEnergy -= targetMass;
    187         forwardCount ++;
    188       }
    189     }
    190 
    191     for( i=0; i<vecLen; ++i )
    192     {
    193       if( vec[i]->GetSide() == -1 )
    194       {
    195         ++backwardCount;
    196         backwardEnergy -= vec[i]->GetMass()/GeV;
    197       } else {
    198         ++forwardCount;
    199         forwardEnergy -= vec[i]->GetMass()/GeV;
    200       }
    201     }
     417    // Start of outer iteration loop
    202418    //
    203     //  Add particles from intranuclear cascade.
    204     //  nuclearExcitationCount = number of new secondaries produced by nuclear excitation
    205     //  extraCount = number of nucleons within these new secondaries
    206     //
    207     G4double xtarg;
    208     if( centerofmassEnergy < (2.0+G4UniformRand()) )
    209       xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount+vecLen+2)/2.0;
    210     else
    211       xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount);
    212     if( xtarg <= 0.0 )xtarg = 0.01;
    213     G4int nuclearExcitationCount = G4Poisson( xtarg );
    214     if(atomicWeight<1.0001) nuclearExcitationCount = 0;
    215     G4int extraNucleonCount = 0;
    216     G4double extraNucleonMass = 0.0;
    217     if( nuclearExcitationCount > 0 )
    218     {
    219       const G4double nucsup[] = { 1.00, 0.7, 0.5, 0.4, 0.35, 0.3 };
    220       const G4double psup[] = { 3., 6., 20., 50., 100., 1000. };
    221       G4int momentumBin = 0;
    222       while( (momentumBin < 6) &&
    223              (modifiedOriginal.GetTotalMomentum()/GeV > psup[momentumBin]) )
    224         ++momentumBin;
    225       momentumBin = std::min( 5, momentumBin );
    226       //
    227       //  NOTE: in GENXPT, these new particles were given negative codes
    228       //        here I use  NewlyAdded = true  instead
    229       //
    230 
    231       for( i=0; i<nuclearExcitationCount; ++i )
    232       {
    233         G4ReactionProduct * pVec = new G4ReactionProduct();
    234         if( G4UniformRand() < nucsup[momentumBin] )
    235         {
    236           if( G4UniformRand() > 1.0-atomicNumber/atomicWeight )
    237             pVec->SetDefinition( aProton );
    238           else
    239             pVec->SetDefinition( aNeutron );
    240           pVec->SetSide( -2 );                // -2 means backside nucleon
    241           ++extraNucleonCount;
    242           backwardEnergy += pVec->GetMass()/GeV;
    243           extraNucleonMass += pVec->GetMass()/GeV;
    244         }
    245         else
    246         {
    247           G4double ran = G4UniformRand();
    248           if( ran < 0.3181 )
    249             pVec->SetDefinition( aPiPlus );
    250           else if( ran < 0.6819 )
    251             pVec->SetDefinition( aPiZero );
    252           else
    253             pVec->SetDefinition( aPiMinus );
    254           pVec->SetSide( -1 );                // backside particle, but not a nucleon
    255         }
    256         pVec->SetNewlyAdded( true );                // true is the same as IPA(i)<0
    257         vec.SetElement( vecLen++, pVec );   
    258         // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    259         backwardEnergy -= pVec->GetMass()/GeV;
    260         ++backwardCount;
    261       }
    262     }
    263     //
    264     //  assume conservation of kinetic energy in forward & backward hemispheres
    265     //
    266     G4int is, iskip;
    267     while( forwardEnergy <= 0.0 )  // must eliminate a particle from the forward side
    268     {
    269       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    270       iskip = G4int(G4UniformRand()*forwardCount) + 1; // 1 <= iskip <= forwardCount
    271       is = 0;
    272       G4int forwardParticlesLeft = 0;
    273       for( i=(vecLen-1); i>=0; --i )
    274       {
    275         if( vec[i]->GetSide() == 1 && vec[i]->GetMayBeKilled())
    276         {
    277           forwardParticlesLeft = 1; 
    278           if( ++is == iskip )
    279           {
    280             forwardEnergy += vec[i]->GetMass()/GeV;
    281             for( G4int j=i; j<(vecLen-1); j++ )*vec[j] = *vec[j+1];    // shift up
    282             --forwardCount;
    283             delete vec[vecLen-1];
    284             if( --vecLen == 0 )return false;  // all the secondaries have been eliminated
    285             break;  // --+
    286           }         //   |
    287         }           //   |
    288       }             // break goes down to here
    289       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    290       if( forwardParticlesLeft == 0 )
    291       {
    292         G4int iremove = -1;
    293         for (G4int i = 0; i < vecLen; i++) {
    294           if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
    295             iremove = i;
    296             break;
     419    outerCounter = 0;
     420    eliminateThisParticle = true;
     421    resetEnergies = true;
     422    dndl[0] = 0.0;
     423
     424    while (++outerCounter < 3) {
     425
     426      FragmentationIntegral(pt, et, aspar, vecMass);
     427      innerCounter = 0;
     428      vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
     429
     430      // Start of inner iteration loop
     431
     432      while (++innerCounter < 7) {
     433
     434        ran = G4UniformRand()*dndl[19];
     435        l = 1;
     436        while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
     437        x = (G4double(l-1) + G4UniformRand())/19.;
     438        if (vec[i]->GetSide() < 0) x *= -1.;
     439        vec[i]->SetMomentum( x*et*GeV );              // set the z-momentum
     440        totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
     441        vec[i]->SetTotalEnergy( totalEnergy*GeV );
     442        kineticEnergy = vec[i]->GetKineticEnergy()/GeV;
     443
     444        if (vec[i]->GetSide() > 0) {                  // forward side
     445          if( (forwardKinetic+kineticEnergy) < 0.95*forwardEnergy ) {
     446            // Leave at least 5% of the forward free energy for the projectile
     447
     448            pseudoParticle[4] = pseudoParticle[4] + (*vec[i]);
     449            forwardKinetic += kineticEnergy;
     450            outerCounter = 2;                  // leave outer loop
     451            eliminateThisParticle = false;     // don't eliminate this particle
     452            resetEnergies = false;
     453            break;                             // leave inner loop
     454          }
     455          if( innerCounter > 5 )break;         // leave inner loop
     456          if( backwardEnergy >= vecMass )      // switch sides
     457          {
     458            vec[i]->SetSide(-1);
     459            forwardEnergy += vecMass;
     460            backwardEnergy -= vecMass;
     461            ++backwardCount;
     462          }
     463        } else {                               // backward side
     464          //  if (extraNucleonCount > 19) x = 0.999;
     465          //  G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
     466          //  DHW: I think above lines were meant to be as follows:
     467          G4double xxx = 0.999;
     468          if (extraNucleonCount < 20) xxx = 0.95+0.05*extraNucleonCount/20.0;
     469
     470          if ((backwardKinetic+kineticEnergy) < xxx*backwardEnergy) {
     471            pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
     472            backwardKinetic += kineticEnergy;
     473            outerCounter = 2;                  // leave outer loop
     474            eliminateThisParticle = false;     // don't eliminate this particle
     475            resetEnergies = false;
     476            break;                             // leave inner loop
     477          }
     478          if (innerCounter > 5) break;         // leave inner loop
     479          if (forwardEnergy >= vecMass) {      // switch sides
     480            vec[i]->SetSide(1);
     481            forwardEnergy -= vecMass;
     482            backwardEnergy += vecMass;
     483            backwardCount--;
    297484          }
    298485        }
    299         if (iremove == -1) {
    300           for (G4int i = 0; i < vecLen; i++) {
    301             if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
    302               iremove = i;
    303               break;
    304             }
    305           }
     486        G4ThreeVector momentum = vec[i]->GetMomentum();
     487        vec[i]->SetMomentum( momentum.x() * 0.9, momentum.y() * 0.9 );
     488        pt *= 0.9;
     489        dndl[19] *= 0.9;
     490      }                      // closes inner loop
     491
     492      // If we get here, the inner loop has been done 6 times.
     493      // If necessary, reduce energies of the previously done particles if
     494      // they are lighter than protons or are in the forward hemisphere.
     495      // Then continue with outer loop.
     496
     497      if (resetEnergies)
     498        ReduceEnergiesOfSecondaries(i+1, forwardKinetic, backwardKinetic,
     499                                    vec, vecLen,
     500                                    pseudoParticle[4], pseudoParticle[5],
     501                                    pt);
     502
     503    } // closes outer loop
     504             
     505    if (eliminateThisParticle && vec[i]->GetMayBeKilled()) {
     506      // not enough energy, eliminate this particle
     507
     508      if (vec[i]->GetSide() > 0) {
     509        --forwardCount;
     510        forwardEnergy += vecMass;
     511      } else {
     512        --backwardCount;
     513        if (vec[i]->GetSide() == -2) {
     514          --extraNucleonCount;
     515          extraNucleonMass -= vecMass;
     516        } else {
     517          backwardEnergy += vecMass;
     518        }
     519      }
     520
     521      for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];    // shift up
     522      G4ReactionProduct* temp = vec[vecLen-1];
     523      delete temp;
     524      // To do: modify target nucleus according to particle eliminated 
     525
     526      if( --vecLen == 0 ){
     527        G4cout << " FALSE RETURN DUE TO ENERGY BALANCE " << G4endl;
     528        return false;
     529      }  // all the secondaries have been eliminated
     530    }
     531  } // closes main loop over secondaries
     532
     533  // Re-balance forward and backward energy if possible and if necessary
     534
     535  G4double forwardKEDiff = forwardEnergy - forwardKinetic;
     536  G4double backwardKEDiff = backwardEnergy - backwardKinetic;
     537
     538  if (forwardKEDiff < 0.0 || backwardKEDiff < 0.0) {
     539    ReduceEnergiesOfSecondaries(0, forwardKinetic, backwardKinetic,
     540                                vec, vecLen,
     541                                pseudoParticle[4], pseudoParticle[5],
     542                                pt);
     543 
     544    forwardKEDiff = forwardEnergy - forwardKinetic;
     545    backwardKEDiff = backwardEnergy - backwardKinetic;
     546    if (backwardKEDiff < 0.0) {
     547      if (forwardKEDiff + backwardKEDiff > 0.0) {
     548        backwardEnergy = backwardKinetic;
     549        forwardEnergy += backwardKEDiff;
     550        forwardKEDiff = forwardEnergy - forwardKinetic;
     551        backwardKEDiff = 0.0;
     552      } else {
     553        G4cout << " False return due to insufficient backward energy " << G4endl;
     554        return false;
     555      }
     556    }
     557     
     558    if (forwardKEDiff < 0.0) {
     559      if (forwardKEDiff + backwardKEDiff > 0.0) {
     560        forwardEnergy = forwardKinetic;
     561        backwardEnergy += forwardKEDiff;
     562        backwardKEDiff = backwardEnergy - backwardKinetic;
     563        forwardKEDiff = 0.0;
     564      } else {
     565        G4cout << " False return due to insufficient forward energy " << G4endl;
     566        return false;
     567      }
     568    }
     569  }
     570
     571  // Generate momentum for incident (current) particle, which was placed
     572  // in the forward hemisphere.
     573  // Set mass parameter for lambda fragmentation model.
     574  // Set pt and phi values, which are changed somewhat in the iteration loop
     575
     576  G4double ran = -std::log(1.0-G4UniformRand());
     577  if (currentParticle.GetDefinition()->GetParticleSubType() == "pi") {
     578    aspar = 0.60;
     579    pt = std::sqrt( std::pow( ran/6.0, 1.7 ) );
     580  } else if (currentParticle.GetDefinition()->GetParticleSubType() == "kaon") {
     581    aspar = 0.50;
     582    pt = std::sqrt( std::pow( ran/5.0, 1.4 ) );
     583  } else {
     584    aspar = 0.40;
     585    pt = std::sqrt( std::pow( ran/4.0, 1.2 ) );
     586  }
     587
     588  phi = G4UniformRand()*twopi;
     589  currentParticle.SetMomentum(pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV);
     590  et = pseudoParticle[0].GetTotalEnergy()/GeV;
     591  dndl[0] = 0.0;
     592  vecMass = currentParticle.GetMass()/GeV;
     593
     594  FragmentationIntegral(pt, et, aspar, vecMass);
     595
     596  ran = G4UniformRand()*dndl[19];
     597  l = 1;
     598  while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
     599  x = (G4double(l-1) + G4UniformRand())/19.;
     600  currentParticle.SetMomentum( x*et*GeV );             // set the z-momentum
     601
     602  if (forwardEnergy < forwardKinetic) {
     603    totalEnergy = vecMass + 0.04*std::fabs(normal());
     604    G4cout << " Not enough forward energy: forwardEnergy = "
     605           << forwardEnergy << " forwardKinetic = " 
     606           << forwardKinetic << " total energy left = "
     607           << backwardKEDiff + forwardKEDiff << G4endl;
     608  } else {
     609    totalEnergy = vecMass + forwardEnergy - forwardKinetic;
     610    forwardKinetic = forwardEnergy;
     611  }
     612  currentParticle.SetTotalEnergy( totalEnergy*GeV );
     613  pp = std::sqrt(std::abs( totalEnergy*totalEnergy - vecMass*vecMass) )*GeV;
     614  pp1 = currentParticle.GetMomentum().mag();
     615
     616  if (pp1 < 1.0e-6*GeV) {
     617    G4ThreeVector iso = Isotropic(pp);
     618    currentParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
     619  } else {
     620    currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
     621  }
     622  pseudoParticle[4] = pseudoParticle[4] + currentParticle;
     623
     624  // Current particle now finished
     625
     626  // Begin target particle
     627
     628  if (backwardNucleonCount < 18) {
     629    targetParticle.SetSide(-3);
     630    ++backwardNucleonCount;
     631
     632  } else {
     633    // Set pt and phi values, they are changed somewhat in the iteration loop
     634    // Set mass parameter for lambda fragmentation model
     635
     636    vecMass = targetParticle.GetMass()/GeV;
     637    ran = -std::log(1.0-G4UniformRand());
     638    aspar = 0.40;
     639    pt = std::max( 0.001, std::sqrt( std::pow( ran/4.0, 1.2 ) ) );
     640    phi = G4UniformRand()*twopi;
     641    targetParticle.SetMomentum(pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV);
     642    et = pseudoParticle[1].GetTotalEnergy()/GeV;
     643    outerCounter = 0;
     644    innerCounter = 0;
     645    G4bool marginalEnergy = true;
     646    dndl[0] = 0.0;
     647    G4double xxx = 0.999;
     648    if( extraNucleonCount < 20 ) xxx = 0.95+0.05*extraNucleonCount/20.0;
     649    G4ThreeVector momentum;
     650
     651    while (++outerCounter < 4) {
     652      FragmentationIntegral(pt, et, aspar, vecMass);
     653
     654      for (innerCounter = 0; innerCounter < 6; innerCounter++) {
     655        ran = G4UniformRand()*dndl[19];
     656        l = 1;
     657        while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
     658        x = -(G4double(l-1) + G4UniformRand())/19.;
     659        targetParticle.SetMomentum( x*et*GeV );        // set the z-momentum
     660        totalEnergy = std::sqrt(x*et*x*et + pt*pt + vecMass*vecMass);
     661        targetParticle.SetTotalEnergy( totalEnergy*GeV );
     662
     663        if ((backwardKinetic+totalEnergy-vecMass) < xxx*backwardEnergy) {
     664          pseudoParticle[5] = pseudoParticle[5] + targetParticle;
     665          backwardKinetic += totalEnergy - vecMass;
     666          outerCounter = 3;                 // leave outer loop
     667          marginalEnergy = false;
     668          break;                            // leave inner loop
    306669        }
    307         if (iremove == -1) iremove = 0;
    308 
    309         forwardEnergy += vec[iremove]->GetMass()/GeV;
    310         if (vec[iremove]->GetSide() > 0) --forwardCount;
    311  
    312         for (G4int i = iremove; i < vecLen-1; i++) *vec[i] = *vec[i+1];
    313         delete vec[vecLen-1];
    314         vecLen--;
    315         if (vecLen == 0) return false;  // all secondaries have been eliminated
    316         break;
    317       }
    318     } // while
    319 
    320       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    321     while( backwardEnergy <= 0.0 )  // must eliminate a particle from the backward side
     670        momentum = targetParticle.GetMomentum();
     671        targetParticle.SetMomentum(momentum.x() * 0.9, momentum.y() * 0.9);
     672        pt *= 0.9;
     673        dndl[19] *= 0.9;
     674      }
     675    }
     676
     677    if (marginalEnergy) {
     678      G4cout << " Extra backward kinetic energy = "
     679             << 0.999*backwardEnergy - backwardKinetic << G4endl;
     680      totalEnergy = vecMass + 0.999*backwardEnergy - backwardKinetic;
     681      targetParticle.SetTotalEnergy(totalEnergy*GeV);
     682      pp = std::sqrt(std::abs(totalEnergy*totalEnergy - vecMass*vecMass) )*GeV;
     683      targetParticle.SetMomentum(momentum.x()/0.9, momentum.y()/0.9);
     684      pp1 = targetParticle.GetMomentum().mag();
     685      targetParticle.SetMomentum(targetParticle.GetMomentum() * pp/pp1 );
     686      pseudoParticle[5] = pseudoParticle[5] + targetParticle;
     687      backwardKinetic = 0.999*backwardEnergy;
     688    }
     689
     690  }
     691
     692  if (backwardEnergy < backwardKinetic)
     693    G4cout << " Backward Edif = " << backwardEnergy - backwardKinetic << G4endl;
     694  if (forwardEnergy != forwardKinetic)
     695    G4cout << " Forward Edif = " << forwardEnergy - forwardKinetic << G4endl;
     696
     697  // Target particle finished.
     698  // Now produce backward nucleons with a cluster model
     699  // ps[2] = CM frame of projectile + target
     700  // ps[3] = sum of projectile + nucleon cluster in lab frame
     701  // ps[6] = proj + cluster 4-vector boosted into CM frame of proj + targ
     702  //         with secondaries, current and target particles subtracted
     703  //       = total 4-momentum of backward nucleon cluster 
     704
     705  pseudoParticle[6].Lorentz( pseudoParticle[3], pseudoParticle[2] );
     706  pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[4];
     707  pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[5];
     708
     709  if (backwardNucleonCount == 1) {   
     710    // Target particle is the only backward nucleon.  Give it the remainder
     711    // of the backward kinetic energy.
     712
     713    G4double ekin =
     714      std::min(backwardEnergy-backwardKinetic, centerofmassEnergy/2.0-protonMass/GeV);
     715
     716    if( ekin < 0.04 )ekin = 0.04 * std::fabs( normal() );
     717    vecMass = targetParticle.GetMass()/GeV;
     718    totalEnergy = ekin + vecMass;
     719    targetParticle.SetTotalEnergy( totalEnergy*GeV );
     720    pp = std::sqrt(std::abs(totalEnergy*totalEnergy - vecMass*vecMass) )*GeV;
     721    pp1 = pseudoParticle[6].GetMomentum().mag();
     722    if (pp1 < 1.0e-6*GeV) {
     723      G4ThreeVector iso = Isotropic(pp);
     724      targetParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
     725    } else {
     726      targetParticle.SetMomentum( pseudoParticle[6].GetMomentum() * (pp/pp1));
     727    }
     728    pseudoParticle[5] = pseudoParticle[5] + targetParticle;
     729
     730  } else if (backwardNucleonCount > 1) {
     731    // Share remaining energy with up to 17 backward nucleons
     732
     733    G4int tempCount = 5;
     734    if (backwardNucleonCount < 5) tempCount = backwardNucleonCount;
     735    tempCount -= 2;
     736
     737    G4double clusterMass = 0.;
     738    if (targetParticle.GetSide() == -3)
     739      clusterMass = targetParticle.GetMass()/GeV;
     740    for (i = 0; i < vecLen; ++i)
     741      if (vec[i]->GetSide() == -3) clusterMass += vec[i]->GetMass()/GeV;
     742    clusterMass += backwardEnergy - backwardKinetic;
     743
     744    totalEnergy = pseudoParticle[6].GetTotalEnergy()/GeV;
     745    pseudoParticle[6].SetMass(clusterMass*GeV);
     746
     747    pp = std::sqrt(std::abs(totalEnergy*totalEnergy -
     748                            clusterMass*clusterMass) )*GeV;
     749    pp1 = pseudoParticle[6].GetMomentum().mag();
     750    if (pp1 < 1.0e-6*GeV) {
     751      G4ThreeVector iso = Isotropic(pp);
     752      pseudoParticle[6].SetMomentum(iso.x(), iso.y(), iso.z());
     753    } else {
     754      pseudoParticle[6].SetMomentum(pseudoParticle[6].GetMomentum() * (-pp/pp1));
     755    }
     756
     757    std::vector<G4ReactionProduct*> tempList;  // ptrs to backward nucleons
     758    if (targetParticle.GetSide() == -3) tempList.push_back(&targetParticle);
     759    for (i = 0; i < vecLen; ++i)
     760      if (vec[i]->GetSide() == -3) tempList.push_back(vec[i]);
     761
     762    constantCrossSection = true;
     763
     764    if (tempList.size() > 1) {
     765      G4int n_entry = 0;
     766      wgt = GenerateNBodyEventT(pseudoParticle[6].GetMass(),
     767                                constantCrossSection, tempList);
     768
     769      if (targetParticle.GetSide() == -3) {
     770        targetParticle = *tempList[0];
     771        targetParticle.Lorentz(targetParticle, pseudoParticle[6]);
     772        n_entry++;
     773      }
     774
     775      for (i = 0; i < vecLen; ++i) {
     776        if (vec[i]->GetSide() == -3) {
     777          *vec[i] = *tempList[n_entry];
     778          vec[i]->Lorentz(*vec[i], pseudoParticle[6]);
     779          n_entry++;
     780        }
     781      }
     782    }
     783  } else return false;
     784
     785  if (vecLen == 0) return false;  // all the secondaries have been eliminated
     786
     787  // Lorentz transformation to lab frame
     788
     789  currentParticle.Lorentz( currentParticle, pseudoParticle[1] );
     790  targetParticle.Lorentz( targetParticle, pseudoParticle[1] );   
     791  for (i = 0; i < vecLen; ++i) vec[i]->Lorentz(*vec[i], pseudoParticle[1]);
     792
     793  // Set leading strange particle flag.
     794  // leadFlag will be true if original particle and incident particle are
     795  // both strange, in which case the incident particle becomes the leading
     796  // particle.
     797  // leadFlag will also be true if the target particle is strange, but the
     798  // incident particle is not, in which case the target particle becomes the
     799  // leading particle.
     800
     801  G4bool leadingStrangeParticleHasChanged = true;
     802  if (leadFlag)
     803  {
     804    if (currentParticle.GetDefinition() == leadingStrangeParticle.GetDefinition())
     805      leadingStrangeParticleHasChanged = false;
     806    if (leadingStrangeParticleHasChanged &&
     807        (targetParticle.GetDefinition() == leadingStrangeParticle.GetDefinition()) )
     808      leadingStrangeParticleHasChanged = false;
     809    if( leadingStrangeParticleHasChanged )
    322810    {
    323       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    324       iskip = G4int(G4UniformRand()*backwardCount) + 1; // 1 <= iskip <= backwardCount
    325       is = 0;
    326       G4int backwardParticlesLeft = 0;
    327       for( i=(vecLen-1); i>=0; --i )
     811      for( i=0; i<vecLen; i++ )
    328812      {
    329         if( vec[i]->GetSide() < 0 && vec[i]->GetMayBeKilled())
    330         {
    331           backwardParticlesLeft = 1;
    332           if( ++is == iskip )        // eliminate the i'th particle
    333           {
    334             if( vec[i]->GetSide() == -2 )
    335             {
    336               --extraNucleonCount;
    337               extraNucleonMass -= vec[i]->GetMass()/GeV;
    338               backwardEnergy -= vec[i]->GetTotalEnergy()/GeV;
    339             }
    340             backwardEnergy += vec[i]->GetTotalEnergy()/GeV;
    341             for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];   // shift up
    342             --backwardCount;
    343             delete vec[vecLen-1];
    344             if( --vecLen == 0 )return false;  // all the secondaries have been eliminated
    345             break;
    346           }
     813        if( vec[i]->GetDefinition() == leadingStrangeParticle.GetDefinition() )
     814        {
     815          leadingStrangeParticleHasChanged = false;
     816          break;
    347817        }
    348818      }
    349       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    350       if( backwardParticlesLeft == 0 )
     819    }
     820    if( leadingStrangeParticleHasChanged )
     821    {
     822      G4bool leadTest =
     823        (leadingStrangeParticle.GetDefinition()->GetParticleSubType() == "kaon" ||
     824         leadingStrangeParticle.GetDefinition()->GetParticleSubType() == "pi");
     825      G4bool targetTest =
     826        (targetParticle.GetDefinition()->GetParticleSubType() == "kaon" ||
     827         targetParticle.GetDefinition()->GetParticleSubType() == "pi");
     828       
     829      // following modified by JLC 22-Oct-97
     830         
     831      if( (leadTest&&targetTest) || !(leadTest||targetTest) ) // both true or both false
    351832      {
    352         G4int iremove = -1;
    353         for (G4int i = 0; i < vecLen; i++) {
    354           if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
    355             iremove = i;
    356             break;
    357           }
    358         }
    359         if (iremove == -1) {
    360           for (G4int i = 0; i < vecLen; i++) {
    361             if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
    362               iremove = i;
    363               break;
    364             }
    365           }
    366         }
    367         if (iremove == -1) iremove = 0;
    368  
    369         backwardEnergy += vec[iremove]->GetMass()/GeV;
    370         if (vec[iremove]->GetSide() > 0) --backwardCount;
    371  
    372         for (G4int i = iremove; i < vecLen-1; i++) *vec[i] = *vec[i+1];
    373         delete vec[vecLen-1];
    374         vecLen--;
    375         if (vecLen == 0) return false;  // all secondaries have been eliminated
    376         break;
    377       }
    378     } // while
    379 
    380       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    381     //
    382     //  define initial state vectors for Lorentz transformations
    383     //  the pseudoParticles have non-standard masses, hence the "pseudo"
    384     //
    385     G4ReactionProduct pseudoParticle[8];
    386     for( i=0; i<8; ++i )pseudoParticle[i].SetZero();
    387    
    388     pseudoParticle[0].SetMass( mOriginal*GeV );
    389     pseudoParticle[0].SetMomentum( 0.0, 0.0, pOriginal*GeV );
    390     pseudoParticle[0].SetTotalEnergy(
    391      std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
    392    
    393     pseudoParticle[1].SetMass( protonMass*MeV );        // this could be targetMass
    394     pseudoParticle[1].SetTotalEnergy( protonMass*MeV );
    395    
    396     pseudoParticle[3].SetMass( protonMass*(1+extraNucleonCount)*MeV );
    397     pseudoParticle[3].SetTotalEnergy( protonMass*(1+extraNucleonCount)*MeV );
    398    
    399     pseudoParticle[2] = pseudoParticle[0] + pseudoParticle[1];
    400     pseudoParticle[3] = pseudoParticle[3] + pseudoParticle[0];
    401    
    402     pseudoParticle[0].Lorentz( pseudoParticle[0], pseudoParticle[2] );
    403     pseudoParticle[1].Lorentz( pseudoParticle[1], pseudoParticle[2] );
    404    
    405     //
    406     //  main loop for 4-momentum generation
    407     //  see Pitha-report (Aachen) for a detailed description of the method
    408     //
    409     G4double aspar, pt, et, x, pp, pp1, wgt;
    410     G4int    innerCounter, outerCounter;
    411     G4bool   eliminateThisParticle, resetEnergies, constantCrossSection;
    412    
    413     G4double forwardKinetic = 0.0, backwardKinetic = 0.0;
    414     //
    415     // process the secondary particles in reverse order
    416     // the incident particle is Done after the secondaries
    417     // nucleons, including the target, in the backward hemisphere are also Done later
    418     //
    419     G4int backwardNucleonCount = 0;       // number of nucleons in backward hemisphere
    420     G4double totalEnergy, kineticEnergy, vecMass;
    421 
    422     for( i=(vecLen-1); i>=0; --i )
    423     {
    424       G4double phi = G4UniformRand()*twopi;
    425       if( vec[i]->GetNewlyAdded() )           // added from intranuclear cascade
     833        targetParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.GetDefinition() );
     834        targetHasChanged = true;
     835      }
     836      else
    426837      {
    427         if( vec[i]->GetSide() == -2 )         //  is a nucleon
    428         {
    429           if( backwardNucleonCount < 18 )
    430           {
    431             if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
    432               for(G4int i=0; i<vecLen; i++) delete vec[i];
    433               vecLen = 0;
    434               throw G4HadReentrentException(__FILE__, __LINE__,
    435               "G4RPGFragmentation::ReactionStage : a pion has been counted as a backward nucleon");
    436             }
    437             vec[i]->SetSide( -3 );
    438             ++backwardNucleonCount;
    439             continue;
    440           }
    441         }
    442       }
    443       //
    444       //  set pt and phi values, they are changed somewhat in the iteration loop
    445       //  set mass parameter for lambda fragmentation model
    446       //
    447       vecMass = vec[i]->GetMass()/GeV;
    448       G4double ran = -std::log(1.0-G4UniformRand())/3.5;
    449       if( vec[i]->GetSide() == -2 )   // backward nucleon
    450       {
    451         if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon" ||
    452             vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
    453           aspar = 0.75;
    454           pt = std::sqrt( std::pow( ran, 1.7 ) );
    455         } else {                          // vec[i] must be a proton, neutron,
    456           aspar = 0.20;                   //  lambda, sigma, xsi, or ion
    457           pt = std::sqrt( std::pow( ran, 1.2 ) );
    458         }
    459 
    460       } else {                          // not a backward nucleon
    461 
    462         if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
    463           aspar = 0.75;
    464           pt = std::sqrt( std::pow( ran, 1.7 ) );
    465         } else if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
    466           aspar = 0.70;
    467           pt = std::sqrt( std::pow( ran, 1.7 ) );
    468         } else {                        // vec[i] must be a proton, neutron,
    469           aspar = 0.65;                 //  lambda, sigma, xsi, or ion
    470           pt = std::sqrt( std::pow( ran, 1.5 ) );
    471         }
    472       }
    473       pt = std::max( 0.001, pt );
    474       vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
    475       if( vec[i]->GetSide() > 0 )
    476         et = pseudoParticle[0].GetTotalEnergy()/GeV;
    477       else
    478         et = pseudoParticle[1].GetTotalEnergy()/GeV;
    479 
    480       //
    481       //   start of outer iteration loop
    482       //
    483       outerCounter = 0;
    484       eliminateThisParticle = true;
    485       resetEnergies = true;
    486       dndl[0] = 0.0;
    487 
    488       while( ++outerCounter < 3 )
    489       {
    490         FragmentationIntegral(pt, et, aspar, vecMass);
    491 
    492         innerCounter = 0;
    493         vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
    494         //
    495         //   start of inner iteration loop
    496         //
    497         while( ++innerCounter < 7 )
    498         {
    499           ran = G4UniformRand()*dndl[19];
    500           l = 1;
    501           while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
    502           x = (G4double(l-1) + G4UniformRand())/19.;
    503           if( vec[i]->GetSide() < 0 )x *= -1.;
    504           vec[i]->SetMomentum( x*et*GeV );              // set the z-momentum
    505           totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
    506           vec[i]->SetTotalEnergy( totalEnergy*GeV );
    507           kineticEnergy = vec[i]->GetKineticEnergy()/GeV;
    508           if( vec[i]->GetSide() > 0 )                            // forward side
    509           {
    510             if( (forwardKinetic+kineticEnergy) < 0.95*forwardEnergy )
    511             {
    512               pseudoParticle[4] = pseudoParticle[4] + (*vec[i]);
    513               forwardKinetic += kineticEnergy;
    514               outerCounter = 2;                     // leave outer loop
    515               eliminateThisParticle = false;        // don't eliminate this particle
    516               resetEnergies = false;
    517               break;                                // leave inner loop
    518             }
    519             if( innerCounter > 5 )break;           // leave inner loop
    520             if( backwardEnergy >= vecMass )  // switch sides
    521             {
    522               vec[i]->SetSide( -1 );
    523               forwardEnergy += vecMass;
    524               backwardEnergy -= vecMass;
    525               ++backwardCount;
    526             }
    527           } else {                                                 // backward side
    528            if( extraNucleonCount > 19 )   // commented out to duplicate ?bug? in GENXPT
    529              x = 0.999;
    530            G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
    531            if( (backwardKinetic+kineticEnergy) < xxx*backwardEnergy )
    532             {
    533               pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
    534               backwardKinetic += kineticEnergy;
    535               outerCounter = 2;                    // leave outer loop
    536               eliminateThisParticle = false;       // don't eliminate this particle
    537               resetEnergies = false;
    538               break;                               // leave inner loop
    539             }
    540             if( innerCounter > 5 )break;           // leave inner loop
    541             if( forwardEnergy >= vecMass )  // switch sides
    542             {
    543               vec[i]->SetSide( 1 );
    544               forwardEnergy -= vecMass;
    545               backwardEnergy += vecMass;
    546               backwardCount--;
    547             }
    548           }
    549           G4ThreeVector momentum = vec[i]->GetMomentum();
    550           vec[i]->SetMomentum( momentum.x() * 0.9, momentum.y() * 0.9 );
    551           pt *= 0.9;
    552           dndl[19] *= 0.9;
    553         }                       // closes inner loop
    554         if( resetEnergies ) {
    555           //  If we get to here, the inner loop has been done 6 times.
    556           //  Reset the kinetic energies of previously done particles, if
    557           //  they are lighter than protons and in the forward hemisphere,
    558           //  then continue with outer loop.
    559           //
    560           forwardKinetic = 0.0;
    561           backwardKinetic = 0.0;
    562           pseudoParticle[4].SetZero();
    563           pseudoParticle[5].SetZero();
    564           for( l=i+1; l<vecLen; ++l ) {
    565             if (vec[l]->GetSide() > 0 ||
    566                 vec[l]->GetDefinition()->GetParticleSubType() == "kaon" ||
    567                 vec[l]->GetDefinition()->GetParticleSubType() == "pi") {
    568 
    569               G4double tempMass = vec[l]->GetMass()/MeV;
    570               totalEnergy = 0.95*vec[l]->GetTotalEnergy()/MeV + 0.05*tempMass;
    571               totalEnergy = std::max( tempMass, totalEnergy );
    572               vec[l]->SetTotalEnergy( totalEnergy*MeV );
    573               pp = std::sqrt( std::abs( totalEnergy*totalEnergy - tempMass*tempMass ) );
    574               pp1 = vec[l]->GetMomentum().mag()/MeV;
    575               if( pp1 < 1.0e-6*GeV ) {
    576                 G4ThreeVector iso = Isotropic(pp);
    577                 vec[l]->SetMomentum( iso.x(), iso.y(), iso.z() );
    578               } else {
    579                 vec[l]->SetMomentum( vec[l]->GetMomentum() * (pp/pp1) );
    580               }
    581               G4double px = vec[l]->GetMomentum().x()/MeV;
    582               G4double py = vec[l]->GetMomentum().y()/MeV;
    583               pt = std::max( 1.0, std::sqrt( px*px + py*py ) )/GeV;
    584               if( vec[l]->GetSide() > 0 )
    585               {
    586                 forwardKinetic += vec[l]->GetKineticEnergy()/GeV;
    587                 pseudoParticle[4] = pseudoParticle[4] + (*vec[l]);
    588               } else {
    589                 backwardKinetic += vec[l]->GetKineticEnergy()/GeV;
    590                 pseudoParticle[5] = pseudoParticle[5] + (*vec[l]);
    591               }
    592             } // if pi, K or forward
    593           } // for l
    594         } // if resetEnergies
    595       } // closes outer loop
    596              
    597       if( eliminateThisParticle && vec[i]->GetMayBeKilled())  // not enough energy, eliminate this particle
    598       {
    599         if( vec[i]->GetSide() > 0 )
    600         {
    601           --forwardCount;
    602           forwardEnergy += vecMass;
    603         } else {
    604           if( vec[i]->GetSide() == -2 )
    605           {
    606             --extraNucleonCount;
    607             extraNucleonMass -= vecMass;
    608             backwardEnergy -= vecMass;
    609           }
    610           --backwardCount;
    611           backwardEnergy += vecMass;
    612         }
    613         for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];    // shift up
    614         G4ReactionProduct *temp = vec[vecLen-1];
    615         delete temp;
    616         // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    617         if( --vecLen == 0 )return false;  // all the secondaries have been eliminated
    618       }
    619     }   // closes main for loop
    620 
    621     //
    622     //  for the incident particle:  it was placed in the forward hemisphere
    623     //   set pt and phi values, they are changed somewhat in the iteration loop
    624     //   set mass parameter for lambda fragmentation model
    625     //
    626     G4double phi = G4UniformRand()*twopi;
    627     G4double ran = -std::log(1.0-G4UniformRand());
    628     if (currentParticle.GetDefinition()->GetParticleSubType() == "pi") {
    629       aspar = 0.60;
    630       pt = std::sqrt( std::pow( ran/6.0, 1.7 ) );
    631     } else if (currentParticle.GetDefinition()->GetParticleSubType() == "kaon") {
    632       aspar = 0.50;
    633       pt = std::sqrt( std::pow( ran/5.0, 1.4 ) );
    634     } else {
    635       aspar = 0.40;
    636       pt = std::sqrt( std::pow( ran/4.0, 1.2 ) );
    637     }
    638 
    639     currentParticle.SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
    640     et = pseudoParticle[0].GetTotalEnergy()/GeV;
    641     dndl[0] = 0.0;
    642     vecMass = currentParticle.GetMass()/GeV;
    643 
    644     FragmentationIntegral(pt, et, aspar, vecMass);
    645 
    646     ran = G4UniformRand()*dndl[19];
    647     l = 1;
    648     while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
    649     x = (G4double(l-1) + G4UniformRand())/19.;
    650     currentParticle.SetMomentum( x*et*GeV );                 // set the z-momentum
    651     if( forwardEnergy < forwardKinetic )
    652       totalEnergy = vecMass + 0.04*std::fabs(normal());
    653     else
    654       totalEnergy = vecMass + forwardEnergy - forwardKinetic;
    655     currentParticle.SetTotalEnergy( totalEnergy*GeV );
    656     pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
    657     pp1 = currentParticle.GetMomentum().mag()/MeV;
    658 
    659     if( pp1 < 1.0e-6*GeV ) {
    660       G4ThreeVector iso = Isotropic(pp);
    661       currentParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
    662     } else {
    663       currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
    664     }
    665     pseudoParticle[4] = pseudoParticle[4] + currentParticle;
    666 
    667     //
    668     // Current particle now finished
    669     //
    670     // Begin target particle
    671     //
    672 
    673     if( backwardNucleonCount < 18 )
    674     {
    675       targetParticle.SetSide( -3 );
    676       ++backwardNucleonCount;
    677     }
    678     else
    679     {
    680       //  set pt and phi values, they are changed somewhat in the iteration loop
    681       //  set mass parameter for lambda fragmentation model
    682       //
    683       vecMass = targetParticle.GetMass()/GeV;
    684       ran = -std::log(1.0-G4UniformRand());
    685       aspar = 0.40;
    686       pt = std::max( 0.001, std::sqrt( std::pow( ran/4.0, 1.2 ) ) );
    687       targetParticle.SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
    688       et = pseudoParticle[1].GetTotalEnergy()/GeV;
    689       outerCounter = 0;
    690       eliminateThisParticle = true;     // should never eliminate the target particle
    691       resetEnergies = true;
    692       dndl[0] = 0.0;
    693 
    694       while( ++outerCounter < 3 )     // start of outer iteration loop
    695       {
    696         FragmentationIntegral(pt, et, aspar, vecMass);
    697 
    698         innerCounter = 0;
    699         while( ++innerCounter < 7 )    // start of inner iteration loop
    700         {
    701           ran = G4UniformRand()*dndl[19];
    702           l = 1;
    703           while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
    704           x = (G4double(l-1) + G4UniformRand())/19.;
    705           if( targetParticle.GetSide() < 0 )x *= -1.;
    706           targetParticle.SetMomentum( x*et*GeV );                // set the z-momentum
    707           totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
    708           targetParticle.SetTotalEnergy( totalEnergy*GeV );
    709           if( targetParticle.GetSide() < 0 )
    710           {
    711             if( extraNucleonCount > 19 )x=0.999;
    712             G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
    713             if( (backwardKinetic+totalEnergy-vecMass) < xxx*backwardEnergy )
    714             {
    715               pseudoParticle[5] = pseudoParticle[5] + targetParticle;
    716               backwardKinetic += totalEnergy - vecMass;
    717               //              pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
    718               //              pseudoParticle[6].SetMomentum( 0.0 );                      // set z-momentum
    719               outerCounter = 2;                    // leave outer loop
    720               eliminateThisParticle = false;       // don't eliminate this particle
    721               resetEnergies = false;
    722               break;                               // leave inner loop
    723             }
    724             if( innerCounter > 5 )break;           // leave inner loop
    725             if( forwardEnergy >= vecMass )  // switch sides
    726             {
    727               targetParticle.SetSide( 1 );
    728               forwardEnergy -= vecMass;
    729               backwardEnergy += vecMass;
    730               --backwardCount;
    731             }
    732             G4ThreeVector momentum = targetParticle.GetMomentum();
    733             targetParticle.SetMomentum( momentum.x() * 0.9, momentum.y() * 0.9 );
    734             pt *= 0.9;
    735             dndl[19] *= 0.9;
    736           }
    737           else                    // target has gone to forward side
    738           {
    739             if( forwardEnergy < forwardKinetic )
    740               totalEnergy = vecMass + 0.04*std::fabs(normal());
    741             else
    742               totalEnergy = vecMass + forwardEnergy - forwardKinetic;
    743             targetParticle.SetTotalEnergy( totalEnergy*GeV );
    744             pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
    745             pp1 = targetParticle.GetMomentum().mag()/MeV;
    746             if( pp1 < 1.0e-6*GeV ) {
    747               G4ThreeVector iso = Isotropic(pp);
    748               targetParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
    749             } else {
    750               targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
    751             }
    752 
    753             pseudoParticle[4] = pseudoParticle[4] + targetParticle;
    754             outerCounter = 2;                    // leave outer loop
    755             eliminateThisParticle = false;       // don't eliminate this particle
    756             resetEnergies = false;
    757             break;                               // leave inner loop
    758           }
    759         }    // closes inner loop
    760 
    761         if( resetEnergies ) {
    762           //  If we get to here, the inner loop has been done 6 times.
    763           //  Reset the kinetic energies of previously done particles,
    764           //  if they are lighter than protons and in the forward hemisphere,
    765           //  then continue with outer loop.
    766          
    767           forwardKinetic = backwardKinetic = 0.0;
    768           pseudoParticle[4].SetZero();
    769           pseudoParticle[5].SetZero();
    770           for( l=0; l<vecLen; ++l ) {
    771             if (vec[l]->GetSide() > 0 ||
    772                 vec[l]->GetDefinition()->GetParticleSubType() == "kaon" ||
    773                 vec[l]->GetDefinition()->GetParticleSubType() == "pi") {
    774               G4double tempMass = vec[l]->GetMass()/GeV;
    775               totalEnergy =
    776                 std::max( tempMass, 0.95*vec[l]->GetTotalEnergy()/GeV + 0.05*tempMass );
    777               vec[l]->SetTotalEnergy( totalEnergy*GeV );
    778               pp = std::sqrt( std::abs( totalEnergy*totalEnergy - tempMass*tempMass ) )*GeV;
    779               pp1 = vec[l]->GetMomentum().mag()/MeV;
    780               if( pp1 < 1.0e-6*GeV ) {
    781                 G4ThreeVector iso = Isotropic(pp);
    782                 vec[l]->SetMomentum( iso.x(), iso.y(), iso.z() );
    783               } else {
    784                 vec[l]->SetMomentum( vec[l]->GetMomentum() * (pp/pp1) );
    785               }
    786               pt = std::max( 0.001*GeV, std::sqrt( sqr(vec[l]->GetMomentum().x()/MeV) +
    787                                          sqr(vec[l]->GetMomentum().y()/MeV) ) )/GeV;
    788               if( vec[l]->GetSide() > 0)
    789               {
    790                 forwardKinetic += vec[l]->GetKineticEnergy()/GeV;
    791                 pseudoParticle[4] = pseudoParticle[4] + (*vec[l]);
    792               } else {
    793                 backwardKinetic += vec[l]->GetKineticEnergy()/GeV;
    794                 pseudoParticle[5] = pseudoParticle[5] + (*vec[l]);
    795               }
    796             } // if pi, K or forward
    797           } // for l
    798         } // if (resetEnergies)
    799       } // closes outer loop
    800 
    801 //      if( eliminateThisParticle )  // not enough energy, eliminate target
    802 //      {
    803 //        G4cerr << "Warning: eliminating target particle" << G4endl;
    804 //        exit( EXIT_FAILURE );
    805 //      }
    806     }
    807     //
    808     // Target particle finished.
    809     //
    810     // Now produce backward nucleons with a cluster model
    811     //
    812     pseudoParticle[6].Lorentz( pseudoParticle[3], pseudoParticle[2] );
    813     pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[4];
    814     pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[5];
    815     if( backwardNucleonCount == 1 )  // target particle is the only backward nucleon
    816     {
    817       G4double ekin =
    818         std::min( backwardEnergy-backwardKinetic, centerofmassEnergy/2.0-protonMass/GeV );
    819 
    820       if( ekin < 0.04 )ekin = 0.04 * std::fabs( normal() );
    821       vecMass = targetParticle.GetMass()/GeV;
    822       totalEnergy = ekin+vecMass;
    823       targetParticle.SetTotalEnergy( totalEnergy*GeV );
    824       pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
    825       pp1 = pseudoParticle[6].GetMomentum().mag()/MeV;
    826       if( pp1 < 1.0e-6*GeV ) {
    827         G4ThreeVector iso = Isotropic(pp);
    828         targetParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
    829       } else {
    830         targetParticle.SetMomentum( pseudoParticle[6].GetMomentum() * (pp/pp1) );
    831       }
    832       pseudoParticle[5] = pseudoParticle[5] + targetParticle;
    833     }
    834     else if (backwardNucleonCount > 1)
    835     {
    836       const G4double cpar[] = { 1.60, 1.35, 1.15, 1.10 };
    837       const G4double gpar[] = { 2.60, 1.80, 1.30, 1.20 };
    838 
    839       G4int tempCount = 5;
    840       if (backwardNucleonCount < 5) tempCount = backwardNucleonCount;
    841       tempCount -= 2;
    842 
    843       G4double rmb = 0.;
    844       if( targetParticle.GetSide() == -3 ) rmb += targetParticle.GetMass()/GeV;
    845       for( i=0; i<vecLen; ++i )
    846       {
    847         if( vec[i]->GetSide() == -3 ) rmb += vec[i]->GetMass()/GeV;
    848       }
    849       rmb += std::pow(-std::log(1.0-G4UniformRand()),1./cpar[tempCount]) / gpar[tempCount];
    850       totalEnergy = pseudoParticle[6].GetTotalEnergy()/GeV;
    851       vecMass = std::min( rmb, totalEnergy );
    852       pseudoParticle[6].SetMass( vecMass*GeV );
    853       pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
    854       pp1 = pseudoParticle[6].GetMomentum().mag()/MeV;
    855       if( pp1 < 1.0e-6*GeV ) {
    856         G4ThreeVector iso = Isotropic(pp);
    857         pseudoParticle[6].SetMomentum( iso.x(), iso.y(), iso.z() );
    858       } else {
    859         pseudoParticle[6].SetMomentum( pseudoParticle[6].GetMomentum() * (-pp/pp1) );
    860       }
    861       G4FastVector<G4ReactionProduct,256> tempV;  // tempV contains the backward nucleons
    862       tempV.Initialize( backwardNucleonCount );
    863       G4int tempLen = 0;
    864       if( targetParticle.GetSide() == -3 )tempV.SetElement( tempLen++, &targetParticle );
    865       for( i=0; i<vecLen; ++i )
    866       {
    867         if( vec[i]->GetSide() == -3 )tempV.SetElement( tempLen++, vec[i] );
    868       }
    869       if( tempLen != backwardNucleonCount )
    870       {
    871         G4cerr << "tempLen is not the same as backwardNucleonCount" << G4endl;
    872         G4cerr << "tempLen = " << tempLen;
    873         G4cerr << ", backwardNucleonCount = " << backwardNucleonCount << G4endl;
    874         G4cerr << "targetParticle side = " << targetParticle.GetSide() << G4endl;
    875         G4cerr << "currentParticle side = " << currentParticle.GetSide() << G4endl;
    876         for( i=0; i<vecLen; ++i )
    877           G4cerr << "particle #" << i << " side = " << vec[i]->GetSide() << G4endl;
    878         exit( EXIT_FAILURE );
    879       }
    880       constantCrossSection = true;
    881       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    882       if( tempLen >= 2 )
    883       {
    884         wgt = GenerateNBodyEvent(
    885          pseudoParticle[6].GetMass(), constantCrossSection, tempV, tempLen );
    886          // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    887         if( targetParticle.GetSide() == -3 )
    888         {
    889           targetParticle.Lorentz( targetParticle, pseudoParticle[6] );
    890           // tempV contains the real stuff
    891           pseudoParticle[5] = pseudoParticle[5] + targetParticle;
    892         }
    893         for( i=0; i<vecLen; ++i )
    894         {
    895           if( vec[i]->GetSide() == -3 )
    896           {
    897             vec[i]->Lorentz( *vec[i], pseudoParticle[6] );
    898             pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
    899           }
    900         }
    901       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    902       }
    903     }
    904     else return false;
    905 
    906     //
    907     //  Lorentz transformation in lab system
    908     //
    909     if( vecLen == 0 )return false;  // all the secondaries have been eliminated
    910       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    911    
    912     currentParticle.Lorentz( currentParticle, pseudoParticle[1] );
    913     targetParticle.Lorentz( targetParticle, pseudoParticle[1] );   
    914     for( i=0; i<vecLen; ++i ) vec[i]->Lorentz( *vec[i], pseudoParticle[1] );
    915 
    916     // leadFlag will be true if original particle and incident particle are
    917     // both strange, in which case the incident particle becomes the leading
    918     // particle.
    919     // leadFlag will also be true if the target particle is strange, but the
    920     // incident particle is not, in which case the target particle becomes the
    921     // leading particle.
    922 
    923     G4bool leadingStrangeParticleHasChanged = true;
    924     if( leadFlag )
    925     {
    926       if( currentParticle.GetDefinition() == leadingStrangeParticle.GetDefinition() )
    927         leadingStrangeParticleHasChanged = false;
    928       if( leadingStrangeParticleHasChanged &&
    929           ( targetParticle.GetDefinition() == leadingStrangeParticle.GetDefinition() ) )
    930         leadingStrangeParticleHasChanged = false;
    931       if( leadingStrangeParticleHasChanged )
    932       {
    933         for( i=0; i<vecLen; i++ )
    934         {
    935           if( vec[i]->GetDefinition() == leadingStrangeParticle.GetDefinition() )
    936           {
    937             leadingStrangeParticleHasChanged = false;
    938             break;
    939           }
    940         }
    941       }
    942       if( leadingStrangeParticleHasChanged )
    943       {
    944         G4bool leadTest =
    945           (leadingStrangeParticle.GetDefinition()->GetParticleSubType() == "kaon" ||
    946            leadingStrangeParticle.GetDefinition()->GetParticleSubType() == "pi");
    947         G4bool targetTest =
    948           (targetParticle.GetDefinition()->GetParticleSubType() == "kaon" ||
    949            targetParticle.GetDefinition()->GetParticleSubType() == "pi");
    950        
    951         // following modified by JLC 22-Oct-97
    952          
    953         if( (leadTest&&targetTest) || !(leadTest||targetTest) ) // both true or both false
    954         {
    955           targetParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.GetDefinition() );
    956           targetHasChanged = true;
    957       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    958         }
    959         else
    960         {
    961           currentParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.GetDefinition() );
    962           incidentHasChanged = false;
    963       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    964         }
    965       }
    966     }   // end of if( leadFlag )
    967 
    968     // Get number of final state nucleons and nucleons remaining in
    969     // target nucleus
    970    
    971     std::pair<G4int, G4int> finalStateNucleons =
    972       GetFinalStateNucleons(originalTarget, vec, vecLen);
    973 
    974     G4int protonsInFinalState = finalStateNucleons.first;
    975     G4int neutronsInFinalState = finalStateNucleons.second;
    976 
    977     G4int numberofFinalStateNucleons =
    978       protonsInFinalState + neutronsInFinalState;
    979 
    980     if (currentParticle.GetDefinition()->GetBaryonNumber() == 1 &&
    981         targetParticle.GetDefinition()->GetBaryonNumber() == 1 &&
    982         originalIncident->GetDefinition()->GetPDGMass() <
    983                                    G4Lambda::Lambda()->GetPDGMass())
    984       numberofFinalStateNucleons++;
    985 
    986     numberofFinalStateNucleons = std::max(1, numberofFinalStateNucleons);
    987 
    988     G4int PinNucleus = std::max(0,
    989       G4int(targetNucleus.GetZ()) - protonsInFinalState);
    990     G4int NinNucleus = std::max(0,
    991       G4int(targetNucleus.GetN()-targetNucleus.GetZ()) - neutronsInFinalState);
    992 
    993     pseudoParticle[3].SetMomentum( 0.0, 0.0, pOriginal*GeV );
    994     pseudoParticle[3].SetMass( mOriginal*GeV );
    995     pseudoParticle[3].SetTotalEnergy(
    996      std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
    997    
    998     G4ParticleDefinition * aOrgDef = modifiedOriginal.GetDefinition();
    999     G4int diff = 0;
    1000     if(aOrgDef == G4Proton::Proton() || aOrgDef == G4Neutron::Neutron() )  diff = 1;
    1001     if(numberofFinalStateNucleons == 1) diff = 0;
    1002     pseudoParticle[4].SetMomentum( 0.0, 0.0, 0.0 );
    1003     pseudoParticle[4].SetMass( protonMass*(numberofFinalStateNucleons-diff)*MeV );
    1004     pseudoParticle[4].SetTotalEnergy( protonMass*(numberofFinalStateNucleons-diff)*MeV );
    1005    
    1006     G4double theoreticalKinetic =
    1007       pseudoParticle[3].GetTotalEnergy()/MeV +
    1008       pseudoParticle[4].GetTotalEnergy()/MeV -
    1009       currentParticle.GetMass()/MeV -
    1010       targetParticle.GetMass()/MeV;
    1011    
    1012     G4double simulatedKinetic =
    1013       currentParticle.GetKineticEnergy()/MeV + targetParticle.GetKineticEnergy()/MeV;
    1014    
    1015     pseudoParticle[5] = pseudoParticle[3] + pseudoParticle[4];
    1016     pseudoParticle[3].Lorentz( pseudoParticle[3], pseudoParticle[5] );
    1017     pseudoParticle[4].Lorentz( pseudoParticle[4], pseudoParticle[5] );
    1018    
    1019     pseudoParticle[7].SetZero();
    1020     pseudoParticle[7] = pseudoParticle[7] + currentParticle;
    1021     pseudoParticle[7] = pseudoParticle[7] + targetParticle;
    1022 
    1023     for( i=0; i<vecLen; ++i )
    1024     {
    1025       pseudoParticle[7] = pseudoParticle[7] + *vec[i];
    1026       simulatedKinetic += vec[i]->GetKineticEnergy()/MeV;
    1027       theoreticalKinetic -= vec[i]->GetMass()/MeV;
    1028     }
    1029 
     838        currentParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.GetDefinition() );
     839        incidentHasChanged = false;
     840      }
     841    }
     842  }   // end of if( leadFlag )
     843
     844  // Get number of final state nucleons and nucleons remaining in
     845  // target nucleus
     846   
     847  std::pair<G4int, G4int> finalStateNucleons =
     848    GetFinalStateNucleons(originalTarget, vec, vecLen);
     849
     850  G4int protonsInFinalState = finalStateNucleons.first;
     851  G4int neutronsInFinalState = finalStateNucleons.second;
     852
     853  G4int numberofFinalStateNucleons =
     854    protonsInFinalState + neutronsInFinalState;
     855
     856  if (currentParticle.GetDefinition()->GetBaryonNumber() == 1 &&
     857      targetParticle.GetDefinition()->GetBaryonNumber() == 1 &&
     858      originalIncident->GetDefinition()->GetPDGMass() <
     859                                 G4Lambda::Lambda()->GetPDGMass())
     860    numberofFinalStateNucleons++;
     861
     862  numberofFinalStateNucleons = std::max(1, numberofFinalStateNucleons);
     863
     864  G4int PinNucleus = std::max(0,
     865    G4int(targetNucleus.GetZ()) - protonsInFinalState);
     866  G4int NinNucleus = std::max(0,
     867    G4int(targetNucleus.GetN()-targetNucleus.GetZ()) - neutronsInFinalState);
     868
     869  pseudoParticle[3].SetMomentum( 0.0, 0.0, pOriginal*GeV );
     870  pseudoParticle[3].SetMass( mOriginal*GeV );
     871  pseudoParticle[3].SetTotalEnergy(
     872   std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
     873   
     874  G4ParticleDefinition * aOrgDef = modifiedOriginal.GetDefinition();
     875  G4int diff = 0;
     876  if(aOrgDef == G4Proton::Proton() || aOrgDef == G4Neutron::Neutron() )  diff = 1;
     877  if(numberofFinalStateNucleons == 1) diff = 0;
     878  pseudoParticle[4].SetMomentum( 0.0, 0.0, 0.0 );
     879  pseudoParticle[4].SetMass( protonMass*(numberofFinalStateNucleons-diff) );
     880  pseudoParticle[4].SetTotalEnergy( protonMass*(numberofFinalStateNucleons-diff) );
     881   
     882  G4double theoreticalKinetic =
     883    pseudoParticle[3].GetTotalEnergy() + pseudoParticle[4].GetTotalEnergy() -
     884    currentParticle.GetMass() - targetParticle.GetMass();
     885  for (i = 0; i < vecLen; ++i) theoreticalKinetic -= vec[i]->GetMass();
     886   
     887  G4double simulatedKinetic =
     888    currentParticle.GetKineticEnergy() + targetParticle.GetKineticEnergy();
     889  for (i = 0; i < vecLen; ++i)
     890    simulatedKinetic += vec[i]->GetKineticEnergy();
     891   
     892  pseudoParticle[5] = pseudoParticle[3] + pseudoParticle[4];
     893  pseudoParticle[3].Lorentz( pseudoParticle[3], pseudoParticle[5] );
     894  pseudoParticle[4].Lorentz( pseudoParticle[4], pseudoParticle[5] );
     895   
     896  pseudoParticle[7].SetZero();
     897  pseudoParticle[7] = pseudoParticle[7] + currentParticle;
     898  pseudoParticle[7] = pseudoParticle[7] + targetParticle;
     899  for (i = 0; i < vecLen; ++i)
     900    pseudoParticle[7] = pseudoParticle[7] + *vec[i];
     901
     902    /*
     903    // This code does not appear to do anything to the energy or angle spectra
    1030904    if( vecLen <= 16 && vecLen > 0 )
    1031905    {
     
    1037911      tempR[1] = targetParticle;
    1038912      for( i=0; i<vecLen; ++i )tempR[i+2] = *vec[i];
    1039       G4FastVector<G4ReactionProduct,256> tempV;
    1040       tempV.Initialize( vecLen+2 );
    1041       G4int tempLen = 0;
    1042       for( i=0; i<vecLen+2; ++i )tempV.SetElement( tempLen++, &tempR[i] );
     913      G4FastVector<G4ReactionProduct,256> tempV1;
     914      tempV1.Initialize( vecLen+2 );
     915      G4int tempLen1 = 0;
     916      for( i=0; i<vecLen+2; ++i )tempV1.SetElement( tempLen1++, &tempR[i] );
    1043917      constantCrossSection = true;
    1044918
    1045       wgt = GenerateNBodyEvent( pseudoParticle[3].GetTotalEnergy()/MeV+
    1046                                 pseudoParticle[4].GetTotalEnergy()/MeV,
    1047                                 constantCrossSection, tempV, tempLen );
     919      wgt = GenerateNBodyEvent(pseudoParticle[3].GetTotalEnergy() +
     920                               pseudoParticle[4].GetTotalEnergy(),
     921                               constantCrossSection, tempV1, tempLen1);
    1048922      if (wgt == -1) {
    1049923        G4double Qvalue = 0;
    1050         for (i = 0; i < tempLen; i++) Qvalue += tempV[i]->GetMass();
    1051         wgt = GenerateNBodyEvent( Qvalue/MeV,
    1052                                   constantCrossSection, tempV, tempLen );
     924        for (i = 0; i < tempLen1; i++) Qvalue += tempV1[i]->GetMass();
     925        wgt = GenerateNBodyEvent(Qvalue,
     926                                 constantCrossSection, tempV1, tempLen1);
    1053927      }
    1054928      if(wgt>-.5)
    1055929      {
    1056930        theoreticalKinetic = 0.0;
    1057         for( i=0; i<tempLen; ++i )
     931        for( i=0; i<tempLen1; ++i )
    1058932        {
    1059           pseudoParticle[6].Lorentz( *tempV[i], pseudoParticle[4] );
    1060           theoreticalKinetic += pseudoParticle[6].GetKineticEnergy()/MeV;
     933          pseudoParticle[6].Lorentz( *tempV1[i], pseudoParticle[4] );
     934          theoreticalKinetic += pseudoParticle[6].GetKineticEnergy();
    1061935        }
    1062936      }
    1063937      // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    1064938    }
    1065     //
    1066     //  Make sure, that the kinetic energies are correct
    1067     //
    1068     if( simulatedKinetic != 0.0 )
    1069     {
    1070       wgt = (theoreticalKinetic)/simulatedKinetic;
    1071       theoreticalKinetic = currentParticle.GetKineticEnergy()/MeV * wgt;
    1072       simulatedKinetic = theoreticalKinetic;
    1073       currentParticle.SetKineticEnergy( theoreticalKinetic*MeV );
    1074       pp = currentParticle.GetTotalMomentum()/MeV;
    1075       pp1 = currentParticle.GetMomentum().mag()/MeV;
     939    */
     940
     941  //
     942  // Make sure that the kinetic energies are correct
     943  //
     944
     945  if (simulatedKinetic != 0.0) {
     946    wgt = theoreticalKinetic/simulatedKinetic;
     947    theoreticalKinetic = currentParticle.GetKineticEnergy() * wgt;
     948    simulatedKinetic = theoreticalKinetic;
     949    currentParticle.SetKineticEnergy(theoreticalKinetic);
     950    pp = currentParticle.GetTotalMomentum();
     951    pp1 = currentParticle.GetMomentum().mag();
     952    if (pp1 < 1.0e-6*GeV) {
     953      G4ThreeVector iso = Isotropic(pp);
     954      currentParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
     955    } else {
     956      currentParticle.SetMomentum(currentParticle.GetMomentum() * (pp/pp1));
     957    }
     958
     959    theoreticalKinetic = targetParticle.GetKineticEnergy() * wgt;
     960    targetParticle.SetKineticEnergy(theoreticalKinetic);
     961    simulatedKinetic += theoreticalKinetic;
     962    pp = targetParticle.GetTotalMomentum();
     963    pp1 = targetParticle.GetMomentum().mag();
     964
     965    if (pp1 < 1.0e-6*GeV) {
     966      G4ThreeVector iso = Isotropic(pp);
     967      targetParticle.SetMomentum(iso.x(), iso.y(), iso.z() );
     968    } else {
     969      targetParticle.SetMomentum(targetParticle.GetMomentum() * (pp/pp1) );
     970    }
     971
     972    for (i = 0; i < vecLen; ++i ) {
     973      theoreticalKinetic = vec[i]->GetKineticEnergy() * wgt;
     974      simulatedKinetic += theoreticalKinetic;
     975      vec[i]->SetKineticEnergy(theoreticalKinetic);
     976      pp = vec[i]->GetTotalMomentum();
     977      pp1 = vec[i]->GetMomentum().mag();
    1076978      if( pp1 < 1.0e-6*GeV ) {
    1077979        G4ThreeVector iso = Isotropic(pp);
    1078         currentParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
     980        vec[i]->SetMomentum(iso.x(), iso.y(), iso.z() );
    1079981      } else {
    1080         currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
    1081       }
    1082       theoreticalKinetic = targetParticle.GetKineticEnergy()/MeV * wgt;
    1083       targetParticle.SetKineticEnergy( theoreticalKinetic*MeV );
    1084       simulatedKinetic += theoreticalKinetic;
    1085       pp = targetParticle.GetTotalMomentum()/MeV;
    1086       pp1 = targetParticle.GetMomentum().mag()/MeV;
    1087       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    1088       if( pp1 < 1.0e-6*GeV ) {
    1089         G4ThreeVector iso = Isotropic(pp);
    1090         targetParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
    1091       } else {
    1092         targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
    1093       }
    1094 
    1095       for( i=0; i<vecLen; ++i ) {
    1096         theoreticalKinetic = vec[i]->GetKineticEnergy()/MeV * wgt;
    1097         simulatedKinetic += theoreticalKinetic;
    1098         vec[i]->SetKineticEnergy( theoreticalKinetic*MeV );
    1099         pp = vec[i]->GetTotalMomentum()/MeV;
    1100         pp1 = vec[i]->GetMomentum().mag()/MeV;
    1101         if( pp1 < 1.0e-6*GeV ) {
    1102           G4ThreeVector iso = Isotropic(pp);
    1103           vec[i]->SetMomentum( iso.x(), iso.y(), iso.z() );
    1104         } else {
    1105           vec[i]->SetMomentum( vec[i]->GetMomentum() * (pp/pp1) );
    1106         }
    1107       }
    1108     }
    1109     // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    1110 
    1111     Rotate( numberofFinalStateNucleons, pseudoParticle[3].GetMomentum(),
    1112             modifiedOriginal, originalIncident, targetNucleus,
    1113             currentParticle, targetParticle, vec, vecLen );
    1114       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    1115     //
    1116     // add black track particles
    1117     // the total number of particles produced is restricted to 198
    1118     // this may have influence on very high energies
    1119     //
    1120     if( atomicWeight >= 1.5 )
     982        vec[i]->SetMomentum(vec[i]->GetMomentum() * (pp/pp1) );
     983      }
     984    }
     985  }
     986
     987  //    Rotate(numberofFinalStateNucleons, pseudoParticle[3].GetMomentum(),
     988  //           modifiedOriginal, originalIncident, targetNucleus,
     989  //           currentParticle, targetParticle, vec, vecLen );
     990
     991  // Add black track particles
     992  // the total number of particles produced is restricted to 198
     993  // this may have influence on very high energies
     994
     995  if( atomicWeight >= 1.5 )
     996  {
     997    // npnb is number of proton/neutron black track particles
     998    // ndta is the number of deuterons, tritons, and alphas produced
     999    // epnb is the kinetic energy available for proton/neutron black track
     1000    //    particles
     1001    // edta is the kinetic energy available for deuteron/triton/alpha particles
     1002
     1003    G4int npnb = 0;
     1004    G4int ndta = 0;
     1005     
     1006    G4double epnb, edta;
     1007    if (veryForward) {
     1008      epnb = targetNucleus.GetAnnihilationPNBlackTrackEnergy();
     1009      edta = targetNucleus.GetAnnihilationDTABlackTrackEnergy();
     1010    } else {
     1011      epnb = targetNucleus.GetPNBlackTrackEnergy();
     1012      edta = targetNucleus.GetDTABlackTrackEnergy();
     1013    }
     1014      /*
     1015      G4ReactionProduct* fudge = new G4ReactionProduct();
     1016      fudge->SetDefinition( aProton );
     1017      G4double TT = epnb + edta;
     1018      G4double MM = fudge->GetMass()/GeV;
     1019      fudge->SetTotalEnergy(MM*GeV + TT*GeV);
     1020      G4double pzz = std::sqrt(TT*(TT + 2.*MM));
     1021      fudge->SetMomentum(0.0, 0.0, pzz*GeV);
     1022      vec.SetElement(vecLen++, fudge);   
     1023      // G4cout << " Fudge = " << vec[vecLen-1]->GetKineticEnergy()/GeV
     1024                << G4endl;
     1025      */
     1026
     1027    const G4double pnCutOff = 0.001;
     1028    const G4double dtaCutOff = 0.001;
     1029    //    const G4double kineticMinimum = 1.e-6;
     1030    //    const G4double kineticFactor = -0.010;
     1031    //    G4double sprob = 0.0;  // sprob = probability of self-absorption in
     1032                           // heavy molecules
     1033    //  Not currently used (DHW 9 June 2008)  const G4double ekIncident = originalIncident->GetKineticEnergy()/GeV;
     1034    //    if (ekIncident >= 5.0) sprob = std::min(1.0, 0.6*std::log(ekIncident-4.0));
     1035    if (epnb > pnCutOff)
    11211036    {
    1122       // npnb is number of proton/neutron black track particles
    1123       // ndta is the number of deuterons, tritons, and alphas produced
    1124       // epnb is the kinetic energy available for proton/neutron black track particles
    1125       // edta is the kinetic energy available for deuteron/triton/alpha particles
    1126       //
    1127       G4int npnb = 0;
    1128       G4int ndta = 0;
    1129      
    1130       G4double epnb, edta;
    1131       if (veryForward) {
    1132         epnb = targetNucleus.GetAnnihilationPNBlackTrackEnergy();
    1133         edta = targetNucleus.GetAnnihilationDTABlackTrackEnergy();
    1134       } else {
    1135         epnb = targetNucleus.GetPNBlackTrackEnergy();
    1136         edta = targetNucleus.GetDTABlackTrackEnergy();
    1137       }
    1138 
    1139       const G4double pnCutOff = 0.001;
    1140       const G4double dtaCutOff = 0.001;
    1141       const G4double kineticMinimum = 1.e-6;
    1142       const G4double kineticFactor = -0.010;
    1143       G4double sprob = 0.0; // sprob = probability of self-absorption in heavy molecules
    1144       const G4double ekIncident = originalIncident->GetKineticEnergy()/GeV;
    1145       if( ekIncident >= 5.0 )sprob = std::min( 1.0, 0.6*std::log(ekIncident-4.0) );
    1146       if( epnb >= pnCutOff )
    1147       {
    1148         npnb = G4Poisson((1.5+1.25*numberofFinalStateNucleons)*epnb/(epnb+edta));
    1149         if( numberofFinalStateNucleons + npnb > atomicWeight )
    1150           npnb = G4int(atomicWeight+0.00001 - numberofFinalStateNucleons);
    1151         npnb = std::min( npnb, 127-vecLen );
    1152       }
    1153       if( edta >= dtaCutOff )
    1154       {
    1155         ndta = G4Poisson( (1.5+1.25*numberofFinalStateNucleons)*edta/(epnb+edta) );
    1156         ndta = std::min( ndta, 127-vecLen );
    1157       }
    1158       if (npnb == 0 && ndta == 0) npnb = 1;
    1159 
    1160       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    1161 
    1162       AddBlackTrackParticles(epnb, npnb, edta, ndta, sprob, kineticMinimum,
    1163                              kineticFactor, modifiedOriginal,
    1164                              PinNucleus, NinNucleus, targetNucleus,
    1165                              vec, vecLen);
    1166     }
     1037      npnb = G4Poisson((1.5+1.25*numberofFinalStateNucleons)*epnb/(epnb+edta));
     1038      if (numberofFinalStateNucleons + npnb > atomicWeight)
     1039        npnb = G4int(atomicWeight+0.00001 - numberofFinalStateNucleons);
     1040      npnb = std::min( npnb, 127-vecLen );
     1041    }
     1042    if( edta >= dtaCutOff )
     1043    {
     1044      ndta = G4Poisson((1.5+1.25*numberofFinalStateNucleons)*edta/(epnb+edta));
     1045      ndta = std::min( ndta, 127-vecLen );
     1046    }
     1047    if (npnb == 0 && ndta == 0) npnb = 1;
     1048
     1049    AddBlackTrackParticles(epnb, npnb, edta, ndta, modifiedOriginal,
     1050                           PinNucleus, NinNucleus, targetNucleus,
     1051                           vec, vecLen);
     1052  }
     1053
    11671054  //  if( centerofmassEnergy <= (4.0+G4UniformRand()) )
    11681055  //    MomentumCheck( modifiedOriginal, currentParticle, targetParticle,
     
    11711058  //  calculate time delay for nuclear reactions
    11721059  //
     1060
    11731061  if( (atomicWeight >= 1.5) && (atomicWeight <= 230.0) && (ekOriginal <= 0.2) )
    11741062    currentParticle.SetTOF(
     
    11791067
    11801068}
    1181  
     1069
     1070
     1071void G4RPGFragmentation::
     1072ReduceEnergiesOfSecondaries(G4int startingIndex,
     1073                            G4double& forwardKinetic,
     1074                            G4double& backwardKinetic,
     1075                            G4FastVector<G4ReactionProduct,256>& vec,
     1076                            G4int& vecLen,
     1077                            G4ReactionProduct& forwardPseudoParticle,
     1078                            G4ReactionProduct& backwardPseudoParticle,
     1079                            G4double& pt)
     1080{
     1081  // Reduce energies and pt of secondaries in order to maintain
     1082  // energy conservation
     1083
     1084  G4double totalEnergy;
     1085  G4double pp;
     1086  G4double pp1;
     1087  G4double px;
     1088  G4double py;
     1089  G4double mass;
     1090  G4ReactionProduct* pVec;
     1091  G4int i;
     1092
     1093  forwardKinetic = 0.0;
     1094  backwardKinetic = 0.0;
     1095  forwardPseudoParticle.SetZero();
     1096  backwardPseudoParticle.SetZero();
     1097
     1098  for (i = startingIndex; i < vecLen; i++) {
     1099    pVec = vec[i];
     1100    if (pVec->GetSide() != -3) {
     1101      mass = pVec->GetMass();
     1102      totalEnergy = 0.95*pVec->GetTotalEnergy() + 0.05*mass;
     1103      pVec->SetTotalEnergy(totalEnergy);
     1104      pp = std::sqrt( std::abs( totalEnergy*totalEnergy - mass*mass ) );
     1105      pp1 = pVec->GetMomentum().mag();
     1106      if (pp1 < 1.0e-6*GeV) {
     1107        G4ThreeVector iso = Isotropic(pp);
     1108        pVec->SetMomentum( iso.x(), iso.y(), iso.z() );
     1109      } else {
     1110        pVec->SetMomentum(pVec->GetMomentum() * (pp/pp1) );
     1111      }
     1112
     1113      px = pVec->GetMomentum().x();
     1114      py = pVec->GetMomentum().y();
     1115      pt = std::max(1.0, std::sqrt( px*px + py*py ) )/GeV;
     1116      if (pVec->GetSide() > 0) {
     1117        forwardKinetic += pVec->GetKineticEnergy()/GeV;
     1118        forwardPseudoParticle = forwardPseudoParticle + (*pVec);
     1119      } else {
     1120        backwardKinetic += pVec->GetKineticEnergy()/GeV;
     1121        backwardPseudoParticle = backwardPseudoParticle + (*pVec);
     1122      }
     1123    }
     1124  }
     1125}
     1126
    11821127 /* end of file */
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGInelastic.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGInelastic.cc,v 1.2 2007/08/15 20:38:25 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGInelastic.cc,v 1.6 2008/03/22 00:03:24 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929
     
    168168  }
    169169 
    170 void G4RPGInelastic::CalculateMomenta(
    171   G4FastVector<G4ReactionProduct,256> &vec,
    172   G4int &vecLen,
    173   const G4HadProjectile *originalIncident,
    174   const G4DynamicParticle *originalTarget,
    175   G4ReactionProduct &modifiedOriginal,
    176   G4Nucleus &targetNucleus,
    177   G4ReactionProduct &currentParticle,
    178   G4ReactionProduct &targetParticle,
    179   G4bool &incidentHasChanged,
    180   G4bool &targetHasChanged,
    181   G4bool quasiElastic )
     170void
     171G4RPGInelastic::CalculateMomenta(G4FastVector<G4ReactionProduct,256>& vec,
     172                                 G4int& vecLen,
     173                                 const G4HadProjectile* originalIncident,
     174                                 const G4DynamicParticle* originalTarget,
     175                                 G4ReactionProduct& modifiedOriginal,
     176                                 G4Nucleus& targetNucleus,
     177                                 G4ReactionProduct& currentParticle,
     178                                 G4ReactionProduct& targetParticle,
     179                                 G4bool& incidentHasChanged,
     180                                 G4bool& targetHasChanged,
     181                                 G4bool quasiElastic)
    182182{
    183183  cache = 0;
     
    186186  G4ReactionProduct leadingStrangeParticle;
    187187
    188   strangeProduction.ReactionStage(originalIncident, modifiedOriginal,
    189                                   incidentHasChanged, originalTarget,
    190                                   targetParticle, targetHasChanged,
    191                                   targetNucleus, currentParticle,
    192                                   vec, vecLen,
    193                                   false, leadingStrangeParticle);
     188  //  strangeProduction.ReactionStage(originalIncident, modifiedOriginal,
     189  //                                  incidentHasChanged, originalTarget,
     190  //                                  targetParticle, targetHasChanged,
     191  //                                  targetNucleus, currentParticle,
     192  //                                  vec, vecLen,
     193  //                              false, leadingStrangeParticle);
    194194
    195195  if( quasiElastic )
     
    266266  for (G4int i = 0; i < vecLen; i++) savevec.push_back(*vec[i]);
    267267
    268   if( annihilation || (vecLen >= 6) ||
    269       (modifiedOriginal.GetKineticEnergy()/GeV >= 1.0) &&
     268  // Call fragmentation code if
     269  //   1) there is annihilation, or
     270  //   2) there are more than 5 secondaries, or
     271  //   3) incident KE is > 1 GeV AND
     272  //        ( incident is a kaon AND rand < 0.5 OR twsup )
     273  //
     274
     275  if( annihilation || vecLen > 5 ||
     276      ( modifiedOriginal.GetKineticEnergy()/GeV >= 1.0 &&
     277
    270278      (((originalIncident->GetDefinition() == G4KaonPlus::KaonPlus() ||
    271279         originalIncident->GetDefinition() == G4KaonMinus::KaonMinus() ||
    272280         originalIncident->GetDefinition() == G4KaonZeroLong::KaonZeroLong() ||
    273281         originalIncident->GetDefinition() == G4KaonZeroShort::KaonZeroShort()) &&
    274         rand1 < 0.5) || rand2 > twsup[vecLen]) )
     282          rand1 < 0.5)
     283       || rand2 > twsup[vecLen]) ) )
    275284
    276285    finishedGenXPt =
     
    282291                                  leadFlag, leadingStrangeParticle);
    283292
    284   if( finishedGenXPt )
    285   {
    286     Rotate(vec, vecLen);
    287     return;
    288   }
     293  if (finishedGenXPt) return;
    289294
    290295  G4bool finishedTwoClu = false;
    291   if( modifiedOriginal.GetTotalMomentum()/MeV < 1.0 )
    292   {
    293     for(G4int i=0; i<vecLen; i++) delete vec[i];
     296
     297  if (modifiedOriginal.GetTotalMomentum() < 1.0) {
     298    for (G4int i = 0; i < vecLen; i++) delete vec[i];
    294299    vecLen = 0;
    295   }
    296   else
    297   {
     300
     301  } else {
    298302    // Occaisionally, GenerateXandPt will fail in the annihilation channel.
    299303    // Restore current, target and secondaries to pre-GenerateXandPt state
     
    313317    }
    314318
    315     pionSuppression.ReactionStage(originalIncident, modifiedOriginal,
    316                                   incidentHasChanged, originalTarget,
    317                                   targetParticle, targetHasChanged,
    318                                   targetNucleus, currentParticle,
    319                                   vec, vecLen,
    320                                   false, leadingStrangeParticle);
     319    // Big violations of energy conservation in this method - don't use
     320    //
     321    //    pionSuppression.ReactionStage(originalIncident, modifiedOriginal,
     322    //                                  incidentHasChanged, originalTarget,
     323    //                                  targetParticle, targetHasChanged,
     324    //                                  targetNucleus, currentParticle,
     325    //                                  vec, vecLen,
     326    //                                  false, leadingStrangeParticle);
    321327
    322328    try
     
    337343  }
    338344
    339   if( finishedTwoClu )
    340   {
    341     Rotate(vec, vecLen);
    342     return;
    343   }
     345  if (finishedTwoClu) return;
    344346
    345347  twoBody.ReactionStage(originalIncident, modifiedOriginal,
     
    351353}
    352354
    353  
     355/*
    354356 void G4RPGInelastic::
    355357 Rotate(G4FastVector<G4ReactionProduct,256> &vec, G4int &vecLen)
     
    365367   }
    366368 }     
     369*/
    367370
    368371void
    369 G4RPGInelastic::SetUpChange(G4FastVector<G4ReactionProduct,256> &vec,
    370                             G4int &vecLen,
    371                             G4ReactionProduct &currentParticle,
    372                             G4ReactionProduct &targetParticle,
    373                             G4bool &incidentHasChanged )
     372G4RPGInelastic::SetUpChange(G4FastVector<G4ReactionProduct,256>& vec,
     373                            G4int& vecLen,
     374                            G4ReactionProduct& currentParticle,
     375                            G4ReactionProduct& targetParticle,
     376                            G4bool& incidentHasChanged )
    374377{
    375378  theParticleChange.Clear();
    376   G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
    377   G4ParticleDefinition *aKaonZS = G4KaonZeroShort::KaonZeroShort();
     379  G4ParticleDefinition* aKaonZL = G4KaonZeroLong::KaonZeroLong();
     380  G4ParticleDefinition* aKaonZS = G4KaonZeroShort::KaonZeroShort();
    378381  G4int i;
    379   if( currentParticle.GetDefinition() == aKaonZL )
    380   {
    381     if( G4UniformRand() <= 0.5 )
    382     {
    383       currentParticle.SetDefinition( aKaonZS );
     382
     383  if (currentParticle.GetDefinition() == particleDef[k0]) {
     384    if (G4UniformRand() < 0.5) {
     385      currentParticle.SetDefinitionAndUpdateE(aKaonZL);
    384386      incidentHasChanged = true;
    385     }
    386   }
    387   else if( currentParticle.GetDefinition() == aKaonZS )
    388   {
    389     if( G4UniformRand() > 0.5 )
    390     {
    391       currentParticle.SetDefinition( aKaonZL );
     387    } else {
     388      currentParticle.SetDefinitionAndUpdateE(aKaonZS);
     389    }
     390  } else if (currentParticle.GetDefinition() == particleDef[k0b]) {
     391    if (G4UniformRand() < 0.5) {
     392      currentParticle.SetDefinitionAndUpdateE(aKaonZL);
     393    } else {
     394      currentParticle.SetDefinitionAndUpdateE(aKaonZS);
    392395      incidentHasChanged = true;
    393396    }
    394397  }
    395398
    396   if( targetParticle.GetDefinition() == aKaonZL )
    397   {
    398     if( G4UniformRand() <= 0.5 )targetParticle.SetDefinition( aKaonZS );
    399   }
    400   else if( targetParticle.GetDefinition() == aKaonZS )
    401   {
    402     if( G4UniformRand() > 0.5 )targetParticle.SetDefinition( aKaonZL );
    403   }
    404   for( i=0; i<vecLen; ++i )
    405   {
    406     if( vec[i]->GetDefinition() == aKaonZL )
    407     {
    408       if( G4UniformRand() <= 0.5 )vec[i]->SetDefinition( aKaonZS );
    409     }
    410     else if( vec[i]->GetDefinition() == aKaonZS )
    411     {
    412       if( G4UniformRand() > 0.5 )vec[i]->SetDefinition( aKaonZL );
    413     }
    414   }
    415 
    416   if( incidentHasChanged )
    417   {
     399  if (targetParticle.GetDefinition() == particleDef[k0] ||
     400      targetParticle.GetDefinition() == particleDef[k0b] ) {
     401    if (G4UniformRand() < 0.5) {
     402      targetParticle.SetDefinitionAndUpdateE(aKaonZL);
     403    } else {
     404      targetParticle.SetDefinitionAndUpdateE(aKaonZS);
     405    }
     406  }
     407
     408  for (i = 0; i < vecLen; ++i) {
     409    if (vec[i]->GetDefinition() == particleDef[k0] ||
     410        vec[i]->GetDefinition() == particleDef[k0b] ) {
     411      if (G4UniformRand() < 0.5) {
     412        vec[i]->SetDefinitionAndUpdateE(aKaonZL);
     413      } else {
     414        vec[i]->SetDefinitionAndUpdateE(aKaonZS);
     415      }
     416    }
     417  }
     418
     419  if (incidentHasChanged) {
    418420    G4DynamicParticle* p0 = new G4DynamicParticle;
    419     p0->SetDefinition( currentParticle.GetDefinition() );
    420     p0->SetMomentum( currentParticle.GetMomentum() );
     421    p0->SetDefinition(currentParticle.GetDefinition() );
     422    p0->SetMomentum(currentParticle.GetMomentum() );
    421423    theParticleChange.AddSecondary( p0 );
    422424    theParticleChange.SetStatusChange( stopAndKill );
    423425    theParticleChange.SetEnergyChange( 0.0 );
    424   }
    425   else
    426   {
     426
     427  } else {
    427428    G4double p = currentParticle.GetMomentum().mag()/MeV;
    428429    G4ThreeVector m = currentParticle.GetMomentum();
    429     if( p > DBL_MIN )
     430    if (p > DBL_MIN)
    430431      theParticleChange.SetMomentumChange( m.x()/p, m.y()/p, m.z()/p );
    431432    else
     
    437438  }
    438439
    439   if( targetParticle.GetMass() > 0.0 )  // Tgt particle can be eliminated in TwoBody
     440  if (targetParticle.GetMass() > 0.0)  // Tgt particle can be eliminated in TwoBody
    440441  {
    441442    G4ThreeVector momentum = targetParticle.GetMomentum();
     
    455456
    456457  G4DynamicParticle* p;
    457   for( i=0; i<vecLen; ++i )
    458   {
     458  for (i = 0; i < vecLen; ++i) {
    459459    G4double secKE = vec[i]->GetKineticEnergy();
    460460    G4ThreeVector momentum = vec[i]->GetMomentum();
     
    470470  }
    471471}
    472  
     472
     473
     474std::pair<G4int, G4double>
     475G4RPGInelastic::interpolateEnergy(G4double e) const
     476{
     477  G4int index = 29;
     478  G4double fraction = 0.0;
     479
     480  for (G4int i = 1; i < 30; i++) {
     481    if (e < energyScale[i]) {
     482      index = i-1;
     483      fraction = (e - energyScale[index]) / (energyScale[i] - energyScale[index]);
     484      break;
     485    }
     486  }
     487  return std::pair<G4int, G4double>(index, fraction);
     488}
     489
     490
     491G4int
     492G4RPGInelastic::sampleFlat(std::vector<G4double> sigma) const
     493{
     494  G4int i;
     495  G4double sum(0.);
     496  for (i = 0; i < G4int(sigma.size()); i++) sum += sigma[i];
     497
     498  G4double fsum = sum*G4UniformRand();
     499  G4double partialSum = 0.0;
     500  G4int channel = 0;
     501
     502  for (i = 0; i < G4int(sigma.size()); i++) {
     503    partialSum += sigma[i];
     504    if (fsum < partialSum) {
     505      channel = i;
     506      break;
     507    }
     508  }
     509
     510  return channel;
     511}
     512
     513
     514void G4RPGInelastic::CheckQnums(G4FastVector<G4ReactionProduct,256> &vec,
     515                                G4int &vecLen,
     516                                G4ReactionProduct &currentParticle,
     517                                G4ReactionProduct &targetParticle,
     518                                G4double Q, G4double B, G4double S)
     519{
     520  G4ParticleDefinition* projDef = currentParticle.GetDefinition();
     521  G4ParticleDefinition* targDef = targetParticle.GetDefinition();
     522  G4double chargeSum = projDef->GetPDGCharge() + targDef->GetPDGCharge();
     523  G4double baryonSum = projDef->GetBaryonNumber() + targDef->GetBaryonNumber();
     524  G4double strangenessSum = projDef->GetQuarkContent(3) -
     525                            projDef->GetAntiQuarkContent(3) +
     526                            targDef->GetQuarkContent(3) -
     527                            targDef->GetAntiQuarkContent(3);
     528
     529  G4ParticleDefinition* secDef = 0;
     530  for (G4int i = 0; i < vecLen; i++) {
     531    secDef = vec[i]->GetDefinition();
     532    chargeSum += secDef->GetPDGCharge();
     533    baryonSum += secDef->GetBaryonNumber();
     534    strangenessSum += secDef->GetQuarkContent(3)
     535                    - secDef->GetAntiQuarkContent(3);
     536  }
     537
     538  G4bool OK = true;
     539  if (chargeSum != Q) {
     540    G4cout << " Charge not conserved " << G4endl;
     541    OK = false;
     542  }
     543  if (baryonSum != B) {
     544    G4cout << " Baryon number not conserved " << G4endl;
     545    OK = false;
     546  }
     547  if (strangenessSum != S) {
     548    G4cout << " Strangeness not conserved " << G4endl;
     549    OK = false;
     550  }
     551
     552  if (!OK) {
     553    G4cout << " projectile: " << projDef->GetParticleName()
     554           << "  target: " << targDef->GetParticleName() << G4endl;
     555    for (G4int i = 0; i < vecLen; i++) {
     556      secDef = vec[i]->GetDefinition();
     557      G4cout << secDef->GetParticleName() << " " ;
     558    }
     559    G4cout << G4endl;
     560  }
     561
     562}
     563
     564
     565const G4double G4RPGInelastic::energyScale[30] = {
     566  0.0,  0.01, 0.013, 0.018, 0.024, 0.032, 0.042, 0.056, 0.075, 0.1,
     567  0.13, 0.18, 0.24,  0.32,  0.42,  0.56,  0.75,  1.0,   1.3,   1.8,
     568  2.4,  3.2,  4.2,   5.6,   7.5,   10.0,  13.0,  18.0,  24.0, 32.0 };
     569
     570G4ParticleDefinition* p0 = G4PionZero::PionZero();
     571G4ParticleDefinition* p1 = G4PionPlus::PionPlus();
     572G4ParticleDefinition* p2 = G4PionMinus::PionMinus();
     573G4ParticleDefinition* p3 = G4KaonPlus::KaonPlus();
     574G4ParticleDefinition* p4 = G4KaonMinus::KaonMinus();
     575G4ParticleDefinition* p5 = G4KaonZero::KaonZero();
     576G4ParticleDefinition* p6 = G4AntiKaonZero::AntiKaonZero();
     577G4ParticleDefinition* p7 = G4Proton::Proton();
     578G4ParticleDefinition* p8 = G4Neutron::Neutron();
     579G4ParticleDefinition* p9 = G4Lambda::Lambda();
     580G4ParticleDefinition* p10 = G4SigmaPlus::SigmaPlus();
     581G4ParticleDefinition* p11 = G4SigmaZero::SigmaZero();
     582G4ParticleDefinition* p12 = G4SigmaMinus::SigmaMinus();
     583G4ParticleDefinition* p13 = G4XiZero::XiZero();
     584G4ParticleDefinition* p14 = G4XiMinus::XiMinus();
     585G4ParticleDefinition* p15 = G4OmegaMinus::OmegaMinus();
     586G4ParticleDefinition* p16 = G4AntiProton::AntiProton();
     587G4ParticleDefinition* p17 = G4AntiNeutron::AntiNeutron();
     588
     589G4ParticleDefinition* G4RPGInelastic::particleDef[18] = {
     590  p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14,
     591  p15, p16, p17 };
     592
    473593/* end of file */
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGKMinusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGKMinusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGKPlusInelastic.cc

    r819 r962  
    2626//
    2727// $Id: G4RPGKPlusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    28 // GEANT4 tag $Name: $
     28// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2929//
    3030 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGKZeroInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGKZeroInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGLambdaInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGLambdaInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGNeutronInelastic.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGNeutronInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGNeutronInelastic.cc,v 1.4 2008/05/05 21:21:55 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
    3030#include "G4RPGNeutronInelastic.hh"
    3131#include "Randomize.hh"
    32 #include "G4Electron.hh"
    33 // #include "DumpFrame.hh"
    34 
    35  G4HadFinalState *
    36   G4RPGNeutronInelastic::ApplyYourself( const G4HadProjectile &aTrack,
    37                                        G4Nucleus &targetNucleus )
    38   {
    39     theParticleChange.Clear();
    40     const G4HadProjectile *originalIncident = &aTrack;
    41     //
    42     // create the target particle
    43     //
    44     G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
    45    
    46     if( verboseLevel > 1 )
    47     {
    48       const G4Material *targetMaterial = aTrack.GetMaterial();
    49       G4cout << "G4RPGNeutronInelastic::ApplyYourself called" << G4endl;
    50       G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
    51       G4cout << "target material = " << targetMaterial->GetName() << ", ";
    52       G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
    53            << G4endl;
    54     }
    55 /* not true, for example for Fe56, etc..
    56     if( originalIncident->GetKineticEnergy()/MeV < 0.000001 )
    57       throw G4HadronicException(__FILE__, __LINE__, "G4RPGNeutronInelastic: should be capture process!");
    58     if( originalIncident->Get4Momentum().vect().mag()/MeV < 0.000001 )
    59       throw G4HadronicException(__FILE__, __LINE__, "G4RPGNeutronInelastic: should be capture process!");
    60 */
    61    
    62     G4ReactionProduct modifiedOriginal;
    63     modifiedOriginal = *originalIncident;
    64     G4ReactionProduct targetParticle;
    65     targetParticle = *originalTarget;
    66     if( originalIncident->GetKineticEnergy()/GeV < 0.01 + 2.*G4UniformRand()/9. )
    67     {
    68       SlowNeutron( originalIncident, modifiedOriginal, targetParticle, targetNucleus );
    69       delete originalTarget;
    70       return &theParticleChange;
    71     }
    72     //
    73     // Fermi motion and evaporation
    74     // As of Geant3, the Fermi energy calculation had not been Done
    75     //
    76     G4double ek = originalIncident->GetKineticEnergy()/MeV;
    77     G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
    78    
    79     G4double tkin = targetNucleus.Cinema( ek );
    80     ek += tkin;
    81     modifiedOriginal.SetKineticEnergy( ek*MeV );
    82     G4double et = ek + amas;
    83     G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
    84     G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
    85     if( pp > 0.0 )
    86     {
    87       G4ThreeVector momentum = modifiedOriginal.GetMomentum();
    88       modifiedOriginal.SetMomentum( momentum * (p/pp) );
    89     }
    90     //
    91     // calculate black track energies
    92     //
    93     tkin = targetNucleus.EvaporationEffects( ek );
    94     ek -= tkin;
    95     modifiedOriginal.SetKineticEnergy( ek*MeV );
    96     et = ek + amas;
    97     p = std::sqrt( std::abs((et-amas)*(et+amas)) );
    98     pp = modifiedOriginal.GetMomentum().mag()/MeV;
    99     if( pp > 0.0 )
    100     {
    101       G4ThreeVector momentum = modifiedOriginal.GetMomentum();
    102       modifiedOriginal.SetMomentum( momentum * (p/pp) );
    103     }
    104     const G4double cutOff = 0.1;
    105     if( modifiedOriginal.GetKineticEnergy()/MeV <= cutOff )
    106     {
    107       SlowNeutron( originalIncident, modifiedOriginal, targetParticle, targetNucleus );
    108       delete originalTarget;
    109       return &theParticleChange;
    110     }
    111     G4ReactionProduct currentParticle = modifiedOriginal;
    112     currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
    113     targetParticle.SetSide( -1 );  // target always goes in backward hemisphere
    114     G4bool incidentHasChanged = false;
    115     G4bool targetHasChanged = false;
    116     G4bool quasiElastic = false;
    117     G4FastVector<G4ReactionProduct,256> vec;  // vec will contain the secondary particles
    118     G4int vecLen = 0;
    119     vec.Initialize( 0 );
    120    
    121     Cascade( vec, vecLen,
    122              originalIncident, currentParticle, targetParticle,
    123              incidentHasChanged, targetHasChanged, quasiElastic );
    124    
    125     CalculateMomenta( vec, vecLen,
    126                       originalIncident, originalTarget, modifiedOriginal,
    127                       targetNucleus, currentParticle, targetParticle,
    128                       incidentHasChanged, targetHasChanged, quasiElastic );
    129    
    130     SetUpChange( vec, vecLen,
    131                  currentParticle, targetParticle,
    132                  incidentHasChanged );
    133    
     32
     33
     34G4HadFinalState*
     35G4RPGNeutronInelastic::ApplyYourself(const G4HadProjectile& aTrack,
     36                                      G4Nucleus& targetNucleus)
     37{
     38  theParticleChange.Clear();
     39  const G4HadProjectile* originalIncident = &aTrack;
     40
     41  //
     42  // create the target particle
     43  //
     44  G4DynamicParticle* originalTarget = targetNucleus.ReturnTargetParticle();
     45 
     46  G4ReactionProduct modifiedOriginal;
     47  modifiedOriginal = *originalIncident;
     48  G4ReactionProduct targetParticle;
     49  targetParticle = *originalTarget;
     50  if( originalIncident->GetKineticEnergy()/GeV < 0.01 + 2.*G4UniformRand()/9. )
     51  {
     52    SlowNeutron(originalIncident,modifiedOriginal,targetParticle,targetNucleus );
    13453    delete originalTarget;
    13554    return &theParticleChange;
    13655  }
    137  
    138  void
    139   G4RPGNeutronInelastic::SlowNeutron(
    140    const G4HadProjectile *originalIncident,
    141    G4ReactionProduct &modifiedOriginal,
    142    G4ReactionProduct &targetParticle,
    143    G4Nucleus &targetNucleus )
    144   {       
    145     const G4double A = targetNucleus.GetN();    // atomic weight
    146     const G4double Z = targetNucleus.GetZ();    // atomic number
    147    
    148     G4double currentKinetic = modifiedOriginal.GetKineticEnergy()/MeV;
    149     G4double currentMass = modifiedOriginal.GetMass()/MeV;
    150     if( A < 1.5 )   // Hydrogen
     56
     57  //
     58  // Fermi motion and evaporation
     59  // As of Geant3, the Fermi energy calculation had not been Done
     60  //
     61  G4double ek = originalIncident->GetKineticEnergy()/MeV;
     62  G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
     63   
     64  G4double tkin = targetNucleus.Cinema( ek );
     65  ek += tkin;
     66  modifiedOriginal.SetKineticEnergy( ek*MeV );
     67  G4double et = ek + amas;
     68  G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
     69  G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
     70  if( pp > 0.0 )
     71  {
     72    G4ThreeVector momentum = modifiedOriginal.GetMomentum();
     73    modifiedOriginal.SetMomentum( momentum * (p/pp) );
     74  }
     75  //
     76  // calculate black track energies
     77  //
     78  tkin = targetNucleus.EvaporationEffects( ek );
     79  ek -= tkin;
     80  modifiedOriginal.SetKineticEnergy(ek);
     81  et = ek + amas;
     82  p = std::sqrt( std::abs((et-amas)*(et+amas)) );
     83  pp = modifiedOriginal.GetMomentum().mag();
     84  if( pp > 0.0 )
     85  {
     86    G4ThreeVector momentum = modifiedOriginal.GetMomentum();
     87    modifiedOriginal.SetMomentum( momentum * (p/pp) );
     88  }
     89  const G4double cutOff = 0.1;
     90  if( modifiedOriginal.GetKineticEnergy()/MeV <= cutOff )
     91  {
     92    SlowNeutron( originalIncident, modifiedOriginal, targetParticle, targetNucleus );
     93    delete originalTarget;
     94    return &theParticleChange;
     95  }
     96
     97  G4ReactionProduct currentParticle = modifiedOriginal;
     98  currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
     99  targetParticle.SetSide( -1 );  // target always goes in backward hemisphere
     100  G4bool incidentHasChanged = false;
     101  G4bool targetHasChanged = false;
     102  G4bool quasiElastic = false;
     103  G4FastVector<G4ReactionProduct,256> vec;  // vec will contain sec. particles
     104  G4int vecLen = 0;
     105  vec.Initialize( 0 );
     106   
     107  InitialCollision(vec, vecLen, currentParticle, targetParticle,
     108                   incidentHasChanged, targetHasChanged);
     109   
     110  CalculateMomenta(vec, vecLen,
     111                   originalIncident, originalTarget, modifiedOriginal,
     112                   targetNucleus, currentParticle, targetParticle,
     113                   incidentHasChanged, targetHasChanged, quasiElastic);
     114   
     115  SetUpChange(vec, vecLen,
     116              currentParticle, targetParticle,
     117              incidentHasChanged);
     118   
     119  delete originalTarget;
     120  return &theParticleChange;
     121}
     122 
     123void
     124G4RPGNeutronInelastic::SlowNeutron(const G4HadProjectile* originalIncident,
     125                              G4ReactionProduct& modifiedOriginal,
     126                              G4ReactionProduct& targetParticle,
     127                              G4Nucleus& targetNucleus)
     128{       
     129  const G4double A = targetNucleus.GetN();    // atomic weight
     130  const G4double Z = targetNucleus.GetZ();    // atomic number
     131   
     132  G4double currentKinetic = modifiedOriginal.GetKineticEnergy()/MeV;
     133  G4double currentMass = modifiedOriginal.GetMass()/MeV;
     134  if( A < 1.5 )   // Hydrogen
     135  {
     136    //
     137    // very simple simulation of scattering angle and energy
     138    // nonrelativistic approximation with isotropic angular
     139    // distribution in the cms system
     140    //
     141    G4double cost1, eka = 0.0;
     142    while (eka <= 0.0)
    151143    {
    152       //
    153       // very simple simulation of scattering angle and energy
    154       // nonrelativistic approximation with isotropic angular
    155       // distribution in the cms system
    156       //
    157       G4double cost1, eka = 0.0;
    158       while (eka <= 0.0)
    159       {
    160         cost1 = -1.0 + 2.0*G4UniformRand();
    161         eka = 1.0 + 2.0*cost1*A + A*A;
     144      cost1 = -1.0 + 2.0*G4UniformRand();
     145      eka = 1.0 + 2.0*cost1*A + A*A;
     146    }
     147    G4double cost = std::min( 1.0, std::max( -1.0, (A*cost1+1.0)/std::sqrt(eka) ) );
     148    eka /= (1.0+A)*(1.0+A);
     149    G4double ek = currentKinetic*MeV/GeV;
     150    G4double amas = currentMass*MeV/GeV;
     151    ek *= eka;
     152    G4double en = ek + amas;
     153    G4double p = std::sqrt(std::abs(en*en-amas*amas));
     154    G4double sint = std::sqrt(std::abs(1.0-cost*cost));
     155    G4double phi = G4UniformRand()*twopi;
     156    G4double px = sint*std::sin(phi);
     157    G4double py = sint*std::cos(phi);
     158    G4double pz = cost;
     159    targetParticle.SetMomentum( px*GeV, py*GeV, pz*GeV );
     160    G4double pxO = originalIncident->Get4Momentum().x()/GeV;
     161    G4double pyO = originalIncident->Get4Momentum().y()/GeV;
     162    G4double pzO = originalIncident->Get4Momentum().z()/GeV;
     163    G4double ptO = pxO*pxO + pyO+pyO;
     164    if( ptO > 0.0 )
     165    {
     166      G4double pO = std::sqrt(pxO*pxO+pyO*pyO+pzO*pzO);
     167      cost = pzO/pO;
     168      sint = 0.5*(std::sqrt(std::abs((1.0-cost)*(1.0+cost)))+std::sqrt(ptO)/pO);
     169      G4double ph = pi/2.0;
     170      if( pyO < 0.0 )ph = ph*1.5;
     171      if( std::abs(pxO) > 0.000001 )ph = std::atan2(pyO,pxO);
     172      G4double cosp = std::cos(ph);
     173      G4double sinp = std::sin(ph);
     174      px = cost*cosp*px - sinp*py+sint*cosp*pz;
     175      py = cost*sinp*px + cosp*py+sint*sinp*pz;
     176      pz = -sint*px     + cost*pz;
     177    }
     178    else
     179    {
     180      if( pz < 0.0 )pz *= -1.0;
     181    }
     182    G4double pu = std::sqrt(px*px+py*py+pz*pz);
     183    modifiedOriginal.SetMomentum( targetParticle.GetMomentum() * (p/pu) );
     184    modifiedOriginal.SetKineticEnergy( ek*GeV );
     185     
     186    targetParticle.SetMomentum(
     187     originalIncident->Get4Momentum().vect() - modifiedOriginal.GetMomentum() );
     188    G4double pp = targetParticle.GetMomentum().mag();
     189    G4double tarmas = targetParticle.GetMass();
     190    targetParticle.SetTotalEnergy( std::sqrt( pp*pp + tarmas*tarmas ) );
     191     
     192    theParticleChange.SetEnergyChange( modifiedOriginal.GetKineticEnergy() );
     193    G4DynamicParticle *pd = new G4DynamicParticle;
     194    pd->SetDefinition( targetParticle.GetDefinition() );
     195    pd->SetMomentum( targetParticle.GetMomentum() );
     196    theParticleChange.AddSecondary( pd );
     197    return;
     198  }
     199
     200  G4FastVector<G4ReactionProduct,4> vec;  // vec will contain the secondary particles
     201  G4int vecLen = 0;
     202  vec.Initialize( 0 );
     203   
     204  G4double theAtomicMass = targetNucleus.AtomicMass( A, Z );
     205  G4double massVec[9];
     206  massVec[0] = targetNucleus.AtomicMass( A+1.0, Z     );
     207  massVec[1] = theAtomicMass;
     208  massVec[2] = 0.;
     209  if (Z > 1.0) massVec[2] = targetNucleus.AtomicMass(A, Z-1.0);
     210  massVec[3] = 0.;
     211  if (Z > 1.0 && A > 1.0) massVec[3] = targetNucleus.AtomicMass(A-1.0, Z-1.0 );
     212  massVec[4] = 0.;
     213  if (Z > 1.0 && A > 2.0 && A-2.0 > Z-1.0)
     214    massVec[4] = targetNucleus.AtomicMass( A-2.0, Z-1.0 );
     215  massVec[5] = 0.;
     216  if (Z > 2.0 && A > 3.0 && A-3.0 > Z-2.0)
     217    massVec[5] = targetNucleus.AtomicMass( A-3.0, Z-2.0 );
     218  massVec[6] = 0.;
     219  if (A > 1.0 && A-1.0 > Z) massVec[6] = targetNucleus.AtomicMass(A-1.0, Z);
     220  massVec[7] = massVec[3];
     221  massVec[8] = 0.;
     222  if (Z > 2.0 && A > 1.0) massVec[8] = targetNucleus.AtomicMass( A-1.0,Z-2.0 );
     223   
     224  twoBody.NuclearReaction(vec, vecLen, originalIncident,
     225                          targetNucleus, theAtomicMass, massVec );
     226   
     227  theParticleChange.SetStatusChange( stopAndKill );
     228  theParticleChange.SetEnergyChange( 0.0 );
     229   
     230  G4DynamicParticle* pd;
     231  for( G4int i=0; i<vecLen; ++i ) {
     232    pd = new G4DynamicParticle();
     233    pd->SetDefinition( vec[i]->GetDefinition() );
     234    pd->SetMomentum( vec[i]->GetMomentum() );
     235    theParticleChange.AddSecondary( pd );
     236    delete vec[i];
     237  }
     238}
     239
     240
     241// Initial Collision
     242//   selects the particle types arising from the initial collision of
     243//   the neutron and target nucleon.  Secondaries are assigned to
     244//   forward and backward reaction hemispheres, but final state energies
     245//   and momenta are not calculated here.
     246
     247void
     248G4RPGNeutronInelastic::InitialCollision(G4FastVector<G4ReactionProduct,256>& vec,
     249                                   G4int& vecLen,
     250                                   G4ReactionProduct& currentParticle,
     251                                   G4ReactionProduct& targetParticle,
     252                                   G4bool& incidentHasChanged,
     253                                   G4bool& targetHasChanged)
     254{
     255  G4double KE = currentParticle.GetKineticEnergy()/GeV;
     256 
     257  G4int mult;
     258  G4int partType;
     259  std::vector<G4int> fsTypes;
     260  G4int part1;
     261  G4int part2;
     262 
     263  G4double testCharge;
     264  G4double testBaryon;
     265  G4double testStrange;
     266 
     267  // Get particle types according to incident and target types
     268
     269  if (targetParticle.GetDefinition() == particleDef[neu]) {
     270    mult = GetMultiplicityT1(KE);
     271    fsTypes = GetFSPartTypesForNN(mult, KE);
     272
     273    part1 = fsTypes[0];
     274    part2 = fsTypes[1];
     275    currentParticle.SetDefinition(particleDef[part1]);
     276    targetParticle.SetDefinition(particleDef[part2]);
     277    if (part1 == pro) {     
     278      if (part2 == neu) {
     279        if (G4UniformRand() > 0.5) {
     280          incidentHasChanged = true;
     281        } else {
     282          targetHasChanged = true;
     283          currentParticle.SetDefinition(particleDef[part2]);
     284          targetParticle.SetDefinition(particleDef[part1]);
     285        }
     286      } else {
     287        targetHasChanged = true;
     288        incidentHasChanged = true;
    162289      }
    163       G4double cost = std::min( 1.0, std::max( -1.0, (A*cost1+1.0)/std::sqrt(eka) ) );
    164       eka /= (1.0+A)*(1.0+A);
    165       G4double ek = currentKinetic*MeV/GeV;
    166       G4double amas = currentMass*MeV/GeV;
    167       ek *= eka;
    168       G4double en = ek + amas;
    169       G4double p = std::sqrt(std::abs(en*en-amas*amas));
    170       G4double sint = std::sqrt(std::abs(1.0-cost*cost));
    171       G4double phi = G4UniformRand()*twopi;
    172       G4double px = sint*std::sin(phi);
    173       G4double py = sint*std::cos(phi);
    174       G4double pz = cost;
    175       targetParticle.SetMomentum( px*GeV, py*GeV, pz*GeV );
    176       G4double pxO = originalIncident->Get4Momentum().x()/GeV;
    177       G4double pyO = originalIncident->Get4Momentum().y()/GeV;
    178       G4double pzO = originalIncident->Get4Momentum().z()/GeV;
    179       G4double ptO = pxO*pxO + pyO+pyO;
    180       if( ptO > 0.0 )
    181       {
    182         G4double pO = std::sqrt(pxO*pxO+pyO*pyO+pzO*pzO);
    183         cost = pzO/pO;
    184         sint = 0.5*(std::sqrt(std::abs((1.0-cost)*(1.0+cost)))+std::sqrt(ptO)/pO);
    185         G4double ph = pi/2.0;
    186         if( pyO < 0.0 )ph = ph*1.5;
    187         if( std::abs(pxO) > 0.000001 )ph = std::atan2(pyO,pxO);
    188         G4double cosp = std::cos(ph);
    189         G4double sinp = std::sin(ph);
    190         px = cost*cosp*px - sinp*py+sint*cosp*pz;
    191         py = cost*sinp*px + cosp*py+sint*sinp*pz;
    192         pz = -sint*px     + cost*pz;
     290
     291    } else { // neutron
     292      if (part2 > neu && part2 < xi0) targetHasChanged = true;
     293    }
     294
     295    testCharge = 0.0;
     296    testBaryon = 2.0;
     297    testStrange = 0.0;
     298
     299  } else { // target was a proton
     300    mult = GetMultiplicityT0(KE);
     301    fsTypes = GetFSPartTypesForNP(mult, KE);
     302 
     303    part1 = fsTypes[0];
     304    part2 = fsTypes[1];
     305    currentParticle.SetDefinition(particleDef[part1]);
     306    targetParticle.SetDefinition(particleDef[part2]);
     307    if (part1 == pro) {
     308      if (part2 == pro) {
     309        incidentHasChanged = true;
     310      } else if (part2 == neu) {
     311        if (G4UniformRand() > 0.5) {
     312          incidentHasChanged = true;
     313          targetHasChanged = true;
     314        } else {
     315          currentParticle.SetDefinition(particleDef[part2]);
     316          targetParticle.SetDefinition(particleDef[part1]);
     317        }
     318       
     319      } else if (part2 > neu && part2 < xi0) {
     320        incidentHasChanged = true;
     321        targetHasChanged = true;
    193322      }
    194       else
    195       {
    196         if( pz < 0.0 )pz *= -1.0;
    197       }
    198       G4double pu = std::sqrt(px*px+py*py+pz*pz);
    199       modifiedOriginal.SetMomentum( targetParticle.GetMomentum() * (p/pu) );
    200       modifiedOriginal.SetKineticEnergy( ek*GeV );
    201      
    202       targetParticle.SetMomentum(
    203        originalIncident->Get4Momentum().vect() - modifiedOriginal.GetMomentum() );
    204       G4double pp = targetParticle.GetMomentum().mag();
    205       G4double tarmas = targetParticle.GetMass();
    206       targetParticle.SetTotalEnergy( std::sqrt( pp*pp + tarmas*tarmas ) );
    207      
    208       theParticleChange.SetEnergyChange( modifiedOriginal.GetKineticEnergy() );
    209       G4DynamicParticle *pd = new G4DynamicParticle;
    210       pd->SetDefinition( targetParticle.GetDefinition() );
    211       pd->SetMomentum( targetParticle.GetMomentum() );
    212       theParticleChange.AddSecondary( pd );
    213       return;
    214     }
    215     G4FastVector<G4ReactionProduct,4> vec;  // vec will contain the secondary particles
    216     G4int vecLen = 0;
    217     vec.Initialize( 0 );
    218    
    219     G4double theAtomicMass = targetNucleus.AtomicMass( A, Z );
    220     G4double massVec[9];
    221     massVec[0] = targetNucleus.AtomicMass( A+1.0, Z     );
    222     massVec[1] = theAtomicMass;
    223     massVec[2] = 0.;
    224     if (Z > 1.0)
    225         massVec[2] = targetNucleus.AtomicMass( A    , Z-1.0 );
    226     massVec[3] = 0.;
    227     if (Z > 1.0 && A > 1.0)
    228         massVec[3] = targetNucleus.AtomicMass( A-1.0, Z-1.0 );
    229     massVec[4] = 0.;
    230     if (Z > 1.0 && A > 2.0 && A-2.0 > Z-1.0)
    231         massVec[4] = targetNucleus.AtomicMass( A-2.0, Z-1.0 );
    232     massVec[5] = 0.;
    233     if (Z > 2.0 && A > 3.0 && A-3.0 > Z-2.0)
    234         massVec[5] = targetNucleus.AtomicMass( A-3.0, Z-2.0 );
    235     massVec[6] = 0.;
    236     if (A > 1.0 && A-1.0 > Z)
    237         massVec[6] = targetNucleus.AtomicMass( A-1.0, Z     );
    238     massVec[7] = massVec[3];
    239     massVec[8] = 0.;
    240     if (Z > 2.0 && A > 1.0)
    241         massVec[8] = targetNucleus.AtomicMass( A-1.0, Z-2.0 );
    242    
    243     twoBody.NuclearReaction(vec, vecLen, originalIncident,
    244                             targetNucleus, theAtomicMass, massVec );
    245    
    246     theParticleChange.SetStatusChange( stopAndKill );
    247     theParticleChange.SetEnergyChange( 0.0 );
    248    
    249     G4DynamicParticle * pd;
    250     for( G4int i=0; i<vecLen; ++i )
    251     {
    252       pd = new G4DynamicParticle();
    253       pd->SetDefinition( vec[i]->GetDefinition() );
    254       pd->SetMomentum( vec[i]->GetMomentum() );
    255       theParticleChange.AddSecondary( pd );
    256       delete vec[i];
    257     }
    258   }
    259  
    260  void
    261   G4RPGNeutronInelastic::Cascade(
    262    G4FastVector<G4ReactionProduct,256> &vec,
    263    G4int& vecLen,
    264    const G4HadProjectile *originalIncident,
    265    G4ReactionProduct &currentParticle,
    266    G4ReactionProduct &targetParticle,
    267    G4bool &incidentHasChanged,
    268    G4bool &targetHasChanged,
    269    G4bool &quasiElastic )
    270   {
    271     // derived from original FORTRAN code CASN by H. Fesefeldt (13-Sep-1987)
    272     //
    273     // Neutron undergoes interaction with nucleon within a nucleus.  Check if it is
    274     // energetically possible to produce pions/kaons.  In not, assume nuclear excitation
    275     // occurs and input particle is degraded in energy. No other particles are produced.
    276     // If reaction is possible, find the correct number of pions/protons/neutrons
    277     // produced using an interpolation to multiplicity data.  Replace some pions or
    278     // protons/neutrons by kaons or strange baryons according to the average
    279     // multiplicity per Inelastic reaction.
    280     //
    281     const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
    282     const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
    283     const G4double targetMass = targetParticle.GetMass()/MeV;
    284     G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
    285                                         targetMass*targetMass +
    286                                         2.0*targetMass*etOriginal );
    287     G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
    288     if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
    289     {
    290       quasiElastic = true;
    291       return;
    292     }
    293     static G4bool first = true;
    294     const G4int numMul = 1200;
    295     const G4int numSec = 60;
    296     static G4double protmul[numMul], protnorm[numSec]; // proton constants
    297     static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
    298     // np = number of pi+, nm = number of pi-, nz = number of pi0
    299     G4int counter, nt=0, np=0, nm=0, nz=0;
    300     const G4double c = 1.25;   
    301     const G4double b[] = { 0.35, 0.0 };
    302     if( first )      // compute normalization constants, this will only be Done once
    303     {
    304       first = false;
    305       G4int i;
    306       for( i=0; i<numMul; ++i )protmul[i] = 0.0;
    307       for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
    308       counter = -1;
    309       for( np=0; np<numSec/3; ++np )
    310       {
    311         for( nm=std::max(0,np-1); nm<=(np+1); ++nm )
    312         {
    313           for( nz=0; nz<numSec/3; ++nz )
    314           {
    315             if( ++counter < numMul )
    316             {
    317               nt = np+nm+nz;
    318               if( nt > 0 )
    319               {
    320                 protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c) /
    321                   (Factorial(1-np+nm)*Factorial(1+np-nm) );
    322                 protnorm[nt-1] += protmul[counter];
    323               }
    324             }
    325           }
    326         }
    327       }
    328       for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
    329       for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
    330       counter = -1;
    331       for( np=0; np<(numSec/3); ++np )
    332       {
    333         for( nm=np; nm<=(np+2); ++nm )
    334         {
    335           for( nz=0; nz<numSec/3; ++nz )
    336           {
    337             if( ++counter < numMul )
    338             {
    339               nt = np+nm+nz;
    340               if( (nt>0) && (nt<=numSec) )
    341               {
    342                 neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c) /
    343                   (Factorial(nm-np)*Factorial(2-nm+np) );
    344                 neutnorm[nt-1] += neutmul[counter];
    345               }
    346             }
    347           }
    348         }
    349       }
    350       for( i=0; i<numSec; ++i )
    351       {
    352         if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
    353         if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
    354       }
    355     }   // end of initialization
    356    
    357     const G4double expxu = 82.;      // upper bound for arg. of exp
    358     const G4double expxl = -expxu;        // lower bound for arg. of exp
    359     G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
    360     G4ParticleDefinition *aProton = G4Proton::Proton();
    361     G4int ieab = static_cast<G4int>(availableEnergy*5.0/GeV);
    362     const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
    363     G4double test, w0, wp, wt, wm;
    364     if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
    365     {
    366       // suppress high multiplicity events at low momentum
    367       // only one pion will be produced
    368 
    369       nm = np = nz = 0;
    370       if( targetParticle.GetDefinition() == aNeutron )
    371       {
    372         test = std::exp( std::min( expxu, std::max( expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
    373         w0 = test/2.0;
    374         wm = test;
    375         if( G4UniformRand() < w0/(w0+wm) )
    376           nz = 1;
    377         else
    378           nm = 1;
    379       } else { // target is a proton
    380         test = std::exp( std::min( expxu, std::max( expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
    381         w0 = test;
    382         wp = test/2.0;       
    383         test = std::exp( std::min( expxu, std::max( expxl, -(-1.0+b[0])*(-1.0+b[0])/(2.0*c*c) ) ) );
    384         wm = test/2.0;
    385         wt = w0+wp+wm;
    386         wp += w0;
    387         G4double ran = G4UniformRand();
    388         if( ran < w0/wt )
    389           nz = 1;
    390         else if( ran < wp/wt )
    391           np = 1;
    392         else
    393           nm = 1;
    394       }
    395     } else {  // (availableEnergy >= 2.0*GeV) || (random number < supp[ieab])
    396       G4double n, anpn;
    397       GetNormalizationConstant( availableEnergy, n, anpn );
    398       G4double ran = G4UniformRand();
    399       G4double dum, excs = 0.0;
    400       if( targetParticle.GetDefinition() == aProton )
    401       {
    402         counter = -1;
    403         for( np=0; np<numSec/3 && ran>=excs; ++np )
    404         {
    405           for( nm=std::max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
    406           {
    407             for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
    408             {
    409               if( ++counter < numMul )
    410               {
    411                 nt = np+nm+nz;
    412                 if( nt > 0 )
    413                 {
    414                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
    415                   dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
    416                   if( std::fabs(dum) < 1.0 ) {
    417                     if( test >= 1.0e-10 )excs += dum*test;
    418                   } else {
    419                     excs += dum*test;
    420                   }
    421                 }
    422               }
    423             }
    424           }
    425         }
    426         if( ran >= excs )  // 3 previous loops continued to the end
    427         {
    428           quasiElastic = true;
    429           return;
    430         }
    431         np--; nm--; nz--;
    432       } else { // target must be a neutron
    433         counter = -1;
    434         for( np=0; np<numSec/3 && ran>=excs; ++np )
    435         {
    436           for( nm=np; nm<=(np+2) && ran>=excs; ++nm )
    437           {
    438             for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
    439             {
    440               if( ++counter < numMul )
    441               {
    442                 nt = np+nm+nz;
    443                 if( (nt>=1) && (nt<=numSec) )
    444                 {
    445                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
    446                   dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
    447                   if( std::fabs(dum) < 1.0 ) {
    448                     if( test >= 1.0e-10 )excs += dum*test;
    449                   } else {
    450                     excs += dum*test;
    451                   }
    452                 }
    453               }
    454             }
    455           }
    456         }
    457         if( ran >= excs )  // 3 previous loops continued to the end
    458         {
    459           quasiElastic = true;
    460           return;
    461         }
    462         np--; nm--; nz--;
    463       }
    464     }
    465     if( targetParticle.GetDefinition() == aProton )
    466     {
    467       switch( np-nm )
    468       {
    469        case 0:
    470          if( G4UniformRand() < 0.33 )
    471          {
    472            currentParticle.SetDefinitionAndUpdateE( aProton );
    473            targetParticle.SetDefinitionAndUpdateE( aNeutron );
    474            incidentHasChanged = true;
    475            targetHasChanged = true;
    476          }
    477          break;
    478        case 1:
    479          targetParticle.SetDefinitionAndUpdateE( aNeutron );
    480          targetHasChanged = true;
    481          break;
    482        default:
    483          currentParticle.SetDefinitionAndUpdateE( aProton );
    484          incidentHasChanged = true;
    485          break;
    486       }
    487     } else { // target must be a neutron
    488       switch( np-nm )
    489       {
    490        case -1:                       // changed from +1 by JLC, 7Jul97
    491          if( G4UniformRand() < 0.5 )
    492          {
    493            currentParticle.SetDefinitionAndUpdateE( aProton );
    494            incidentHasChanged = true;
    495          } else {
    496            targetParticle.SetDefinitionAndUpdateE( aProton );
    497            targetHasChanged = true;
    498          }
    499          break;
    500        case 0:
    501          break;
    502        default:
    503          currentParticle.SetDefinitionAndUpdateE( aProton );
    504          targetParticle.SetDefinitionAndUpdateE( aProton );
    505          incidentHasChanged = true;
    506          targetHasChanged = true;
    507          break;
    508       }
    509     }
    510     SetUpPions( np, nm, nz, vec, vecLen );
    511 // DEBUG -->    DumpFrames::DumpFrame(vec, vecLen);
    512     return;
    513   }
    514 
    515  /* end of file */
    516  
     323
     324    } else { // neutron
     325      targetHasChanged = true;
     326    }
     327
     328    testCharge = 1.0;
     329    testBaryon = 2.0;
     330    testStrange = 0.0;
     331  }
     332
     333  //  if (mult == 2 && !incidentHasChanged && !targetHasChanged)
     334  //                                              quasiElastic = true;
     335 
     336  // Remove incident and target from fsTypes
     337 
     338  fsTypes.erase(fsTypes.begin());
     339  fsTypes.erase(fsTypes.begin());
     340
     341  // Remaining particles are secondaries.  Put them into vec.
     342 
     343  G4ReactionProduct* rp(0);
     344  for(G4int i=0; i < mult-2; ++i ) {
     345    partType = fsTypes[i];
     346    rp = new G4ReactionProduct();
     347    rp->SetDefinition(particleDef[partType]);
     348    (G4UniformRand() < 0.5) ? rp->SetSide(-1) : rp->SetSide(1);
     349    vec.SetElement(vecLen++, rp);
     350  }
     351
     352  // Check conservation of charge, strangeness, baryon number
     353 
     354  CheckQnums(vec, vecLen, currentParticle, targetParticle,
     355             testCharge, testBaryon, testStrange);
     356 
     357  return;
     358}
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGOmegaMinusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGOmegaMinusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGPiMinusInelastic.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGPiMinusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGPiMinusInelastic.cc,v 1.4 2008/05/05 21:21:55 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
     
    3131#include "Randomize.hh"
    3232
    33 
    3433G4HadFinalState*
    3534G4RPGPiMinusInelastic::ApplyYourself(const G4HadProjectile& aTrack,
    36                                      G4Nucleus& targetNucleus)
     35                                      G4Nucleus& targetNucleus)
    3736{
    3837  const G4HadProjectile* originalIncident = &aTrack;
    39   if (originalIncident->GetKineticEnergy() <= 0.1*MeV)
    40   {
     38
     39  if (originalIncident->GetKineticEnergy()<= 0.1) {
    4140    theParticleChange.SetStatusChange(isAlive);
    4241    theParticleChange.SetEnergyChange(aTrack.GetKineticEnergy());
     
    5049  G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
    5150   
    52   if( verboseLevel > 1 )
    53   {
    54     const G4Material *targetMaterial = aTrack.GetMaterial();
    55     G4cout << "G4PionMinusInelastic::ApplyYourself called" << G4endl;
    56     G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
    57     G4cout << "target material = " << targetMaterial->GetName() << ", ";
    58     G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
    59            << G4endl;
    60   }
    61 
    6251  G4ReactionProduct currentParticle(
    63     const_cast<G4ParticleDefinition *>(originalIncident->GetDefinition() ) );
     52  const_cast<G4ParticleDefinition *>(originalIncident->GetDefinition() ) );
    6453  currentParticle.SetMomentum( originalIncident->Get4Momentum().vect() );
    6554  currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
     
    7766  G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
    7867  G4double pp = currentParticle.GetMomentum().mag();
    79   if( pp > 0.0 )
    80   {
     68  if( pp > 0.0 ) {
    8169    G4ThreeVector momentum = currentParticle.GetMomentum();
    8270    currentParticle.SetMomentum( momentum * (p/pp) );
     
    9179  p = std::sqrt( std::abs((et-amas)*(et+amas)) );
    9280  pp = currentParticle.GetMomentum().mag();
    93   if( pp > 0.0 )
    94   {
     81  if( pp > 0.0 ) {
    9582    G4ThreeVector momentum = currentParticle.GetMomentum();
    9683    currentParticle.SetMomentum( momentum * (p/pp) );
     
    10491  G4bool targetHasChanged = false;
    10592  G4bool quasiElastic = false;
    106   G4FastVector<G4ReactionProduct,256> vec;
     93  G4FastVector<G4ReactionProduct,256> vec;  // vec will contain the secondary particles
    10794  G4int vecLen = 0;
    10895  vec.Initialize( 0 );
    10996   
    110   const G4double cutOff = 0.1*MeV;
     97  const G4double cutOff = 0.1;
    11198  if( currentParticle.GetKineticEnergy() > cutOff )
    112     Cascade(vec, vecLen,
    113             originalIncident, currentParticle, targetParticle,
    114             incidentHasChanged, targetHasChanged, quasiElastic);
     99    InitialCollision(vec, vecLen, currentParticle, targetParticle,
     100                     incidentHasChanged, targetHasChanged);
    115101   
    116102  CalculateMomenta(vec, vecLen,
     
    119105                   incidentHasChanged, targetHasChanged, quasiElastic);
    120106   
    121   SetUpChange(vec, vecLen, currentParticle, targetParticle,
     107  SetUpChange(vec, vecLen,
     108              currentParticle, targetParticle,
    122109              incidentHasChanged);
    123110   
     
    125112  return &theParticleChange;
    126113}
     114
     115
     116// Initial Collision
     117//   selects the particle types arising from the initial collision of
     118//   the projectile and target nucleon.  Secondaries are assigned to
     119//   forward and backward reaction hemispheres, but final state energies
     120//   and momenta are not calculated here.
    127121 
    128 void G4RPGPiMinusInelastic::Cascade(
    129    G4FastVector<G4ReactionProduct,256> &vec,
    130    G4int& vecLen,
    131    const G4HadProjectile *originalIncident,
    132    G4ReactionProduct &currentParticle,
    133    G4ReactionProduct &targetParticle,
    134    G4bool &incidentHasChanged,
    135    G4bool &targetHasChanged,
    136    G4bool &quasiElastic)
     122void
     123G4RPGPiMinusInelastic::InitialCollision(G4FastVector<G4ReactionProduct,256>& vec,
     124                                  G4int& vecLen,
     125                                  G4ReactionProduct& currentParticle,
     126                                  G4ReactionProduct& targetParticle,
     127                                  G4bool& incidentHasChanged,
     128                                  G4bool& targetHasChanged)
    137129{
    138   // Derived from H. Fesefeldt's original FORTRAN code CASPIM
    139   //
    140   // pi-  undergoes interaction with nucleon within nucleus.
    141   // Check if energetically possible to produce pions/kaons.
    142   // If not assume nuclear excitation occurs and input particle
    143   // is degraded in energy.  No other particles produced.
    144   // If reaction is possible find correct number of pions/protons/neutrons
    145   // produced using an interpolation to multiplicity data.
    146   // Replace some pions or protons/neutrons by kaons or strange baryons
    147   // according to average multiplicity per inelastic reactions.
    148   //
    149   const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
    150   const G4double etOriginal = originalIncident->GetTotalEnergy();
    151   const G4double pOriginal = originalIncident->GetTotalMomentum();
    152   const G4double targetMass = targetParticle.GetMass();
    153   G4double centerofmassEnergy = std::sqrt(mOriginal*mOriginal +
    154                                           targetMass*targetMass +
    155                                           2.0*targetMass*etOriginal);
    156   G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
    157   static G4bool first = true;
    158   const G4int numMul = 1200;
    159   const G4int numSec = 60;
    160   static G4double protmul[numMul], protnorm[numSec]; // proton constants
    161   static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
    162   // np = number of pi+, nm = number of pi-, nz = number of pi0
    163   G4int counter, nt=0, np=0, nm=0, nz=0;
    164   const G4double c = 1.25;
    165   const G4double b[] = { 0.70, 0.70 };
    166   if( first )       // compute normalization constants, this will only be Done once
    167   {
    168       first = false;
    169       G4int i;
    170       for( i=0; i<numMul; ++i )protmul[i] = 0.0;
    171       for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
    172       counter = -1;
    173       for( np=0; np<(numSec/3); ++np )
    174       {
    175         for( nm=std::max(0,np-1); nm<=(np+1); ++nm )
    176         {
    177           for( nz=0; nz<numSec/3; ++nz )
    178           {
    179             if( ++counter < numMul )
    180             {
    181               nt = np+nm+nz;
    182               if( nt > 0 )
    183               {
    184                 protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
    185                 protnorm[nt-1] += protmul[counter];
    186               }
    187             }
    188           }
    189         }
    190       }
    191       for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
    192       for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
    193       counter = -1;
    194       for( np=0; np<numSec/3; ++np )
    195       {
    196         for( nm=np; nm<=(np+2); ++nm )
    197         {
    198           for( nz=0; nz<numSec/3; ++nz )
    199           {
    200             if( ++counter < numMul )
    201             {
    202               nt = np+nm+nz;
    203               if( (nt>0) && (nt<=numSec) )
    204               {
    205                 neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
    206                 neutnorm[nt-1] += neutmul[counter];
    207               }
    208             }
    209           }
    210         }
    211       }
    212     for( i=0; i<numSec; ++i ) {
    213       if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
    214       if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
     130  G4double KE = currentParticle.GetKineticEnergy()/GeV;
     131 
     132  G4int mult;
     133  G4int partType;
     134  std::vector<G4int> fsTypes;
     135
     136  G4double testCharge;
     137  G4double testBaryon;
     138  G4double testStrange;
     139
     140  // Get particle types according to incident and target types
     141
     142  if (targetParticle.GetDefinition() == particleDef[pro]) {
     143    mult = GetMultiplicityT12(KE);
     144    fsTypes = GetFSPartTypesForPimP(mult, KE);
     145    partType = fsTypes[0];
     146    if (partType != pro) {
     147      targetHasChanged = true;
     148      targetParticle.SetDefinition(particleDef[partType]);
    215149    }
    216   }   // end of initialization
    217    
    218   const G4double expxu = 82.;           // upper bound for arg. of exp
    219   const G4double expxl = -expxu;        // lower bound for arg. of exp
    220   G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
    221   G4ParticleDefinition *aProton = G4Proton::Proton();
    222   G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
    223   G4int ieab = G4int(availableEnergy*5.0/GeV);
    224   const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
    225   G4double test, w0, wp, wt, wm;
    226   if( (availableEnergy<2.0*GeV) && (G4UniformRand()>=supp[ieab]) )
    227   {
    228     // suppress high multiplicity events at low momentum
    229     // only one pion will be produced
    230      
    231     // charge exchange reaction is included in inelastic cross section
    232        
    233     const G4double cech[] = {1.,0.95,0.79,0.32,0.19,0.16,0.14,0.12,0.10,0.08};
    234     G4int iplab = G4int(std::min( 9.0, pOriginal/GeV*5.0 ));
    235     if( G4UniformRand() <= cech[iplab] )
    236     {
    237       if( targetParticle.GetDefinition() == aProton )
    238       {
    239         currentParticle.SetDefinitionAndUpdateE( aPiZero );  // charge exchange
    240         targetParticle.SetDefinitionAndUpdateE( aNeutron );
    241         incidentHasChanged = true;
    242         targetHasChanged = true;
    243       }
     150
     151    testCharge = 0.0;
     152    testBaryon = 1.0;
     153    testStrange = 0.0;
     154
     155  } else {   // target was a neutron
     156    mult = GetMultiplicityT32(KE);
     157    fsTypes = GetFSPartTypesForPimN(mult, KE);
     158    partType = fsTypes[0];
     159    if (partType != neu) {
     160      targetHasChanged = true;
     161      targetParticle.SetDefinition(particleDef[partType]);
    244162    }
    245      
    246     if( availableEnergy <= G4PionMinus::PionMinus()->GetPDGMass() )
    247     {
    248       quasiElastic = true;
    249       return;
     163
     164    testCharge = -1.0;
     165    testBaryon = 1.0;
     166    testStrange = 0.0;
     167  }
     168
     169  // Remove target particle from list
     170
     171  fsTypes.erase(fsTypes.begin());
     172
     173  // See if the incident particle changed type
     174
     175  G4int choose = -1;
     176  for(G4int i=0; i < mult-1; ++i ) {
     177    partType = fsTypes[i];
     178    if (partType == pim) {
     179      choose = i;
     180      break;
    250181    }
    251      
    252     nm = np = nz = 0;
    253     if( targetParticle.GetDefinition() == aProton )
    254     {
    255         test = std::exp( std::min( expxu, std::max( expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
    256         w0 = test;
    257         wp = 10.0*test;       
    258         test = std::exp( std::min( expxu, std::max( expxl, -(-1.0+b[0])*(-1.0+b[0])/(2.0*c*c) ) ) );
    259         wm = test;
    260         wt = w0+wp+wm;
    261         wp += w0;
    262         G4double ran = G4UniformRand();
    263         if( ran < w0/wt )
    264           nz = 1;
    265         else if( ran < wp/wt )
    266           np = 1;
    267         else
    268           nm = 1;
    269     }
    270     else  // target is a neutron
    271     {
    272         test = std::exp( std::min( expxu, std::max( expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
    273         w0 = test;
    274         test = std::exp( std::min( expxu, std::max( expxl, -(-1.0+b[1])*(-1.0+b[1])/(2.0*c*c) ) ) );
    275         wm = test;
    276         G4double ran = G4UniformRand();
    277         if( ran < w0/(w0+wm) )
    278           nz = 1;
    279         else
    280           nm = 1;
    281     }
    282   }
    283   else
    284   {
    285       if( availableEnergy <= G4PionMinus::PionMinus()->GetPDGMass() )
    286       {
    287         quasiElastic = true;
    288         return;
    289       }
    290       G4double n, anpn;
    291       GetNormalizationConstant( availableEnergy, n, anpn );
    292       G4double ran = G4UniformRand();
    293       G4double dum, excs = 0.0;
    294       if( targetParticle.GetDefinition() == aProton )
    295       {
    296         counter = -1;
    297         for( np=0; (np<numSec/3) && (ran>=excs); ++np )
    298         {
    299           for( nm=std::max(0,np-1); (nm<=(np+1)) && (ran>=excs); ++nm )
    300           {
    301             for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
    302             {
    303               if( ++counter < numMul )
    304               {
    305                 nt = np+nm+nz;
    306                 if( nt > 0 )
    307                 {
    308                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
    309                   dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
    310                   if( std::fabs(dum) < 1.0 )
    311                   {
    312                     if( test >= 1.0e-10 )excs += dum*test;
    313                   }
    314                   else
    315                     excs += dum*test;
    316                 }
    317               }
    318             }
    319           }
    320         }
    321         if( ran >= excs )  // 3 previous loops continued to the end
    322         {
    323           quasiElastic = true;
    324           return;
    325         }
    326         np--; nm--; nz--;
    327       }
    328       else  // target must be a neutron
    329       {
    330         counter = -1;
    331         for( np=0; (np<numSec/3) && (ran>=excs); ++np )
    332         {
    333           for( nm=np; (nm<=(np+2)) && (ran>=excs); ++nm )
    334           {
    335             for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz )
    336             {
    337               if( ++counter < numMul )
    338               {
    339                 nt = np+nm+nz;
    340                 if( (nt>=1) && (nt<=numSec) )
    341                 {
    342                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
    343                   dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
    344                   if( std::fabs(dum) < 1.0 )
    345                   {
    346                     if( test >= 1.0e-10 )excs += dum*test;
    347                   }
    348                   else
    349                     excs += dum*test;
    350                 }
    351               }
    352             }
    353           }
    354         }
    355         if( ran >= excs )  // 3 previous loops continued to the end
    356         {
    357           quasiElastic = true;
    358           return;
    359         }
    360         np--; nm--; nz--;
    361       }
    362   }
    363   if( targetParticle.GetDefinition() == aProton )
    364   {
    365     switch( np-nm )
    366     {
    367      case 0:
    368        if( G4UniformRand() >= 0.75 )
    369        {
    370          currentParticle.SetDefinitionAndUpdateE( aPiZero );
    371          targetParticle.SetDefinitionAndUpdateE( aNeutron );
    372          incidentHasChanged = true;
    373          targetHasChanged = true;
    374        }
    375        break;
    376      case 1:
    377        targetParticle.SetDefinitionAndUpdateE( aNeutron );
    378        targetHasChanged = true;
    379        break;
    380      default:
    381        currentParticle.SetDefinitionAndUpdateE( aPiZero );
    382        incidentHasChanged = true;
    383        break;
    384     }
    385   }
    386   else
    387   {
    388     switch( np-nm )
    389     {
    390      case -1:
    391        if( G4UniformRand() < 0.5 )
    392        {
    393          targetParticle.SetDefinitionAndUpdateE( aProton );
    394          targetHasChanged = true;
    395        } else {
    396          currentParticle.SetDefinitionAndUpdateE( aPiZero );
    397          incidentHasChanged = true;
    398        }
    399        break;
    400      case 0:
    401        break;
    402      default:
    403        currentParticle.SetDefinitionAndUpdateE( aPiZero );
    404        incidentHasChanged = true;
    405        break;
    406     }
    407   }
    408 
    409   SetUpPions( np, nm, nz, vec, vecLen );
     182  }
     183  if (choose == -1) {
     184    incidentHasChanged = true;
     185    choose = G4int(G4UniformRand()*(mult-1) );
     186    partType = fsTypes[choose];
     187    currentParticle.SetDefinition(particleDef[partType]);
     188  }
     189
     190  fsTypes.erase(fsTypes.begin()+choose);
     191
     192  // Remaining particles are secondaries.  Put them into vec.
     193
     194  G4ReactionProduct* rp(0);
     195  for(G4int i=0; i < mult-2; ++i ) {
     196    partType = fsTypes[i];
     197    rp = new G4ReactionProduct();
     198    rp->SetDefinition(particleDef[partType]);
     199    (G4UniformRand() < 0.5) ? rp->SetSide(-1) : rp->SetSide(1);
     200    if (partType > pim && partType < pro) rp->SetMayBeKilled(false);  // kaons
     201    vec.SetElement(vecLen++, rp);
     202  }
     203
     204  //  if (mult == 2 && !incidentHasChanged && !targetHasChanged)
     205  //                                              quasiElastic = true;
     206
     207  // Check conservation of charge, strangeness, baryon number
     208
     209  CheckQnums(vec, vecLen, currentParticle, targetParticle,
     210             testCharge, testBaryon, testStrange);
     211
    410212  return;
    411213}
    412 
    413  /* end of file */
    414  
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGPiPlusInelastic.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGPiPlusInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGPiPlusInelastic.cc,v 1.4 2008/05/05 21:21:55 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
     
    3131#include "Randomize.hh"
    3232
    33  G4HadFinalState *
    34   G4RPGPiPlusInelastic::ApplyYourself( const G4HadProjectile &aTrack,
    35                                         G4Nucleus &targetNucleus )
    36   {
    37     const G4HadProjectile *originalIncident = &aTrack;
    38     if (originalIncident->GetKineticEnergy()<= 0.1*MeV)
    39     {
    40       theParticleChange.SetStatusChange(isAlive);
    41       theParticleChange.SetEnergyChange(aTrack.GetKineticEnergy());
    42       theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit());
    43       return &theParticleChange;     
    44     }
     33G4HadFinalState*
     34G4RPGPiPlusInelastic::ApplyYourself(const G4HadProjectile& aTrack,
     35                                     G4Nucleus& targetNucleus)
     36{
     37  const G4HadProjectile *originalIncident = &aTrack;
     38  if (originalIncident->GetKineticEnergy()<= 0.1) {
     39    theParticleChange.SetStatusChange(isAlive);
     40    theParticleChange.SetEnergyChange(aTrack.GetKineticEnergy());
     41    theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit());
     42    return &theParticleChange;     
     43  }
    4544
    4645    // create the target particle
    4746   
    4847    G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
    49 //    G4double targetMass = originalTarget->GetDefinition()->GetPDGMass();
    5048    G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
    5149   
    52     if( verboseLevel > 1 )
    53     {
    54       const G4Material *targetMaterial = aTrack.GetMaterial();
    55       G4cout << "G4RPGPiPlusInelastic::ApplyYourself called" << G4endl;
    56       G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
    57       G4cout << "target material = " << targetMaterial->GetName() << ", ";
    58       G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
    59            << G4endl;
    60     }
    6150    G4ReactionProduct currentParticle(
    6251    const_cast<G4ParticleDefinition *>(originalIncident->GetDefinition() ) );
     
    10796    vec.Initialize( 0 );
    10897   
    109     const G4double cutOff = 0.1*MeV;
     98    const G4double cutOff = 0.1;
    11099    if( currentParticle.GetKineticEnergy() > cutOff )
    111       Cascade( vec, vecLen,
    112                originalIncident, currentParticle, targetParticle,
    113                incidentHasChanged, targetHasChanged, quasiElastic );
     100      InitialCollision(vec, vecLen, currentParticle, targetParticle,
     101                       incidentHasChanged, targetHasChanged);
    114102   
    115103    CalculateMomenta( vec, vecLen,
     
    124112    delete originalTarget;
    125113    return &theParticleChange;
    126   }
     114}
     115
     116
     117// Initial Collision
     118//   selects the particle types arising from the initial collision of
     119//   the projectile and target nucleon.  Secondaries are assigned to
     120//   forward and backward reaction hemispheres, but final state energies
     121//   and momenta are not calculated here.
    127122 
    128  void
    129   G4RPGPiPlusInelastic::Cascade(
    130    G4FastVector<G4ReactionProduct,256> &vec,
    131    G4int& vecLen,
    132    const G4HadProjectile *originalIncident,
    133    G4ReactionProduct &currentParticle,
    134    G4ReactionProduct &targetParticle,
    135    G4bool &incidentHasChanged,
    136    G4bool &targetHasChanged,
    137    G4bool &quasiElastic )
    138   {
    139     // derived from original FORTRAN code CASPIP by H. Fesefeldt (18-Sep-1987)
    140     //
    141     // pi+  undergoes interaction with nucleon within nucleus.
    142     // Check if energetically possible to produce pions/kaons.
    143     // If not assume nuclear excitation occurs and input particle
    144     // is degraded in energy.  No other particles produced.
    145     // If reaction is possible find correct number of pions/protons/neutrons
    146     // produced using an interpolation to multiplicity data.
    147     // Replace some pions or protons/neutrons by kaons or strange baryons
    148     // according to average multiplicity per inelastic reactions.
    149     //
    150     const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
    151     const G4double etOriginal = originalIncident->GetTotalEnergy();
    152     const G4double pOriginal = originalIncident->GetTotalMomentum();
    153     const G4double targetMass = targetParticle.GetMass();
    154     G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
    155                                         targetMass*targetMass +
    156                                         2.0*targetMass*etOriginal );
    157     G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
    158     static G4bool first = true;
    159     const G4int numMul = 1200;
    160     const G4int numSec = 60;
    161     static G4double protmul[numMul], protnorm[numSec]; // proton constants
    162     static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
    163     // np = number of pi+, nm = number of pi-, nz = number of pi0
    164     G4int counter, nt=0, np=0, nm=0, nz=0;
    165     const G4double c = 1.25;
    166     const G4double b[] = { 0.70, 0.70 };
    167     if( first ) {      // compute normalization constants, this will only be Done once
    168       first = false;
    169       G4int i;
    170       for( i=0; i<numMul; ++i )protmul[i] = 0.0;
    171       for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
    172       counter = -1;
    173       for( np=0; np<(numSec/3); ++np ) {
    174         for( nm=std::max(0,np-2); nm<=np; ++nm ) {
    175           for( nz=0; nz<numSec/3; ++nz ) {
    176             if( ++counter < numMul ) {
    177               nt = np+nm+nz;
    178               if( nt > 0 ) {
    179                 protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c);
    180                 protnorm[nt-1] += protmul[counter];
    181               }
    182             }
    183           }
    184         }
    185       }
    186       for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
    187       for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
    188       counter = -1;
    189       for( np=0; np<numSec/3; ++np ) {
    190         for( nm=std::max(0,np-1); nm<=(np+1); ++nm ) {
    191           for( nz=0; nz<numSec/3; ++nz ) {
    192             if( ++counter < numMul ) {
    193               nt = np+nm+nz;
    194               if( (nt>0) && (nt<=numSec) ) {
    195                 neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c);
    196                 neutnorm[nt-1] += neutmul[counter];
    197               }
    198             }
    199           }
    200         }
    201       }
    202       for( i=0; i<numSec; ++i ) {
    203         if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
    204         if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
    205       }
    206     }   // end of initialization
    207    
    208     const G4double expxu = 82.;           // upper bound for arg. of exp
    209     const G4double expxl = -expxu;        // lower bound for arg. of exp
    210     G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
    211     G4ParticleDefinition *aProton = G4Proton::Proton();
    212     G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
    213     G4int ieab = static_cast<G4int>(availableEnergy*5.0/GeV);
    214     const G4double supp[] = {0.,0.2,0.45,0.55,0.65,0.75,0.85,0.90,0.94,0.98};
    215     G4double test, w0, wp, wt, wm;
    216     if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
    217     {
    218       // suppress high multiplicity events at low momentum
    219       // only one pion will be produced
    220       // charge exchange reaction is included in inelastic cross section
    221      
    222       const G4double cech[] = {1.,0.95,0.79,0.32,0.19,0.16,0.14,0.12,0.10,0.08};
    223       G4int iplab = G4int(std::min( 9.0, pOriginal/GeV*5.0 ));
    224       if( G4UniformRand() <= cech[iplab] )
    225       {
    226         if( targetParticle.GetDefinition() == aNeutron )
    227         {
    228           currentParticle.SetDefinitionAndUpdateE( aPiZero );  // charge exchange
    229           targetParticle.SetDefinitionAndUpdateE( aProton );
    230           incidentHasChanged = true;
    231           targetHasChanged = true;
    232         }
    233       }
    234      
    235       if( availableEnergy <= G4PionMinus::PionMinus()->GetPDGMass() )
    236       {
    237         quasiElastic = true;
    238         return;
    239       }
    240      
    241       nm = np = nz = 0;
    242       if( targetParticle.GetDefinition() == aProton ) {
    243         test = std::exp( std::min( expxu, std::max( expxl, -sqr(1.0+b[0])/(2.0*c*c) ) ) );
    244         w0 = test;
    245         wp = test;       
    246         if( G4UniformRand() < w0/(w0+wp) )
    247           nz =1;
    248         else
    249           np = 1;
    250       } else { // target is a neutron
    251         test = std::exp( std::min( expxu, std::max( expxl, -sqr(1.0+b[1])/(2.0*c*c) ) ) );
    252         w0 = test;
    253         wp = test;       
    254         test = std::exp( std::min( expxu, std::max( expxl, -sqr(-1.0+b[1])/(2.0*c*c) ) ) );
    255         wm = test;
    256         wt = w0+wp+wm;
    257         wp = w0+wp;
    258         G4double ran = G4UniformRand();
    259         if( ran < w0/wt )
    260           nz = 1;
    261         else if( ran < wp/wt )
    262           np = 1;
    263         else
    264           nm = 1;
    265       }
    266     } else {
    267       if( availableEnergy <= G4PionMinus::PionMinus()->GetPDGMass() )
    268       {
    269         quasiElastic = true;
    270         return;
    271       }
    272       G4double n, anpn;
    273       GetNormalizationConstant( availableEnergy, n, anpn );
    274       G4double ran = G4UniformRand();
    275       G4double dum, excs = 0.0;
    276       if( targetParticle.GetDefinition() == aProton ) {
    277         counter = -1;
    278         for( np=0; (np<numSec/3) && (ran>=excs); ++np ) {
    279           for( nm=std::max(0,np-2); (nm<=np) && (ran>=excs); ++nm ) {
    280             for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz ) {
    281               if( ++counter < numMul ) {
    282                 nt = np+nm+nz;
    283                 if( nt > 0 ) {
    284                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
    285                   dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
    286                   if( std::fabs(dum) < 1.0 ) {
    287                     if( test >= 1.0e-10 )excs += dum*test;
    288                   } else {
    289                     excs += dum*test;
    290                   }
    291                 }
    292               }
    293             }
    294           }
    295         }
    296         if( ran >= excs )
    297         {
    298           quasiElastic = true;
    299           return;  // 3 previous loops continued to the end
    300         }
    301         np--; nm--; nz--;
    302       } else { // target must be a neutron
    303         counter = -1;
    304         for( np=0; (np<numSec/3) && (ran>=excs); ++np ) {
    305           for( nm=std::max(0,np-1); (nm<=(np+1)) && (ran>=excs); ++nm ) {
    306             for( nz=0; (nz<numSec/3) && (ran>=excs); ++nz ) {
    307               if( ++counter < numMul ) {
    308                 nt = np+nm+nz;
    309                 if( (nt>=1) && (nt<=numSec) ) {
    310                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
    311                   dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
    312                   if( std::fabs(dum) < 1.0 ) {
    313                     if( test >= 1.0e-10 )excs += dum*test;
    314                   } else {
    315                     excs += dum*test;
    316                   }
    317                 }
    318               }
    319             }
    320           }
    321         }
    322         if( ran >= excs )  // 3 previous loops continued to the end
    323         {
    324           quasiElastic = true;
    325           return;  // 3 previous loops continued to the end
    326         }
    327         np--; nm--; nz--;
    328       }
    329     }
    330     if( targetParticle.GetDefinition() == aProton ) {
    331       switch( np-nm ) {
    332        case 1:
    333          if( G4UniformRand() < 0.5 ) {
    334            currentParticle.SetDefinitionAndUpdateE( aPiZero );
    335            incidentHasChanged = true;
    336          } else {
    337            targetParticle.SetDefinitionAndUpdateE( aNeutron );
    338            targetHasChanged = true;
    339          }
    340          break;
    341        case 2:
    342          currentParticle.SetDefinitionAndUpdateE( aPiZero );
    343          targetParticle.SetDefinitionAndUpdateE( aNeutron );
    344          incidentHasChanged = true;
    345          targetHasChanged = true;
    346          break;
    347        default:
    348          break;
    349       }
    350     } else {
    351       switch( np-nm ) {
    352        case 0:
    353          if( G4UniformRand() < 0.25 ) {
    354            currentParticle.SetDefinitionAndUpdateE( aPiZero );
    355            targetParticle.SetDefinitionAndUpdateE( aProton );
    356            incidentHasChanged = true;
    357            targetHasChanged = true;
    358          }
    359          break;
    360        case 1:
    361          currentParticle.SetDefinitionAndUpdateE( aPiZero );
    362          incidentHasChanged = true;
    363          break;
    364        default:
    365          targetParticle.SetDefinitionAndUpdateE( aProton );
    366          targetHasChanged = true;
    367          break;
    368       }
    369     }
    370     SetUpPions( np, nm, nz, vec, vecLen );
    371     return;
    372   }
    373 
    374  /* end of file */
     123void
     124G4RPGPiPlusInelastic::InitialCollision(G4FastVector<G4ReactionProduct,256>& vec,
     125                                  G4int& vecLen,
     126                                  G4ReactionProduct& currentParticle,
     127                                  G4ReactionProduct& targetParticle,
     128                                  G4bool& incidentHasChanged,
     129                                  G4bool& targetHasChanged)
     130{
     131  G4double KE = currentParticle.GetKineticEnergy()/GeV;
     132
     133  G4int mult;
     134  G4int partType;
     135  std::vector<G4int> fsTypes;
     136
     137  G4double testCharge;
     138  G4double testBaryon;
     139  G4double testStrange;
     140
     141  // Get particle types according to incident and target types
     142
     143  if (targetParticle.GetDefinition() == particleDef[pro]) {
     144    mult = GetMultiplicityT32(KE);
     145    fsTypes = GetFSPartTypesForPipP(mult, KE);
     146    partType = fsTypes[0];
     147    if (partType != pro) {
     148      targetHasChanged = true;
     149      targetParticle.SetDefinition(particleDef[partType]);
     150    }
     151
     152    testCharge = 2.0;
     153    testBaryon = 1.0;
     154    testStrange = 0.0;
     155
     156  } else {   // target was a neutron
     157    mult = GetMultiplicityT12(KE);
     158    fsTypes = GetFSPartTypesForPipN(mult, KE);
     159    partType = fsTypes[0];
     160    if (partType != neu) {
     161      targetHasChanged = true;
     162      targetParticle.SetDefinition(particleDef[partType]);
     163    }
     164
     165    testCharge = 1.0;
     166    testBaryon = 1.0;
     167    testStrange = 0.0;
     168  }
     169
     170  // Remove target particle from list
     171
     172  fsTypes.erase(fsTypes.begin());
     173
     174  // See if the incident particle changed type
     175
     176  G4int choose = -1;
     177  for(G4int i=0; i < mult-1; ++i ) {
     178    partType = fsTypes[i];
     179    if (partType == pip) {
     180      choose = i;
     181      break;
     182    }
     183  }
     184  if (choose == -1) {
     185    incidentHasChanged = true;
     186    choose = G4int(G4UniformRand()*(mult-1) );
     187    partType = fsTypes[choose];
     188    currentParticle.SetDefinition(particleDef[partType]);
     189  }
     190  fsTypes.erase(fsTypes.begin()+choose);
     191
     192  // Remaining particles are secondaries.  Put them into vec.
     193  //   Improve this by randomizing secondary order, then alternate
     194  //   which secondary is put into forward or backward hemisphere
     195
     196  G4ReactionProduct* rp(0);
     197  for(G4int i=0; i < mult-2; ++i ) {
     198    partType = fsTypes[i];
     199    rp = new G4ReactionProduct();
     200    rp->SetDefinition(particleDef[partType]);
     201    (G4UniformRand() < 0.5) ? rp->SetSide(-1) : rp->SetSide(1);
     202    if (partType > pim && partType < pro) rp->SetMayBeKilled(false);  // kaons
     203    vec.SetElement(vecLen++, rp);
     204  }
    375205 
     206  //  if (mult == 2 && !incidentHasChanged && !targetHasChanged)
     207  //                                              quasiElastic = true;
     208
     209  // Check conservation of charge, strangeness, baryon number
     210
     211  CheckQnums(vec, vecLen, currentParticle, targetParticle,
     212             testCharge, testBaryon, testStrange);
     213
     214  return;
     215}
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGPionSuppression.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGPionSuppression.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGProtonInelastic.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGProtonInelastic.cc,v 1.1 2007/07/18 21:04:20 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGProtonInelastic.cc,v 1.4 2008/05/05 21:21:55 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
     
    3232 
    3333G4HadFinalState*
    34 G4RPGProtonInelastic::ApplyYourself( const G4HadProjectile &aTrack,
    35                                      G4Nucleus &targetNucleus )
     34G4RPGProtonInelastic::ApplyYourself(const G4HadProjectile& aTrack,
     35                                    G4Nucleus& targetNucleus )
    3636{
    3737  theParticleChange.Clear();
    3838  const G4HadProjectile *originalIncident = &aTrack;
    39   if (originalIncident->GetKineticEnergy()<= 0.1*MeV)
     39  if (originalIncident->GetKineticEnergy()<= 0.1)
    4040  {
    4141    theParticleChange.SetStatusChange(isAlive);
     
    4949  //
    5050  G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
    51   if( verboseLevel > 1 )
    52   {
    53     const G4Material *targetMaterial = aTrack.GetMaterial();
    54     G4cout << "G4RPGProtonInelastic::ApplyYourself called" << G4endl;
    55     G4cout << "kinetic energy = "
    56            << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
    57     G4cout << "target material = "
    58            << targetMaterial->GetName() << ", ";
    59     G4cout << "target particle = "
    60            << originalTarget->GetDefinition()->GetParticleName()
    61            << G4endl;
    62   }
    63 
    64   if( originalIncident->GetKineticEnergy()/GeV < 0.01+2.*G4UniformRand()/9. )
     51
     52  if (originalIncident->GetKineticEnergy()/GeV < 0.01+2.*G4UniformRand()/9. )
    6553  {
    6654    SlowProton( originalIncident, targetNucleus );
     
    6957  }
    7058
    71   //
    7259  // Fermi motion and evaporation
    7360  // As of Geant3, the Fermi energy calculation had not been Done
    74   //
    75   G4double ek = originalIncident->GetKineticEnergy()/MeV;
    76   G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
     61
     62  G4double ek = originalIncident->GetKineticEnergy();
     63  G4double amas = originalIncident->GetDefinition()->GetPDGMass();
    7764  G4ReactionProduct modifiedOriginal;
    7865  modifiedOriginal = *originalIncident;
     
    8067  G4double tkin = targetNucleus.Cinema( ek );
    8168  ek += tkin;
    82   modifiedOriginal.SetKineticEnergy( ek*MeV );
     69  modifiedOriginal.SetKineticEnergy(ek);
    8370  G4double et = ek + amas;
    8471  G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
    85   G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
    86   if( pp > 0.0 )
    87   {
     72  G4double pp = modifiedOriginal.GetMomentum().mag();
     73  if (pp > 0.0) {
    8874    G4ThreeVector momentum = modifiedOriginal.GetMomentum();
    8975    modifiedOriginal.SetMomentum( momentum * (p/pp) );
     
    9278  // calculate black track energies
    9379  //
    94   tkin = targetNucleus.EvaporationEffects( ek );
     80  tkin = targetNucleus.EvaporationEffects(ek);
    9581  ek -= tkin;
    96   modifiedOriginal.SetKineticEnergy( ek*MeV );
     82  modifiedOriginal.SetKineticEnergy(ek);
    9783  et = ek + amas;
    9884  p = std::sqrt( std::abs((et-amas)*(et+amas)) );
    99   pp = modifiedOriginal.GetMomentum().mag()/MeV;
    100   if( pp > 0.0 )
    101   {
     85  pp = modifiedOriginal.GetMomentum().mag();
     86  if (pp > 0.0) {
    10287    G4ThreeVector momentum = modifiedOriginal.GetMomentum();
    10388    modifiedOriginal.SetMomentum( momentum * (p/pp) );
    10489  }
    10590  const G4double cutOff = 0.1;
    106   if( modifiedOriginal.GetKineticEnergy()/MeV <= cutOff )
    107   {
     91  if (modifiedOriginal.GetKineticEnergy() < cutOff) {
    10892    SlowProton( originalIncident, targetNucleus );
    10993    delete originalTarget;
     
    123107  vec.Initialize( 0 );
    124108
    125   Cascade( vec, vecLen,
    126            originalIncident, currentParticle, targetParticle,
    127            incidentHasChanged, targetHasChanged, quasiElastic );
    128 
    129   CalculateMomenta( vec, vecLen,
    130                     originalIncident, originalTarget, modifiedOriginal,
    131                     targetNucleus, currentParticle, targetParticle,
    132                     incidentHasChanged, targetHasChanged, quasiElastic );
     109  InitialCollision(vec, vecLen, currentParticle, targetParticle,
     110                   incidentHasChanged, targetHasChanged);
     111
     112  CalculateMomenta(vec, vecLen,
     113                   originalIncident, originalTarget, modifiedOriginal,
     114                   targetNucleus, currentParticle, targetParticle,
     115                   incidentHasChanged, targetHasChanged, quasiElastic);
    133116
    134117  SetUpChange( vec, vecLen,
     
    139122  return &theParticleChange;
    140123}
     124
    141125
    142126void
     
    146130  const G4double A = targetNucleus.GetN();    // atomic weight
    147131  const G4double Z = targetNucleus.GetZ();    // atomic number
    148 //  G4double currentKinetic = originalIncident->GetKineticEnergy()/MeV;
     132//  G4double currentKinetic = originalIncident->GetKineticEnergy();
    149133  //
    150134  // calculate Q-value of reactions
     
    194178  }
    195179}
    196  
    197 void G4RPGProtonInelastic::Cascade(
    198    G4FastVector<G4ReactionProduct,256> &vec,
    199    G4int &vecLen,
    200    const G4HadProjectile *originalIncident,
    201    G4ReactionProduct &currentParticle,
    202    G4ReactionProduct &targetParticle,
    203    G4bool &incidentHasChanged,
    204    G4bool &targetHasChanged,
    205    G4bool &quasiElastic )
     180
     181
     182// Initial Collision
     183//   selects the particle types arising from the initial collision of
     184//   the proton and target nucleon.  Secondaries are assigned to forward
     185//   and backward reaction hemispheres, but final state energies and
     186//   momenta are not calculated here.
     187
     188void
     189G4RPGProtonInelastic::InitialCollision(G4FastVector<G4ReactionProduct,256>& vec,
     190                                  G4int& vecLen,
     191                                  G4ReactionProduct& currentParticle,
     192                                  G4ReactionProduct& targetParticle,
     193                                  G4bool& incidentHasChanged,
     194                                  G4bool& targetHasChanged)
    206195{
    207   // Derived from H. Fesefeldt's original FORTRAN code CASP
    208   //
    209   // Proton undergoes interaction with nucleon within a nucleus.  Check if
    210   // it is energetically possible to produce pions/kaons.  In not, assume
    211   // nuclear excitation occurs and input particle is degraded in energy. No
    212   // other particles are produced.
    213   // If reaction is possible, find the correct number of
    214   // pions/protons/neutrons produced using an interpolation to multiplicity
    215   // data.  Replace some pions or protons/neutrons by kaons or strange
    216   // baryons according to the average multiplicity per Inelastic reaction.
    217   //
    218   // The center of mass energy is based on the initial energy, before
    219   // Fermi motion and evaporation effects are taken into account
    220   //
    221   const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
    222   const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
    223   const G4double targetMass = targetParticle.GetMass()/MeV;
    224   G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
    225                                       targetMass*targetMass +
    226                                       2.0*targetMass*etOriginal );
    227   G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
    228   if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
    229   {      // not energetically possible to produce pion(s)
    230     quasiElastic = true;
    231     return;
    232   }
    233   static G4bool first = true;
    234   const G4int numMul = 1200;
    235   const G4int numSec = 60;
    236   static G4double protmul[numMul], protnorm[numSec]; // proton constants
    237   static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
    238   // np = number of pi+, nm = number of pi-, nz = number of pi0
    239   G4int counter, nt=0, np=0, nm=0, nz=0;
    240   const G4double c = 1.25;   
    241   const G4double b[] = { 0.70, 0.35 };
    242   if( first )      // compute normalization constants, this will only be Done once
    243   {
    244     first = false;
    245     G4int i;
    246     for( i=0; i<numMul; ++i )protmul[i] = 0.0;
    247     for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
    248     counter = -1;
    249     for( np=0; np<(numSec/3); ++np )
    250     {
    251       for( nm=std::max(0,np-2); nm<=np; ++nm )
    252       {
    253         for( nz=0; nz<numSec/3; ++nz )
    254         {
    255           if( ++counter < numMul )
    256           {
    257             nt = np+nm+nz;
    258             if( nt>0 && nt<=numSec )
    259             {
    260               protmul[counter] = Pmltpc(np,nm,nz,nt,b[0],c) /
    261                 (Factorial(2-np+nm)*Factorial(np-nm) );
    262               protnorm[nt-1] += protmul[counter];
    263             }
    264           }
    265         }
     196  G4double KE = currentParticle.GetKineticEnergy()/GeV;
     197
     198  G4int mult;
     199  G4int partType;
     200  std::vector<G4int> fsTypes;
     201  G4int part1;
     202  G4int part2;
     203
     204  G4double testCharge;
     205  G4double testBaryon;
     206  G4double testStrange;
     207 
     208  // Get particle types according to incident and target types
     209 
     210  if (targetParticle.GetDefinition() == particleDef[pro]) {
     211    mult = GetMultiplicityT1(KE);
     212    fsTypes = GetFSPartTypesForPP(mult, KE);
     213
     214    part1 = fsTypes[0];
     215    part2 = fsTypes[1];
     216    currentParticle.SetDefinition(particleDef[part1]);
     217    targetParticle.SetDefinition(particleDef[part2]);
     218    if (part1 == pro) {
     219      if (part2 == neu) {
     220        if (G4UniformRand() > 0.5) {
     221          incidentHasChanged = true;
     222          targetParticle.SetDefinition(particleDef[part1]);
     223          currentParticle.SetDefinition(particleDef[part2]);
     224        } else {
     225          targetHasChanged = true;
     226        }
     227      } else if (part2 > neu && part2 < xi0) {
     228        targetHasChanged = true;
    266229      }
     230
     231    } else {  // neutron
     232      targetHasChanged = true;
     233      incidentHasChanged = true;
    267234    }
    268     for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
    269     for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
    270     counter = -1;
    271     for( np=0; np<numSec/3; ++np )
    272     {
    273       for( nm=std::max(0,np-1); nm<=(np+1); ++nm )
    274       {
    275         for( nz=0; nz<numSec/3; ++nz )
    276         {
    277           if( ++counter < numMul )
    278           {
    279             nt = np+nm+nz;
    280             if( nt>0 && nt<=numSec )
    281             {
    282               neutmul[counter] = Pmltpc(np,nm,nz,nt,b[1],c) /
    283                 (Factorial(1-np+nm)*Factorial(1+np-nm) );
    284               neutnorm[nt-1] += neutmul[counter];
    285             }
    286           }
    287         }
     235
     236    testCharge = 2.0;
     237    testBaryon = 2.0;
     238    testStrange = 0.0;
     239 
     240  } else {   // target was a neutron
     241    mult = GetMultiplicityT0(KE);
     242    fsTypes = GetFSPartTypesForPN(mult, KE);
     243
     244    part1 = fsTypes[0];
     245    part2 = fsTypes[1];
     246    currentParticle.SetDefinition(particleDef[part1]);
     247    targetParticle.SetDefinition(particleDef[part2]);
     248    if (part1 == pro) {
     249      if (part2 == pro) {
     250        targetHasChanged = true;
     251      } else if (part2 == neu) {
     252        if (G4UniformRand() > 0.5) {
     253          incidentHasChanged = true;
     254          targetHasChanged = true;
     255          targetParticle.SetDefinition(particleDef[part1]);
     256          currentParticle.SetDefinition(particleDef[part2]);
     257        }
     258      } else {  // hyperon
     259        targetHasChanged = true;
    288260      }
     261
     262    } else {  // neutron
     263      incidentHasChanged = true;
     264      if (part2 > neu && part2 < xi0) targetHasChanged = true;
    289265    }
    290     for( i=0; i<numSec; ++i )
    291     {
    292       if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
    293       if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
    294     }
    295   }   // end of initialization
    296    
    297   const G4double expxu =  82.;          // upper bound for arg. of exp
    298   const G4double expxl = -expxu;        // lower bound for arg. of exp
    299   G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
    300   G4ParticleDefinition *aProton = G4Proton::Proton();
    301   G4int ieab = static_cast<G4int>(availableEnergy*5.0/GeV);
    302   const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
    303   G4double test, w0, wp, wt, wm;
    304     if( (availableEnergy < 2.0*GeV) && (G4UniformRand() >= supp[ieab]) )
    305     {
    306       // suppress high multiplicity events at low momentum
    307       // only one pion will be produced
    308      
    309       np = nm = nz = 0;
    310       if( targetParticle.GetDefinition() == aProton )
    311       {
    312         test = std::exp( std::min( expxu, std::max(
    313          expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
    314         w0 = test/2.0;
    315         wp = test;
    316         if( G4UniformRand() < w0/(w0+wp) )
    317           nz = 1;
    318         else
    319           np = 1;
    320       }
    321       else // target is a neutron
    322       {
    323         test = std::exp( std::min( expxu, std::max(
    324          expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
    325         w0 = test;
    326         wp = test/2.0;       
    327         test = std::exp( std::min( expxu, std::max(
    328          expxl, -(-1.0+b[1])*(-1.0+b[1])/(2.0*c*c) ) ) );
    329         wm = test/2.0;
    330         wt = w0+wp+wm;
    331         wp += w0;
    332         G4double ran = G4UniformRand();
    333         if( ran < w0/wt )
    334           nz = 1;
    335         else if( ran < wp/wt )
    336           np = 1;
    337         else
    338           nm = 1;
    339       }
    340     }
    341     else // (availableEnergy >= 2.0*GeV) || (random number < supp[ieab])
    342     {
    343       G4double n, anpn;
    344       GetNormalizationConstant( availableEnergy, n, anpn );
    345       G4double ran = G4UniformRand();
    346       G4double dum, excs = 0.0;
    347       if( targetParticle.GetDefinition() == aProton )
    348       {
    349         counter = -1;
    350         for( np=0; np<numSec/3 && ran>=excs; ++np )
    351         {
    352           for( nm=std::max(0,np-2); nm<=np && ran>=excs; ++nm )
    353           {
    354             for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
    355             {
    356               if( ++counter < numMul )
    357               {
    358                 nt = np+nm+nz;
    359                 if( nt>0 && nt<=numSec )
    360                 {
    361                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
    362                   dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
    363                   if( std::fabs(dum) < 1.0 )
    364                   {
    365                     if( test >= 1.0e-10 )excs += dum*test;
    366                   } else {
    367                     excs += dum*test;
    368                   }
    369                 }
    370               }
    371             }
    372           }
    373         }
    374         if( ran >= excs )  // 3 previous loops continued to the end
    375         {
    376           quasiElastic = true;
    377           return;
    378         }
    379       }
    380       else  // target must be a neutron
    381       {
    382         counter = -1;
    383         for( np=0; np<numSec/3 && ran>=excs; ++np )
    384         {
    385           for( nm=std::max(0,np-1); nm<=(np+1) && ran>=excs; ++nm )
    386           {
    387             for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
    388             {
    389               if( ++counter < numMul )
    390               {
    391                 nt = np+nm+nz;
    392                 if( nt>0 && nt<=numSec )
    393                 {
    394                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
    395                   dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
    396                   if( std::fabs(dum) < 1.0 )
    397                   {
    398                     if( test >= 1.0e-10 )excs += dum*test;
    399                   } else {
    400                     excs += dum*test;
    401                   }
    402                 }
    403               }
    404             }
    405           }
    406         }
    407         if( ran >= excs )  // 3 previous loops continued to the end
    408         {
    409           quasiElastic = true;
    410           return;
    411         }
    412       }
    413       np--; nm--; nz--;
    414     }
    415     if( targetParticle.GetDefinition() == aProton )
    416     {
    417       switch( np-nm )
    418       {
    419        case 1:
    420          if( G4UniformRand() < 0.5 )
    421          {
    422            targetParticle.SetDefinitionAndUpdateE( aNeutron );
    423            targetHasChanged = true;
    424          } else {
    425            currentParticle.SetDefinitionAndUpdateE( aNeutron );
    426            incidentHasChanged = true;
    427          }
    428          break;
    429        case 2:
    430          currentParticle.SetDefinitionAndUpdateE( aNeutron );
    431          targetParticle.SetDefinitionAndUpdateE( aNeutron );
    432          incidentHasChanged = true;
    433          targetHasChanged = true;
    434          break;
    435        default:
    436          break;
    437       }
    438     }
    439     else  // target is a neutron
    440     {
    441       switch( np-nm )
    442       {
    443        case 0:
    444          if( G4UniformRand() < 0.333333 )
    445          {
    446            currentParticle.SetDefinitionAndUpdateE( aNeutron );
    447            targetParticle.SetDefinitionAndUpdateE( aProton );
    448            incidentHasChanged = true;
    449            targetHasChanged = true;
    450          }
    451          break;
    452        case 1:
    453          currentParticle.SetDefinitionAndUpdateE( aNeutron );
    454          incidentHasChanged = true;
    455          break;
    456        default:
    457          targetParticle.SetDefinitionAndUpdateE( aProton );
    458          targetHasChanged = true;
    459          break;
    460       }
    461     }
    462     SetUpPions( np, nm, nz, vec, vecLen );
    463     return;
    464   }
    465 
    466  /* end of file */
    467  
     266
     267    testCharge = 1.0;
     268    testBaryon = 2.0;
     269    testStrange = 0.0;
     270  }
     271
     272  // Remove incident and target from fsTypes
     273 
     274  fsTypes.erase(fsTypes.begin());
     275  fsTypes.erase(fsTypes.begin());
     276
     277  // Remaining particles are secondaries.  Put them into vec.
     278 
     279  G4ReactionProduct* rp(0);
     280  for(G4int i=0; i < mult-2; ++i ) {
     281    partType = fsTypes[i];
     282    rp = new G4ReactionProduct();
     283    rp->SetDefinition(particleDef[partType]);
     284    (G4UniformRand() < 0.5) ? rp->SetSide(-1) : rp->SetSide(1);
     285    vec.SetElement(vecLen++, rp);
     286  }
     287
     288  // Check conservation of charge, strangeness, baryon number
     289 
     290  CheckQnums(vec, vecLen, currentParticle, targetParticle,
     291             testCharge, testBaryon, testStrange);
     292 
     293  return;
     294}
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGReaction.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGReaction.cc,v 1.1 2007/07/18 21:04:21 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGReaction.cc,v 1.4 2008/05/05 21:21:55 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929
     
    5858                       const G4double edta,            // GeV
    5959                       const G4int ndta,
    60                        const G4double sprob,
    61                        const G4double kineticMinimum,  // GeV
    62                        const G4double kineticFactor,   // GeV
    63                        const G4ReactionProduct &modifiedOriginal,
     60                       const G4ReactionProduct& modifiedOriginal,
    6461                       G4int PinNucleus,
    6562                       G4int NinNucleus,
    66                        const G4Nucleus &targetNucleus,
    67                        G4FastVector<G4ReactionProduct,256> &vec,
    68                        G4int &vecLen )
     63                       const G4Nucleus& targetNucleus,
     64                       G4FastVector<G4ReactionProduct,256>& vec,
     65                       G4int& vecLen)
    6966{
    7067  // derived from original FORTRAN code in GENXPT and TWOCLU by H. Fesefeldt
     
    7471  // epnb is the kinetic energy available for proton/neutron black track particles
    7572  // edta is the kinetic energy available for deuteron/triton/alpha particles
    76   //
    77    
    78   G4ParticleDefinition *aProton = G4Proton::Proton();
    79   G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
    80   G4ParticleDefinition *aDeuteron = G4Deuteron::Deuteron();
    81   G4ParticleDefinition *aTriton = G4Triton::Triton();
    82   G4ParticleDefinition *anAlpha = G4Alpha::Alpha();
    83    
    84     const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/MeV;
    85     const G4double atomicWeight = targetNucleus.GetN();
    86     const G4double atomicNumber = targetNucleus.GetZ();
    87    
    88     const G4double ika1 = 3.6;
    89     const G4double ika2 = 35.56;
    90     const G4double ika3 = 6.45;
    91    
    92     G4int i;
    93     G4double pp;
    94     G4double kinCreated = 0;
    95     G4double cfa = 0.025*((atomicWeight-1.0)/120.0) * std::exp(-(atomicWeight-1.0)/120.0);
    96 
    97     // First add protons and neutrons to final state
    98 
    99     if (npnb > 0)
    100     {
    101       G4double backwardKinetic = 0.0;
    102       G4int local_npnb = npnb;
    103       for( i=0; i<npnb; ++i ) if( G4UniformRand() < sprob ) local_npnb--;
    104       G4double local_epnb = epnb;
    105       if (ndta == 0) local_epnb += edta;   // Retrieve unused kinetic energy
    106       G4double ekin = local_epnb/std::max(1,local_npnb);
    107      
    108       for( i=0; i<local_npnb; ++i )
    109       {
    110         G4ReactionProduct * p1 = new G4ReactionProduct();
    111         if( backwardKinetic > local_epnb )
    112         {
    113           delete p1;
    114           break;   
    115         }
    116         G4double ran = G4UniformRand();
    117         G4double kinetic = -ekin*std::log(ran) - cfa*(1.0+0.5*normal());
    118         if( kinetic < 0.0 )kinetic = -0.010*std::log(ran);
    119         backwardKinetic += kinetic;
    120         if( backwardKinetic > local_epnb )
    121            kinetic = std::max( kineticMinimum, local_epnb-(backwardKinetic-kinetic) );
    122 
    123         if (G4UniformRand() > (1.0-atomicNumber/atomicWeight)) {
    124 
    125           // Boil off a proton if there are any left, otherwise a neutron
    126 
    127           if (PinNucleus > 0) {
    128             p1->SetDefinition( aProton );
    129             PinNucleus--;
    130           } else if (NinNucleus > 0) {
    131             p1->SetDefinition( aNeutron );
    132             NinNucleus--;
    133           } else {
    134             delete p1;
    135             break;     // no nucleons left in nucleus
    136           }
     73
     74  G4ParticleDefinition* aProton = G4Proton::Proton();
     75  G4ParticleDefinition* aNeutron = G4Neutron::Neutron();
     76  G4ParticleDefinition* aDeuteron = G4Deuteron::Deuteron();
     77  G4ParticleDefinition* aTriton = G4Triton::Triton();
     78  G4ParticleDefinition* anAlpha = G4Alpha::Alpha();
     79   
     80  const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/MeV;
     81  const G4double atomicWeight = targetNucleus.GetN();
     82  const G4double atomicNumber = targetNucleus.GetZ();
     83   
     84  const G4double ika1 = 3.6;
     85  const G4double ika2 = 35.56;
     86  const G4double ika3 = 6.45;
     87   
     88  G4int i;
     89  G4double pp;
     90  G4double kinetic = 0;
     91  G4double kinCreated = 0;
     92  //  G4double cfa = 0.025*((atomicWeight-1.0)/120.0) * std::exp(-(atomicWeight-1.0)/120.0);
     93  G4double remainingE = 0;
     94
     95  // First add protons and neutrons to final state
     96  if (npnb > 0) {
     97    //    G4double backwardKinetic = 0.0;
     98    G4int local_npnb = npnb;
     99    // DHW: does not conserve energy  for (i = 0; i < npnb; ++i) if (G4UniformRand() < sprob) local_npnb--;
     100    local_npnb = std::min(PinNucleus + NinNucleus , local_npnb);
     101    G4double local_epnb = epnb;
     102    if (ndta == 0) local_epnb += edta;   // Retrieve unused kinetic energy
     103    //    G4double ekin = local_epnb/std::max(1,local_npnb);
     104
     105    remainingE = local_epnb;
     106    for (i = 0; i < local_npnb; ++i)
     107    {
     108      G4ReactionProduct* p1 = new G4ReactionProduct();
     109      //      if( backwardKinetic > local_epnb ) {
     110      //        delete p1;
     111      //        break;   
     112      //      }
     113
     114      //      G4double ran = G4UniformRand();
     115      //      G4double kinetic = -ekin*std::log(ran) - cfa*(1.0+0.5*normal());
     116      //      if( kinetic < 0.0 )kinetic = -0.010*std::log(ran);
     117      //      backwardKinetic += kinetic;
     118      //      if( backwardKinetic > local_epnb )
     119      // kinetic = std::max( kineticMinimum, local_epnb-(backwardKinetic-kinetic) );
     120
     121      if (G4UniformRand() > (1.0-atomicNumber/atomicWeight)) {
     122
     123        // Boil off a proton if there are any left, otherwise a neutron
     124
     125        if (PinNucleus > 0) {
     126          p1->SetDefinition( aProton );
     127          PinNucleus--;
    137128        } else {
    138 
    139           // Boil off a neutron if there are any left, otherwise a proton
    140 
    141           if (NinNucleus > 0) {
    142             p1->SetDefinition( aNeutron );
    143             NinNucleus--;
    144           } else if (PinNucleus > 0) {
    145             p1->SetDefinition( aProton );
    146             PinNucleus--;
    147           } else {
    148             delete p1;
    149             break;     // no nucleons left in nucleus
    150           }
    151         }
    152 
    153         vec.SetElement( vecLen, p1 );
    154         G4double cost = G4UniformRand() * 2.0 - 1.0;
    155         G4double sint = std::sqrt(std::fabs(1.0-cost*cost));
    156         G4double phi = twopi * G4UniformRand();
    157         vec[vecLen]->SetNewlyAdded( true );
    158         vec[vecLen]->SetKineticEnergy( kinetic*GeV );
    159         kinCreated+=kinetic;
    160         pp = vec[vecLen]->GetTotalMomentum()/MeV;
    161         vec[vecLen]->SetMomentum( pp*sint*std::sin(phi)*MeV,
    162                                     pp*sint*std::cos(phi)*MeV,
    163                                     pp*cost*MeV );
    164         vecLen++;
    165         // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    166       }
    167 
    168       if (NinNucleus > 0) {
    169         if( (atomicWeight >= 10.0) && (ekOriginal <= 2.0*GeV) )
     129          p1->SetDefinition( aNeutron );
     130          NinNucleus--;
     131          //        } else {
     132          //          delete p1;
     133          //          break;     // no nucleons left in nucleus
     134        }
     135      } else {
     136
     137        // Boil off a neutron if there are any left, otherwise a proton
     138
     139        if (NinNucleus > 0) {
     140          p1->SetDefinition( aNeutron );
     141          NinNucleus--;
     142        } else {
     143          p1->SetDefinition( aProton );
     144          PinNucleus--;
     145          //        } else {
     146          //          delete p1;
     147          //          break;     // no nucleons left in nucleus
     148        }
     149      }
     150
     151      if (i < local_npnb - 1) {
     152        kinetic = remainingE*G4UniformRand();
     153        remainingE -= kinetic;
     154      } else {
     155        kinetic = remainingE;
     156      }
     157
     158      vec.SetElement( vecLen, p1 );
     159      G4double cost = G4UniformRand() * 2.0 - 1.0;
     160      G4double sint = std::sqrt(std::fabs(1.0-cost*cost));
     161      G4double phi = twopi * G4UniformRand();
     162      vec[vecLen]->SetNewlyAdded( true );
     163      vec[vecLen]->SetKineticEnergy( kinetic*GeV );
     164      kinCreated+=kinetic;
     165      pp = vec[vecLen]->GetTotalMomentum();
     166      vec[vecLen]->SetMomentum(pp*sint*std::sin(phi),
     167                               pp*sint*std::cos(phi),
     168                               pp*cost );
     169      vecLen++;
     170    }
     171
     172    if (NinNucleus > 0) {
     173      if( (atomicWeight >= 10.0) && (ekOriginal <= 2.0*GeV) )
     174      {
     175        G4double ekw = ekOriginal/GeV;
     176        G4int ika, kk = 0;
     177        if( ekw > 1.0 )ekw *= ekw;
     178        ekw = std::max( 0.1, ekw );
     179        ika = G4int(ika1*std::exp((atomicNumber*atomicNumber/
     180                                           atomicWeight-ika2)/ika3)/ekw);
     181        if( ika > 0 )
    170182        {
    171           G4double ekw = ekOriginal/GeV;
    172           G4int ika, kk = 0;
    173           if( ekw > 1.0 )ekw *= ekw;
    174           ekw = std::max( 0.1, ekw );
    175           ika = G4int(ika1*std::exp((atomicNumber*atomicNumber/
    176                                              atomicWeight-ika2)/ika3)/ekw);
    177           if( ika > 0 )
     183          for( i=(vecLen-1); i>=0; --i )
    178184          {
    179             for( i=(vecLen-1); i>=0; --i )
     185            if( (vec[i]->GetDefinition() == aProton) && vec[i]->GetNewlyAdded() )
    180186            {
    181               if( (vec[i]->GetDefinition() == aProton) && vec[i]->GetNewlyAdded() )
    182               {
    183                 vec[i]->SetDefinitionAndUpdateE( aNeutron );  // modified 22-Oct-97
    184                 PinNucleus++;
    185                 NinNucleus--;
    186                 if( ++kk > ika )break;
    187               }
     187              vec[i]->SetDefinitionAndUpdateE( aNeutron );  // modified 22-Oct-97
     188              PinNucleus++;
     189              NinNucleus--;
     190              if( ++kk > ika )break;
    188191            }
    189192          }
    190193        }
    191       } // if (NinNucleus >0)
    192     } // if (npnb > 0)
    193 
    194     //  Next try to add deuterons, tritons and alphas to final state
    195 
    196     if (ndta > 0)
    197     {
    198       G4double backwardKinetic = 0.0;
    199       G4int local_ndta=ndta;
    200       // DHW      for( i=0; i<ndta; ++i )if( G4UniformRand() < sprob )local_ndta--;
    201       G4double local_edta = edta;
    202       if (npnb == 0) local_edta += epnb;  // Retrieve unused kinetic energy
    203       G4double ekin = local_edta/std::max(1,local_ndta);
    204 
    205       for( i=0; i<local_ndta; ++i )
    206       {
    207         G4ReactionProduct *p2 = new G4ReactionProduct();
    208         if( backwardKinetic > local_edta )
    209         {
     194      }
     195    } // if (NinNucleus >0)
     196  } // if (npnb > 0)
     197
     198  //  Next try to add deuterons, tritons and alphas to final state
     199
     200  G4double ran = 0;
     201  if (ndta > 0) {
     202    //    G4double backwardKinetic = 0.0;
     203    G4int local_ndta=ndta;
     204    // DHW: does not conserve energy  for (i = 0; i < ndta; ++i) if (G4UniformRand() < sprob) local_ndta--;
     205    G4double local_edta = edta;
     206    if (npnb == 0) local_edta += epnb;  // Retrieve unused kinetic energy
     207    //    G4double ekin = local_edta/std::max(1,local_ndta);
     208
     209    remainingE = local_edta;
     210    for (i = 0; i < local_ndta; ++i) {
     211      G4ReactionProduct* p2 = new G4ReactionProduct();
     212      //        if( backwardKinetic > local_edta ) {
     213      //          delete p2;
     214      //          break;
     215      //        }
     216
     217      //        G4double ran = G4UniformRand();
     218      //        G4double kinetic = -ekin*std::log(ran)-cfa*(1.+0.5*normal());
     219      //        if( kinetic < 0.0 )kinetic = kineticFactor*std::log(ran);
     220      //        backwardKinetic += kinetic;
     221      //        if( backwardKinetic > local_edta )kinetic = local_edta-(backwardKinetic-kinetic);
     222      //        if( kinetic < 0.0 )kinetic = kineticMinimum;
     223
     224      ran = G4UniformRand();
     225      if (ran < 0.60) {
     226        if (PinNucleus > 0 && NinNucleus > 0) {
     227          p2->SetDefinition( aDeuteron );
     228          PinNucleus--;
     229          NinNucleus--;
     230        } else if (NinNucleus > 0) {
     231          p2->SetDefinition( aNeutron );
     232          NinNucleus--;
     233        } else if (PinNucleus > 0) {
     234          p2->SetDefinition( aProton );
     235          PinNucleus--;
     236        } else {
    210237          delete p2;
    211238          break;
    212239        }
    213         G4double ran = G4UniformRand();
    214         G4double kinetic = -ekin*std::log(ran)-cfa*(1.+0.5*normal());
    215         if( kinetic < 0.0 )kinetic = kineticFactor*std::log(ran);
    216         backwardKinetic += kinetic;
    217         if( backwardKinetic > local_edta )kinetic = local_edta-(backwardKinetic-kinetic);
    218         if( kinetic < 0.0 )kinetic = kineticMinimum;
    219         G4double cost = 2.0*G4UniformRand() - 1.0;
    220         G4double sint = std::sqrt(std::max(0.0,(1.0-cost*cost)));
    221         G4double phi = twopi*G4UniformRand();
    222         ran = G4UniformRand();
    223         if (ran < 0.60) {
    224           if (PinNucleus > 0 && NinNucleus > 0) {
    225             p2->SetDefinition( aDeuteron );
    226             PinNucleus--;
    227             NinNucleus--;
    228           } else if (NinNucleus > 0) {
    229             p2->SetDefinition( aNeutron );
    230             NinNucleus--;
    231           } else if (PinNucleus > 0) {
    232             p2->SetDefinition( aProton );
    233             PinNucleus--;
    234           } else {
    235             delete p2;
    236             break;
    237           }
    238         } else if (ran < 0.90) {
    239           if (PinNucleus > 0 && NinNucleus > 1) {
    240             p2->SetDefinition( aTriton );
    241             PinNucleus--;
    242             NinNucleus -= 2;
    243           } else if (PinNucleus > 0 && NinNucleus > 0) {
    244             p2->SetDefinition( aDeuteron );
    245             PinNucleus--;
    246             NinNucleus--;
    247           } else if (NinNucleus > 0) {
    248             p2->SetDefinition( aNeutron );
    249             NinNucleus--;
    250           } else if (PinNucleus > 0) {
    251             p2->SetDefinition( aProton );
    252             PinNucleus--;
    253           } else {
    254             delete p2;
    255             break;
    256           }
    257         } else {
    258           if (PinNucleus > 1 && NinNucleus > 1) {
    259             p2->SetDefinition( anAlpha );
    260             PinNucleus -= 2;
    261             NinNucleus -= 2;
    262           } else if (PinNucleus > 0 && NinNucleus > 1) {
    263             p2->SetDefinition( aTriton );
    264             PinNucleus--;
    265             NinNucleus -= 2;
    266           } else if (PinNucleus > 0 && NinNucleus > 0) {
    267             p2->SetDefinition( aDeuteron );
    268             PinNucleus--;
    269             NinNucleus--;
    270           } else if (NinNucleus > 0) {
    271             p2->SetDefinition( aNeutron );
    272             NinNucleus--;
    273           } else if (PinNucleus > 0) {
    274             p2->SetDefinition( aProton );
    275             PinNucleus--;
    276           } else {
    277             delete p2;
    278             break;
    279           }
    280         }
    281 
    282         vec.SetElement( vecLen, p2 );
    283         vec[vecLen]->SetNewlyAdded( true );
    284         vec[vecLen]->SetKineticEnergy( kinetic*GeV );
    285         kinCreated+=kinetic;
    286         pp = vec[vecLen]->GetTotalMomentum()/MeV;
    287         vec[vecLen++]->SetMomentum( pp*sint*std::sin(phi)*MeV,
    288                                     pp*sint*std::cos(phi)*MeV,
    289                                     pp*cost*MeV );
    290       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    291       }
    292     } // if (ndta > 0)
    293 
    294   //    G4double delta = epnb+edta - kinCreated;
     240      } else if (ran < 0.90) {
     241        if (PinNucleus > 0 && NinNucleus > 1) {
     242          p2->SetDefinition( aTriton );
     243          PinNucleus--;
     244          NinNucleus -= 2;
     245        } else if (PinNucleus > 0 && NinNucleus > 0) {
     246          p2->SetDefinition( aDeuteron );
     247          PinNucleus--;
     248          NinNucleus--;
     249        } else if (NinNucleus > 0) {
     250          p2->SetDefinition( aNeutron );
     251          NinNucleus--;
     252        } else if (PinNucleus > 0) {
     253          p2->SetDefinition( aProton );
     254          PinNucleus--;
     255        } else {
     256          delete p2;
     257          break;
     258        }
     259      } else {
     260        if (PinNucleus > 1 && NinNucleus > 1) {
     261          p2->SetDefinition( anAlpha );
     262          PinNucleus -= 2;
     263          NinNucleus -= 2;
     264        } else if (PinNucleus > 0 && NinNucleus > 1) {
     265          p2->SetDefinition( aTriton );
     266          PinNucleus--;
     267          NinNucleus -= 2;
     268        } else if (PinNucleus > 0 && NinNucleus > 0) {
     269          p2->SetDefinition( aDeuteron );
     270          PinNucleus--;
     271          NinNucleus--;
     272        } else if (NinNucleus > 0) {
     273          p2->SetDefinition( aNeutron );
     274          NinNucleus--;
     275        } else if (PinNucleus > 0) {
     276          p2->SetDefinition( aProton );
     277          PinNucleus--;
     278        } else {
     279          delete p2;
     280          break;
     281        }
     282      }
     283
     284      if (i < local_ndta - 1) {
     285        kinetic = remainingE*G4UniformRand();
     286        remainingE -= kinetic;
     287      } else {
     288        kinetic = remainingE;
     289      }
     290
     291      vec.SetElement( vecLen, p2 );
     292      G4double cost = 2.0*G4UniformRand() - 1.0;
     293      G4double sint = std::sqrt(std::max(0.0,(1.0-cost*cost)));
     294      G4double phi = twopi*G4UniformRand();
     295      vec[vecLen]->SetNewlyAdded( true );
     296      vec[vecLen]->SetKineticEnergy( kinetic*GeV );
     297      kinCreated+=kinetic;
     298
     299      pp = vec[vecLen]->GetTotalMomentum();
     300      vec[vecLen]->SetMomentum( pp*sint*std::sin(phi),
     301                                pp*sint*std::cos(phi),
     302                                pp*cost );
     303      vecLen++;
     304    }
     305  } // if (ndta > 0)
    295306}
    296307
    297308 
    298 G4double G4RPGReaction::GenerateNBodyEvent(
    299   const G4double totalEnergy,                // MeV
    300   const G4bool constantCrossSection,
    301   G4FastVector<G4ReactionProduct,256> &vec,
    302   G4int &vecLen )
     309G4double
     310G4RPGReaction::GenerateNBodyEvent(const G4double totalEnergy,       // MeV
     311                                  const G4bool constantCrossSection,
     312                                  G4FastVector<G4ReactionProduct,256>& vec,
     313                                  G4int &vecLen)
    303314{
    304     G4int i;
    305     const G4double expxu =  82.;           // upper bound for arg. of exp
    306     const G4double expxl = -expxu;         // lower bound for arg. of exp
    307     if( vecLen < 2 )
    308     {
    309       G4cerr << "*** Error in G4RPGReaction::GenerateNBodyEvent" << G4endl;
    310       G4cerr << "    number of particles < 2" << G4endl;
    311       G4cerr << "totalEnergy = " << totalEnergy << "MeV, vecLen = " << vecLen << G4endl;
    312       return -1.0;
    313     }
    314     G4double mass[18];    // mass of each particle
    315     G4double energy[18];  // total energy of each particle
    316     G4double pcm[3][18];           // pcm is an array with 3 rows and vecLen columns
    317    
    318     G4double totalMass = 0.0;
    319     G4double extraMass = 0;
    320     G4double sm[18];
    321    
    322     for( i=0; i<vecLen; ++i )
    323     {
    324       mass[i] = vec[i]->GetMass()/GeV;
    325       if(vec[i]->GetSide() == -2) extraMass+=vec[i]->GetMass()/GeV;
    326       vec[i]->SetMomentum( 0.0, 0.0, 0.0 );
    327       pcm[0][i] = 0.0;      // x-momentum of i-th particle
    328       pcm[1][i] = 0.0;      // y-momentum of i-th particle
    329       pcm[2][i] = 0.0;      // z-momentum of i-th particle
    330       energy[i] = mass[i];  // total energy of i-th particle
    331       totalMass += mass[i];
    332       sm[i] = totalMass;
    333     }
    334     G4double totalE = totalEnergy/GeV;
    335     if( totalMass > totalE )
    336     {
    337       //G4cerr << "*** Error in G4RPGReaction::GenerateNBodyEvent" << G4endl;
    338       //G4cerr << "    total mass (" << totalMass*GeV << "MeV) > total energy ("
    339       //     << totalEnergy << "MeV)" << G4endl;
    340       totalE = totalMass;
    341       return -1.0;
    342     }
    343     G4double kineticEnergy = totalE - totalMass;
    344     G4double emm[18];
    345     //G4double *emm = new G4double [vecLen];
    346     emm[0] = mass[0];
    347     emm[vecLen-1] = totalE;
    348     if( vecLen > 2 )          // the random numbers are sorted
    349     {
    350       G4double ran[18];
    351       for( i=0; i<vecLen; ++i )ran[i] = G4UniformRand();
    352       for( i=0; i<vecLen-2; ++i )
    353       {
    354         for( G4int j=vecLen-2; j>i; --j )
    355         {
    356           if( ran[i] > ran[j] )
    357           {
    358             G4double temp = ran[i];
    359             ran[i] = ran[j];
    360             ran[j] = temp;
    361           }
    362         }
    363       }
    364       for( i=1; i<vecLen-1; ++i )emm[i] = ran[i-1]*kineticEnergy + sm[i];
    365     }
    366     //   Weight is the sum of logarithms of terms instead of the product of terms
    367     G4bool lzero = true;   
    368     G4double wtmax = 0.0;
    369     if( constantCrossSection )     // this is KGENEV=1 in PHASP
    370     {
    371       G4double emmax = kineticEnergy + mass[0];
    372       G4double emmin = 0.0;
     315  G4int i;
     316  const G4double expxu =  82.;           // upper bound for arg. of exp
     317  const G4double expxl = -expxu;         // lower bound for arg. of exp
     318
     319  if (vecLen < 2) {
     320    G4cerr << "*** Error in G4RPGReaction::GenerateNBodyEvent" << G4endl;
     321    G4cerr << "    number of particles < 2" << G4endl;
     322    G4cerr << "totalEnergy = " << totalEnergy << "MeV, vecLen = " << vecLen << G4endl;
     323    return -1.0;
     324  }
     325
     326  G4double mass[18];    // mass of each particle
     327  G4double energy[18];  // total energy of each particle
     328  G4double pcm[3][18];           // pcm is an array with 3 rows and vecLen columns
     329   
     330  G4double totalMass = 0.0;
     331  G4double extraMass = 0;
     332  G4double sm[18];
     333   
     334  for (i=0; i<vecLen; ++i) {
     335    mass[i] = vec[i]->GetMass()/GeV;
     336    if(vec[i]->GetSide() == -2) extraMass+=vec[i]->GetMass()/GeV;
     337    vec[i]->SetMomentum( 0.0, 0.0, 0.0 );
     338    pcm[0][i] = 0.0;      // x-momentum of i-th particle
     339    pcm[1][i] = 0.0;      // y-momentum of i-th particle
     340    pcm[2][i] = 0.0;      // z-momentum of i-th particle
     341    energy[i] = mass[i];  // total energy of i-th particle
     342    totalMass += mass[i];
     343    sm[i] = totalMass;
     344  }
     345
     346  G4double totalE = totalEnergy/GeV;
     347  if (totalMass > totalE) {
     348    //G4cerr << "*** Error in G4RPGReaction::GenerateNBodyEvent" << G4endl;
     349    //G4cerr << "    total mass (" << totalMass*GeV << "MeV) > total energy ("
     350    //     << totalEnergy << "MeV)" << G4endl;
     351    totalE = totalMass;
     352    return -1.0;
     353  }
     354
     355  G4double kineticEnergy = totalE - totalMass;
     356  G4double emm[18];
     357  emm[0] = mass[0];
     358  emm[vecLen-1] = totalE;
     359
     360  if (vecLen > 2) {          // the random numbers are sorted
     361    G4double ran[18];
     362    for( i=0; i<vecLen; ++i )ran[i] = G4UniformRand();
     363    for (i=0; i<vecLen-2; ++i) {
     364      for (G4int j=vecLen-2; j>i; --j) {
     365        if (ran[i] > ran[j]) {
     366          G4double temp = ran[i];
     367          ran[i] = ran[j];
     368          ran[j] = temp;
     369        }
     370      }
     371    }
     372    for( i=1; i<vecLen-1; ++i )emm[i] = ran[i-1]*kineticEnergy + sm[i];
     373  }
     374
     375  // Weight is the sum of logarithms of terms instead of the product of terms
     376
     377  G4bool lzero = true;   
     378  G4double wtmax = 0.0;
     379  if (constantCrossSection) {
     380    G4double emmax = kineticEnergy + mass[0];
     381    G4double emmin = 0.0;
    373382      for( i=1; i<vecLen; ++i )
    374383      {
     
    394403      else
    395404        wtmax = expxu;
    396     }
    397     else
    398     {
     405  } else {
    399406      //   ffq(n) = pi*(2*pi)^(n-2)/(n-2)!
    400407      const G4double ffq[18] = { 0., 3.141592, 19.73921, 62.01255, 129.8788, 204.0131,
     
    403410                                 12.0006,   5.3858,   2.2560,   0.8859 };
    404411      wtmax = std::log( std::pow( kineticEnergy, vecLen-2 ) * ffq[vecLen-1] / totalE );
    405     }
    406     lzero = true;
    407     G4double pd[50];
    408     //G4double *pd = new G4double [vecLen-1];
     412  }
     413
     414  // Calculate momenta for secondaries
     415
     416  lzero = true;
     417  G4double pd[50];
     418
    409419    for( i=0; i<vecLen-1; ++i )
    410420    {
     
    475485      }
    476486    }
    477     for( i=0; i<vecLen; ++i )
    478     {
    479       vec[i]->SetMomentum( pcm[0][i]*GeV, pcm[1][i]*GeV, pcm[2][i]*GeV );
    480       vec[i]->SetTotalEnergy( energy[i]*GeV );
    481     }
    482 
    483       // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    484     return weight;
    485   }
     487
     488  for (i=0; i<vecLen; ++i) {
     489    vec[i]->SetMomentum( pcm[0][i]*GeV, pcm[1][i]*GeV, pcm[2][i]*GeV );
     490    vec[i]->SetTotalEnergy( energy[i]*GeV );
     491  }
     492
     493  return weight;
     494}
     495
    486496 
     497G4double
     498G4RPGReaction::GenerateNBodyEventT(const G4double totalEnergy,
     499                                   const G4bool constantCrossSection,
     500                                   std::vector<G4ReactionProduct*>& tempList)
     501{
     502  G4int i;
     503  const G4double expxu =  82.;           // upper bound for arg. of exp
     504  const G4double expxl = -expxu;         // lower bound for arg. of exp
     505  G4int listLen = tempList.size();
     506
     507  if (listLen < 2) {
     508    G4cerr << "*** Error in G4RPGReaction::GenerateNBodyEvent" << G4endl;
     509    G4cerr << "    number of particles < 2" << G4endl;
     510    G4cerr << "totalEnergy = " << totalEnergy << "MeV, listLen = " << listLen << G4endl;
     511    return -1.0;
     512  }
     513
     514  G4double mass[18];    // mass of each particle
     515  G4double energy[18];  // total energy of each particle
     516  G4double pcm[3][18];           // pcm is an array with 3 rows and listLen columns
     517   
     518  G4double totalMass = 0.0;
     519  G4double extraMass = 0;
     520  G4double sm[18];
     521   
     522  for (i=0; i<listLen; ++i) {
     523    mass[i] = tempList[i]->GetMass()/GeV;
     524    if(tempList[i]->GetSide() == -2) extraMass+=tempList[i]->GetMass()/GeV;
     525    tempList[i]->SetMomentum( 0.0, 0.0, 0.0 );
     526    pcm[0][i] = 0.0;      // x-momentum of i-th particle
     527    pcm[1][i] = 0.0;      // y-momentum of i-th particle
     528    pcm[2][i] = 0.0;      // z-momentum of i-th particle
     529    energy[i] = mass[i];  // total energy of i-th particle
     530    totalMass += mass[i];
     531    sm[i] = totalMass;
     532  }
     533
     534  G4double totalE = totalEnergy/GeV;
     535  if (totalMass > totalE) {
     536    totalE = totalMass;
     537    return -1.0;
     538  }
     539
     540  G4double kineticEnergy = totalE - totalMass;
     541  G4double emm[18];
     542  emm[0] = mass[0];
     543  emm[listLen-1] = totalE;
     544
     545  if (listLen > 2) {          // the random numbers are sorted
     546    G4double ran[18];
     547    for( i=0; i<listLen; ++i )ran[i] = G4UniformRand();
     548    for (i=0; i<listLen-2; ++i) {
     549      for (G4int j=listLen-2; j>i; --j) {
     550        if (ran[i] > ran[j]) {
     551          G4double temp = ran[i];
     552          ran[i] = ran[j];
     553          ran[j] = temp;
     554        }
     555      }
     556    }
     557    for( i=1; i<listLen-1; ++i )emm[i] = ran[i-1]*kineticEnergy + sm[i];
     558  }
     559
     560  // Weight is the sum of logarithms of terms instead of the product of terms
     561
     562  G4bool lzero = true;   
     563  G4double wtmax = 0.0;
     564  if (constantCrossSection) {
     565    G4double emmax = kineticEnergy + mass[0];
     566    G4double emmin = 0.0;
     567      for( i=1; i<listLen; ++i )
     568      {
     569        emmin += mass[i-1];
     570        emmax += mass[i];
     571        G4double wtfc = 0.0;
     572        if( emmax*emmax > 0.0 )
     573        {
     574          G4double arg = emmax*emmax
     575            + (emmin*emmin-mass[i]*mass[i])*(emmin*emmin-mass[i]*mass[i])/(emmax*emmax)
     576            - 2.0*(emmin*emmin+mass[i]*mass[i]);
     577          if( arg > 0.0 )wtfc = 0.5*std::sqrt( arg );
     578        }
     579        if( wtfc == 0.0 )
     580        {
     581          lzero = false;
     582          break;
     583        }
     584        wtmax += std::log( wtfc );
     585      }
     586      if( lzero )
     587        wtmax = -wtmax;
     588      else
     589        wtmax = expxu;
     590  } else {
     591      //   ffq(n) = pi*(2*pi)^(n-2)/(n-2)!
     592      const G4double ffq[18] = { 0., 3.141592, 19.73921, 62.01255, 129.8788, 204.0131,
     593                                 256.3704, 268.4705, 240.9780, 189.2637,
     594                                 132.1308,  83.0202,  47.4210,  24.8295,
     595                                 12.0006,   5.3858,   2.2560,   0.8859 };
     596      wtmax = std::log( std::pow( kineticEnergy, listLen-2 ) * ffq[listLen-1] / totalE );
     597  }
     598
     599  // Calculate momenta for secondaries
     600
     601  lzero = true;
     602  G4double pd[50];
     603
     604    for( i=0; i<listLen-1; ++i )
     605    {
     606      pd[i] = 0.0;
     607      if( emm[i+1]*emm[i+1] > 0.0 )
     608      {
     609        G4double arg = emm[i+1]*emm[i+1]
     610          + (emm[i]*emm[i]-mass[i+1]*mass[i+1])*(emm[i]*emm[i]-mass[i+1]*mass[i+1])
     611            /(emm[i+1]*emm[i+1])
     612          - 2.0*(emm[i]*emm[i]+mass[i+1]*mass[i+1]);
     613        if( arg > 0.0 )pd[i] = 0.5*std::sqrt( arg );
     614      }
     615      if( pd[i] <= 0.0 )    //  changed from  ==  on 02 April 98
     616        lzero = false;
     617      else
     618        wtmax += std::log( pd[i] );
     619    }
     620    G4double weight = 0.0;           // weight is returned by GenerateNBodyEvent
     621    if( lzero )weight = std::exp( std::max(std::min(wtmax,expxu),expxl) );
     622   
     623    G4double bang, cb, sb, s0, s1, s2, c, s, esys, a, b, gama, beta;
     624    pcm[0][0] = 0.0;
     625    pcm[1][0] = pd[0];
     626    pcm[2][0] = 0.0;
     627    for( i=1; i<listLen; ++i )
     628    {
     629      pcm[0][i] = 0.0;
     630      pcm[1][i] = -pd[i-1];
     631      pcm[2][i] = 0.0;
     632      bang = twopi*G4UniformRand();
     633      cb = std::cos(bang);
     634      sb = std::sin(bang);
     635      c = 2.0*G4UniformRand() - 1.0;
     636      s = std::sqrt( std::fabs( 1.0-c*c ) );
     637      if( i < listLen-1 )
     638      {
     639        esys = std::sqrt(pd[i]*pd[i] + emm[i]*emm[i]);
     640        beta = pd[i]/esys;
     641        gama = esys/emm[i];
     642        for( G4int j=0; j<=i; ++j )
     643        {
     644          s0 = pcm[0][j];
     645          s1 = pcm[1][j];
     646          s2 = pcm[2][j];
     647          energy[j] = std::sqrt( s0*s0 + s1*s1 + s2*s2 + mass[j]*mass[j] );
     648          a = s0*c - s1*s;                           //  rotation
     649          pcm[1][j] = s0*s + s1*c;
     650          b = pcm[2][j];
     651          pcm[0][j] = a*cb - b*sb;
     652          pcm[2][j] = a*sb + b*cb;
     653          pcm[1][j] = gama*(pcm[1][j] + beta*energy[j]);
     654        }
     655      }
     656      else
     657      {
     658        for( G4int j=0; j<=i; ++j )
     659        {
     660          s0 = pcm[0][j];
     661          s1 = pcm[1][j];
     662          s2 = pcm[2][j];
     663          energy[j] = std::sqrt( s0*s0 + s1*s1 + s2*s2 + mass[j]*mass[j] );
     664          a = s0*c - s1*s;                           //  rotation
     665          pcm[1][j] = s0*s + s1*c;
     666          b = pcm[2][j];
     667          pcm[0][j] = a*cb - b*sb;
     668          pcm[2][j] = a*sb + b*cb;
     669        }
     670      }
     671    }
     672
     673  for (i=0; i<listLen; ++i) {
     674    tempList[i]->SetMomentum(pcm[0][i]*GeV, pcm[1][i]*GeV, pcm[2][i]*GeV);
     675    tempList[i]->SetTotalEnergy(energy[i]*GeV);
     676  }
     677
     678  return weight;
     679}
     680
     681
    487682G4double G4RPGReaction::normal()
    488683{
     
    493688
    494689 
    495 /*
    496 G4int G4RPGReaction::Poisson( G4double x )
     690void G4RPGReaction::Defs1(const G4ReactionProduct& modifiedOriginal,
     691                          G4ReactionProduct& currentParticle,
     692                          G4ReactionProduct& targetParticle,
     693                          G4FastVector<G4ReactionProduct,256>& vec,
     694                          G4int& vecLen)
    497695{
    498   G4int iran;
    499   G4double ran;
    500      
    501   if( x > 9.9 )    // use normal distribution with sigma^2 = <x>
    502     iran = static_cast<G4int>(std::max( 0.0, x+normal()*std::sqrt(x) ) );
    503   else {
    504     G4int mm = G4int(5.0*x);
    505     if( mm <= 0 )   // for very small x try iran=1,2,3
    506     {
    507       G4double p1 = x*std::exp(-x);
    508       G4double p2 = x*p1/2.0;
    509       G4double p3 = x*p2/3.0;
    510       ran = G4UniformRand();
    511       if( ran < p3 )
    512         iran = 3;
    513       else if( ran < p2 )  // this is original Geisha, it should be ran < p2+p3
    514         iran = 2;
    515       else if( ran < p1 )  // should be ran < p1+p2+p3
    516         iran = 1;
    517       else
    518         iran = 0;
    519     }
     696  // Rotate final state particle momenta by initial particle direction
     697
     698  const G4double pjx = modifiedOriginal.GetMomentum().x()/MeV;
     699  const G4double pjy = modifiedOriginal.GetMomentum().y()/MeV;
     700  const G4double pjz = modifiedOriginal.GetMomentum().z()/MeV;
     701  const G4double p = modifiedOriginal.GetMomentum().mag()/MeV;
     702
     703  if (pjx*pjx+pjy*pjy > 0.0) {
     704    G4double cost, sint, ph, cosp, sinp, pix, piy, piz;
     705    cost = pjz/p;
     706    sint = std::sqrt(std::abs((1.0-cost)*(1.0+cost)));
     707    if( pjy < 0.0 )
     708      ph = 3*halfpi;
    520709    else
    521     {
    522       iran = 0;
    523       G4double r = std::exp(-x);
    524       ran = G4UniformRand();
    525       if( ran > r )
    526       {
    527         G4double rrr;
    528         G4double rr = r;
    529         for( G4int i=1; i<=mm; ++i )
    530         {
    531           iran++;
    532           if( i > 5 )   // Stirling's formula for large numbers
    533             rrr = std::exp(i*std::log(x)-(i+0.5)*std::log((G4double)i)+i-0.9189385);
    534           else
    535             rrr = std::pow(x,i)/Factorial(i);
    536           rr += r*rrr;
    537           if( ran <= rr )break;
    538         }
    539       }
    540     }
    541   }
    542   return iran;
     710      ph = halfpi;
     711    if( std::abs( pjx ) > 0.001*MeV )ph = std::atan2(pjy,pjx);
     712    cosp = std::cos(ph);
     713    sinp = std::sin(ph);
     714    pix = currentParticle.GetMomentum().x()/MeV;
     715    piy = currentParticle.GetMomentum().y()/MeV;
     716    piz = currentParticle.GetMomentum().z()/MeV;
     717    currentParticle.SetMomentum((cost*cosp*pix - sinp*piy + sint*cosp*piz)*MeV,
     718                                (cost*sinp*pix + cosp*piy + sint*sinp*piz)*MeV,
     719                                (-sint*pix + cost*piz)*MeV);
     720    pix = targetParticle.GetMomentum().x()/MeV;
     721    piy = targetParticle.GetMomentum().y()/MeV;
     722    piz = targetParticle.GetMomentum().z()/MeV;
     723    targetParticle.SetMomentum((cost*cosp*pix - sinp*piy + sint*cosp*piz)*MeV,
     724                               (cost*sinp*pix + cosp*piy + sint*sinp*piz)*MeV,
     725                               (-sint*pix + cost*piz)*MeV);
     726
     727    for (G4int i=0; i<vecLen; ++i) {
     728      pix = vec[i]->GetMomentum().x()/MeV;
     729      piy = vec[i]->GetMomentum().y()/MeV;
     730      piz = vec[i]->GetMomentum().z()/MeV;
     731      vec[i]->SetMomentum((cost*cosp*pix - sinp*piy + sint*cosp*piz)*MeV,
     732                          (cost*sinp*pix + cosp*piy + sint*sinp*piz)*MeV,
     733                          (-sint*pix + cost*piz)*MeV);
     734    }
     735
     736  } else {
     737    if (pjz < 0.0) {
     738      currentParticle.SetMomentum( -currentParticle.GetMomentum().z() );
     739      targetParticle.SetMomentum( -targetParticle.GetMomentum().z() );
     740      for (G4int i=0; i<vecLen; ++i) vec[i]->SetMomentum( -vec[i]->GetMomentum().z() );
     741    }
     742  }
    543743}
    544 */
    545  
    546 // G4int G4RPGReaction::Factorial( G4int n )
    547 // {
    548 //  G4int m = std::min(n,10);
    549 //  G4int result = 1;
    550 //  if( m <= 1 )return result;
    551 //  for( G4int i=2; i<=m; ++i )result *= i;
    552 //  return result;
    553 // }
    554 
    555  
    556  void G4RPGReaction::Defs1(
    557    const G4ReactionProduct &modifiedOriginal,
    558    G4ReactionProduct &currentParticle,
    559    G4ReactionProduct &targetParticle,
    560    G4FastVector<G4ReactionProduct,256> &vec,
    561    G4int &vecLen )
    562   {
    563     // Rotate final state particle momenta by initial particle direction
    564 
    565     const G4double pjx = modifiedOriginal.GetMomentum().x()/MeV;
    566     const G4double pjy = modifiedOriginal.GetMomentum().y()/MeV;
    567     const G4double pjz = modifiedOriginal.GetMomentum().z()/MeV;
    568     const G4double p = modifiedOriginal.GetMomentum().mag()/MeV;
    569     if( pjx*pjx+pjy*pjy > 0.0 )
    570     {
    571       G4double cost, sint, ph, cosp, sinp, pix, piy, piz;
    572       cost = pjz/p;
    573       sint = std::sqrt(std::abs((1.0-cost)*(1.0+cost)));
    574       if( pjy < 0.0 )
    575         ph = 3*halfpi;
    576       else
    577         ph = halfpi;
    578       if( std::abs( pjx ) > 0.001*MeV )ph = std::atan2(pjy,pjx);
    579       cosp = std::cos(ph);
    580       sinp = std::sin(ph);
    581       pix = currentParticle.GetMomentum().x()/MeV;
    582       piy = currentParticle.GetMomentum().y()/MeV;
    583       piz = currentParticle.GetMomentum().z()/MeV;
    584       currentParticle.SetMomentum((cost*cosp*pix - sinp*piy + sint*cosp*piz)*MeV,
    585                                   (cost*sinp*pix + cosp*piy + sint*sinp*piz)*MeV,
    586                                   (-sint*pix + cost*piz)*MeV);
    587       pix = targetParticle.GetMomentum().x()/MeV;
    588       piy = targetParticle.GetMomentum().y()/MeV;
    589       piz = targetParticle.GetMomentum().z()/MeV;
    590       targetParticle.SetMomentum((cost*cosp*pix - sinp*piy + sint*cosp*piz)*MeV,
    591                                  (cost*sinp*pix + cosp*piy + sint*sinp*piz)*MeV,
    592                                  (-sint*pix + cost*piz)*MeV);
    593       for( G4int i=0; i<vecLen; ++i )
    594       {
    595         pix = vec[i]->GetMomentum().x()/MeV;
    596         piy = vec[i]->GetMomentum().y()/MeV;
    597         piz = vec[i]->GetMomentum().z()/MeV;
    598         vec[i]->SetMomentum((cost*cosp*pix - sinp*piy + sint*cosp*piz)*MeV,
    599                             (cost*sinp*pix + cosp*piy + sint*sinp*piz)*MeV,
    600                             (-sint*pix + cost*piz)*MeV);
    601       }
    602     }
    603     else
    604     {
    605       if( pjz < 0.0 )
    606       {
    607         currentParticle.SetMomentum( -currentParticle.GetMomentum().z() );
    608         targetParticle.SetMomentum( -targetParticle.GetMomentum().z() );
    609         for( G4int i=0; i<vecLen; ++i )
    610           vec[i]->SetMomentum( -vec[i]->GetMomentum().z() );
    611       }
    612     }
    613   }
    614  
     744
     745
    615746 void G4RPGReaction::Rotate(
    616747  const G4double numberofFinalStateNucleons,
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGSigmaMinusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGSigmaMinusInelastic.cc,v 1.1 2007/07/18 21:04:21 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGSigmaPlusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGSigmaPlusInelastic.cc,v 1.1 2007/07/18 21:04:21 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGStrangeProduction.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGStrangeProduction.cc,v 1.1 2007/07/18 21:04:21 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGTwoBody.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGTwoBody.cc,v 1.2 2007/08/15 20:38:37 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGTwoBody.cc,v 1.4 2008/05/05 21:21:55 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929
     
    8181                            2.0*targetMass*etCurrent );  // in GeV
    8282
    83   if( (pCurrent < 0.1) || (cmEnergy < 0.01) ) // 2-body scattering not possible
    84   {
     83  if (cmEnergy < 0.01) { // 2-body scattering not possible
    8584    targetParticle.SetMass( 0.0 );  // flag that the target particle doesn't exist
    86   }
    87   else
    88   {
     85
     86  } else {
    8987    // Projectile momentum in cm
    9088
     
    231229    const G4double pnCutOff = 0.0001;       // GeV
    232230    const G4double dtaCutOff = 0.0001;      // GeV
    233     const G4double kineticMinimum = 0.0001;
    234     const G4double kineticFactor = -0.010;
    235     G4double sprob = 0.0; // sprob = probability of self-absorption in heavy molecules
     231    //    const G4double kineticMinimum = 0.0001;
     232    //    const G4double kineticFactor = -0.010;
     233    //    G4double sprob = 0.0; // sprob = probability of self-absorption in heavy molecules
    236234    if( epnb >= pnCutOff )
    237235    {
     
    249247    if (npnb == 0 && ndta == 0) npnb = 1;
    250248
    251     AddBlackTrackParticles(epnb, npnb, edta, ndta, sprob, kineticMinimum,
    252                            kineticFactor, modifiedOriginal,
     249    AddBlackTrackParticles(epnb, npnb, edta, ndta, modifiedOriginal,
    253250                           PinNucleus, NinNucleus, targetNucleus,
    254251                           vec, vecLen);
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGTwoCluster.cc

    r819 r962  
    2424// ********************************************************************
    2525//
    26 // $Id: G4RPGTwoCluster.cc,v 1.2 2007/08/15 20:38:48 dennis Exp $
    27 // GEANT4 tag $Name: geant4-09-01-patch-02 $
     26// $Id: G4RPGTwoCluster.cc,v 1.5 2008/06/09 18:13:35 dennis Exp $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929
     
    128128  G4double bMass = backwardMass;
    129129
    130   G4int backwardNucleonCount = 1;  // number of nucleons in backward hemisphere
     130  //  G4int backwardNucleonCount = 1;  // number of nucleons in backward hemisphere
    131131   
    132132  for( i=0; i<vecLen; ++i )
     
    163163
    164164  if(atomicWeight<1.0001) nuclearExcitationCount = 0;
    165   G4int extraNucleonCount = 0;
    166   G4double extraMass = 0.0;
    167   G4double extraNucleonMass = 0.0;
     165  //  G4int extraNucleonCount = 0;
     166  //  G4double extraMass = 0.0;
     167  //  G4double extraNucleonMass = 0.0;
    168168  if( nuclearExcitationCount > 0 )
    169169  {
     
    183183        else
    184184          pVec->SetDefinition( aNeutron );
    185         ++backwardNucleonCount;
    186         ++extraNucleonCount;
    187         extraNucleonMass += pVec->GetMass()/GeV;
     185        // Not used        ++backwardNucleonCount;
     186        // Not used        ++extraNucleonCount;
     187        // Not used        extraNucleonMass += pVec->GetMass()/GeV;
    188188      }
    189189      else
     
    196196        else
    197197          pVec->SetDefinition( aPiMinus );
     198
     199        // DHW: add following two lines to correct energy balance
     200        //        ++backwardCount;
     201        //        backwardMass += pVec->GetMass()/GeV;
    198202      }
    199203      pVec->SetSide( -2 );    // backside particle
    200       extraMass += pVec->GetMass()/GeV;
     204      // Not used     extraMass += pVec->GetMass()/GeV;
    201205      pVec->SetNewlyAdded( true );
    202206      vec.SetElement( vecLen++, pVec );
     
    204208  }
    205209
    206   // Masses of particles added from cascade not included in energy balance
     210  // Masses of particles added from cascade not included in energy balance.
     211  // That's correct for nucleons from the intra-nuclear cascade but not for
     212  // pions from the cascade.
     213 
    207214  G4double forwardEnergy = (centerofmassEnergy-cMass-bMass)/2.0 +cMass - forwardMass;
    208215  G4double backwardEnergy = (centerofmassEnergy-cMass-bMass)/2.0 +bMass - backwardMass;
     
    779786    const G4double pnCutOff = 0.001;     // GeV
    780787    const G4double dtaCutOff = 0.001;    // GeV
    781     const G4double kineticMinimum = 1.e-6;
    782     const G4double kineticFactor = -0.005;
     788    //    const G4double kineticMinimum = 1.e-6;
     789    //    const G4double kineticFactor = -0.005;
    783790     
    784     G4double sprob = 0.0;   // sprob = probability of self-absorption in
     791    //    G4double sprob = 0.0;   // sprob = probability of self-absorption in
    785792                            // heavy molecules
    786     const G4double ekIncident = originalIncident->GetKineticEnergy()/GeV;
    787     if( ekIncident >= 5.0 )sprob = std::min( 1.0, 0.6*std::log(ekIncident-4.0) );
     793    // Not currently used (DHW 9 June 2008)  const G4double ekIncident = originalIncident->GetKineticEnergy()/GeV;
     794    //    if( ekIncident >= 5.0 )sprob = std::min( 1.0, 0.6*std::log(ekIncident-4.0) );
    788795     
    789796    if( epnb >= pnCutOff )
     
    803810    // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
    804811
    805     AddBlackTrackParticles(epnb, npnb, edta, ndta, sprob, kineticMinimum,
    806                            kineticFactor, modifiedOriginal,
     812    AddBlackTrackParticles(epnb, npnb, edta, ndta, modifiedOriginal,
    807813                           PinNucleus, NinNucleus, targetNucleus,
    808814                           vec, vecLen );
  • trunk/source/processes/hadronic/models/rpg/src/G4RPGXiMinusInelastic.cc

    r819 r962  
    2525//
    2626// $Id: G4RPGXiMinusInelastic.cc,v 1.1 2007/07/18 21:04:21 dennis Exp $
    27 // GEANT4 tag $Name: $
     27// GEANT4 tag $Name: geant4-09-02-ref-02 $
    2828//
    2929 
Note: See TracChangeset for help on using the changeset viewer.