diff --git a/SimG4Core/CustomPhysics/interface/CMSQGSPSIMPBuilder.h b/SimG4Core/CustomPhysics/interface/CMSQGSPSIMPBuilder.h index 72f618f8a6189..c2f1201be4741 100644 --- a/SimG4Core/CustomPhysics/interface/CMSQGSPSIMPBuilder.h +++ b/SimG4Core/CustomPhysics/interface/CMSQGSPSIMPBuilder.h @@ -3,44 +3,27 @@ #include "globals.hh" -#include "G4HadronElasticProcess.hh" -#include "G4HadronFissionProcess.hh" -#include "G4HadronCaptureProcess.hh" -#include "SimG4Core/CustomPhysics/interface/CMSSIMPInelasticProcess.h" - -#include "G4TheoFSGenerator.hh" -#include "G4PreCompoundModel.hh" -#include "G4GeneratorPrecompoundInterface.hh" -#include "G4QGSModel.hh" #include "G4QGSParticipants.hh" #include "G4QGSMFragmentation.hh" #include "G4ExcitedStringDecay.hh" -#include "G4QuasiElasticChannel.hh" +#include "G4QGSModel.hh" -class CMSQGSPSIMPBuilder { -public: - CMSQGSPSIMPBuilder(G4bool quasiElastic = false); - virtual ~CMSQGSPSIMPBuilder(); +class CMSSIMPInelasticProcess; +class G4QGSParticipants; +class G4QGSMFragmentation; +class G4ExcitedStringDecay; +class CMSQGSPSIMPBuilder { public: - virtual void Build(G4HadronElasticProcess* aP); - virtual void Build(G4HadronFissionProcess* aP); - virtual void Build(G4HadronCaptureProcess* aP); - virtual void Build(CMSSIMPInelasticProcess* aP); + CMSQGSPSIMPBuilder(); + ~CMSQGSPSIMPBuilder(); - void SetMinEnergy(G4double aM) { theMin = aM; } + void Build(CMSSIMPInelasticProcess* aP); private: - G4TheoFSGenerator* theModel; - G4PreCompoundModel* thePreEquilib; - G4GeneratorPrecompoundInterface* theCascade; G4QGSModel* theStringModel; G4ExcitedStringDecay* theStringDecay; - G4QuasiElasticChannel* theQuasiElastic; - G4QGSMFragmentation* theQGSM; - - G4double theMin; }; #endif diff --git a/SimG4Core/CustomPhysics/interface/CMSSIMPInelasticProcess.h b/SimG4Core/CustomPhysics/interface/CMSSIMPInelasticProcess.h index 3b450f7b86376..12c78d5dbcf46 100644 --- a/SimG4Core/CustomPhysics/interface/CMSSIMPInelasticProcess.h +++ b/SimG4Core/CustomPhysics/interface/CMSSIMPInelasticProcess.h @@ -13,155 +13,15 @@ class CMSSIMPInelasticProcess : public G4HadronicProcess { G4bool IsApplicable(const G4ParticleDefinition& aParticleType) override; - // register generator of secondaries - void RegisterMe(G4HadronicInteraction* a); - - // get cross section per element - inline G4double GetElementCrossSection(const G4DynamicParticle* part, - const G4Element* elm, - const G4Material* mat = nullptr) { - G4double x = theCrossSectionDataStore->GetCrossSection(part, elm, mat); - if (x < 0.0) { - x = 0.0; - } - return x; - } - - // obsolete method to get cross section per element - inline G4double GetMicroscopicCrossSection(const G4DynamicParticle* part, - const G4Element* elm, - const G4Material* mat = nullptr) { - return GetElementCrossSection(part, elm, mat); - } - // generic PostStepDoIt recommended for all derived classes G4VParticleChange* PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) override; - // initialisation of physics tables and CMSSIMPInelasticProcessStore - void PreparePhysicsTable(const G4ParticleDefinition&) override; - - // build physics tables and print out the configuration of the process - void BuildPhysicsTable(const G4ParticleDefinition&) override; - - // dump physics tables - inline void DumpPhysicsTable(const G4ParticleDefinition& p) { theCrossSectionDataStore->DumpPhysicsTable(p); } - - // add cross section data set - inline void AddDataSet(G4VCrossSectionDataSet* aDataSet) { theCrossSectionDataStore->AddDataSet(aDataSet); } - - // access to the manager - inline G4EnergyRangeManager* GetManagerPointer() { return &theEnergyRangeManager; } - - // get inverse cross section per volume - G4double GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*) override; - - // access to the target nucleus - inline const G4Nucleus* GetTargetNucleus() const { return &targetNucleus; } - - // G4ParticleDefinition* GetTargetDefinition(); - inline const G4Isotope* GetTargetIsotope() { return targetNucleus.GetIsotope(); } - - void ProcessDescription(std::ostream& outFile) const override; - -protected: - // generic method to choose secondary generator - // recommended for all derived classes - inline G4HadronicInteraction* ChooseHadronicInteraction(G4double kineticEnergy, - G4Material* aMaterial, - G4Element* anElement) { - return theEnergyRangeManager.GetHadronicInteraction(kineticEnergy, aMaterial, anElement); - } - - // access to the target nucleus - inline G4Nucleus* GetTargetNucleusPointer() { return &targetNucleus; } - -public: - void BiasCrossSectionByFactor(G4double aScale); - - // Energy-momentum non-conservation limits and reporting - inline void SetEpReportLevel(G4int level) { epReportLevel = level; } - - inline void SetEnergyMomentumCheckLevels(G4double relativeLevel, G4double absoluteLevel) { - epCheckLevels.first = relativeLevel; - epCheckLevels.second = absoluteLevel; - levelsSetByProcess = true; - } - - inline std::pair GetEnergyMomentumCheckLevels() const { return epCheckLevels; } - - // access to the cross section data store - inline G4CrossSectionDataStore* GetCrossSectionDataStore() { return theCrossSectionDataStore; } - - inline void MultiplyCrossSectionBy(G4double factor) { aScaleFactor = factor; } - -protected: - void DumpState(const G4Track&, const G4String&, G4ExceptionDescription&); - - // obsolete method will be removed - inline const G4EnergyRangeManager& GetEnergyRangeManager() const { return theEnergyRangeManager; } - - // obsolete method will be removed - inline void SetEnergyRangeManager(const G4EnergyRangeManager& value) { theEnergyRangeManager = value; } - - // access to the chosen generator - inline G4HadronicInteraction* GetHadronicInteraction() const { return theInteraction; } - - // access to the cross section data set - inline G4double GetLastCrossSection() { return theLastCrossSection; } - - // fill result - void FillResult(G4HadFinalState* aR, const G4Track& aT); - - // Check the result for catastrophic energy non-conservation - G4HadFinalState* CheckResult(const G4HadProjectile& thePro, - const G4Nucleus& targetNucleus, - G4HadFinalState* result) const; - - // Check 4-momentum balance - void CheckEnergyMomentumConservation(const G4Track&, const G4Nucleus&); - private: - G4double XBiasSurvivalProbability(); - G4double XBiasSecondaryWeight(); - // hide assignment operator as private CMSSIMPInelasticProcess& operator=(const CMSSIMPInelasticProcess& right) = delete; CMSSIMPInelasticProcess(const CMSSIMPInelasticProcess&) = delete; - // Set E/p conservation check levels from environment variables - void GetEnergyMomentumCheckEnvvars(); - -protected: - G4HadProjectile thePro; - - G4ParticleChange* theTotalResult; - - G4int epReportLevel; - -private: G4ParticleDefinition* theParticle; - - G4EnergyRangeManager theEnergyRangeManager; - - G4HadronicInteraction* theInteraction; - - G4CrossSectionDataStore* theCrossSectionDataStore; - - G4Nucleus targetNucleus; - - bool CMSSIMPInelasticProcess_debug_flag; - - // Energy-momentum checking - std::pair epCheckLevels; - G4bool levelsSetByProcess; - - std::vector theBias; - - G4double theInitialNumberOfInteractionLength; - - G4double aScaleFactor; - G4bool xBiasOn; - G4double theLastCrossSection; }; #endif diff --git a/SimG4Core/CustomPhysics/interface/CMSSIMPInelasticXS.h b/SimG4Core/CustomPhysics/interface/CMSSIMPInelasticXS.h index cc9578fc64ce4..9dfa38287b386 100644 --- a/SimG4Core/CustomPhysics/interface/CMSSIMPInelasticXS.h +++ b/SimG4Core/CustomPhysics/interface/CMSSIMPInelasticXS.h @@ -3,17 +3,8 @@ #include "G4VCrossSectionDataSet.hh" #include "globals.hh" -#include "G4ElementData.hh" -#include -const G4int MAXZINEL = 93; - -class G4DynamicParticle; -class G4ParticleDefinition; -class G4Element; -class G4PhysicsVector; -class G4ComponentGGHadronNucleusXsc; -class G4HadronNucleonXsc; +class G4NeutronInelasticXS; class CMSSIMPInelasticXS : public G4VCrossSectionDataSet { public: @@ -34,36 +25,17 @@ class CMSSIMPInelasticXS : public G4VCrossSectionDataSet { const G4Element* elm, const G4Material* mat) override; - G4Isotope* SelectIsotope(const G4Element*, G4double kinEnergy) override; - void BuildPhysicsTable(const G4ParticleDefinition&) override; - void CrossSectionDescription(std::ostream&) const override; - private: void Initialise(G4int Z, G4DynamicParticle* dp = nullptr, const char* = nullptr); - G4PhysicsVector* RetrieveVector(std::ostringstream& in, G4bool warn); - - G4double IsoCrossSection(G4double ekin, G4int Z, G4int A); - CMSSIMPInelasticXS& operator=(const CMSSIMPInelasticXS& right) = delete; CMSSIMPInelasticXS(const CMSSIMPInelasticXS&) = delete; - G4ComponentGGHadronNucleusXsc* ggXsection; - G4HadronNucleonXsc* fNucleon; - - const G4ParticleDefinition* proton; - - G4ElementData data; - std::vector work; - std::vector temp; - std::vector coeff; - + G4NeutronInelasticXS* nXsection; + const G4ParticleDefinition* neutron; G4bool isInitialized; - - static const G4int amin[MAXZINEL]; - static const G4int amax[MAXZINEL]; }; #endif diff --git a/SimG4Core/CustomPhysics/src/CMSQGSPSIMPBuilder.cc b/SimG4Core/CustomPhysics/src/CMSQGSPSIMPBuilder.cc index 32a3e824356e7..1831b3e2512b2 100644 --- a/SimG4Core/CustomPhysics/src/CMSQGSPSIMPBuilder.cc +++ b/SimG4Core/CustomPhysics/src/CMSQGSPSIMPBuilder.cc @@ -1,57 +1,37 @@ #include "SimG4Core/CustomPhysics/interface/CMSQGSPSIMPBuilder.h" +#include "SimG4Core/CustomPhysics/interface/CMSSIMPInelasticProcess.h" + #include "G4SystemOfUnits.hh" #include "G4ParticleDefinition.hh" -#include "G4ParticleTable.hh" -#include "G4ProcessManager.hh" -#include "G4ExcitationHandler.hh" - -#include "SimG4Core/CustomPhysics/interface/CMSSIMPInelasticXS.h" -#include "SimG4Core/CustomPhysics/interface/CMSSIMP.h" - -CMSQGSPSIMPBuilder::CMSQGSPSIMPBuilder(G4bool quasiElastic) { - theMin = 12 * GeV; - - theModel = new G4TheoFSGenerator("QGSP"); - +#include "G4TheoFSGenerator.hh" +#include "G4PreCompoundModel.hh" +#include "G4GeneratorPrecompoundInterface.hh" +#include "G4QGSParticipants.hh" +#include "G4QGSMFragmentation.hh" +#include "G4ExcitedStringDecay.hh" + +CMSQGSPSIMPBuilder::CMSQGSPSIMPBuilder() { theStringModel = new G4QGSModel; theStringDecay = new G4ExcitedStringDecay(theQGSM = new G4QGSMFragmentation); theStringModel->SetFragmentationModel(theStringDecay); - - theCascade = new G4GeneratorPrecompoundInterface; - thePreEquilib = new G4PreCompoundModel(new G4ExcitationHandler); - theCascade->SetDeExcitation(thePreEquilib); - - theModel->SetTransport(theCascade); - theModel->SetHighEnergyGenerator(theStringModel); - if (quasiElastic) { - theQuasiElastic = new G4QuasiElasticChannel; - theModel->SetQuasiElasticChannel(theQuasiElastic); - } else { - theQuasiElastic = nullptr; - } } CMSQGSPSIMPBuilder::~CMSQGSPSIMPBuilder() { delete theStringDecay; delete theStringModel; - delete thePreEquilib; - delete theCascade; - if (theQuasiElastic) - delete theQuasiElastic; - delete theModel; delete theQGSM; } -void CMSQGSPSIMPBuilder::Build(G4HadronElasticProcess*) {} - -void CMSQGSPSIMPBuilder::Build(G4HadronFissionProcess*) {} - -void CMSQGSPSIMPBuilder::Build(G4HadronCaptureProcess*) {} - void CMSQGSPSIMPBuilder::Build(CMSSIMPInelasticProcess* aP) { - theModel->SetMinEnergy(theMin); - theModel->SetMaxEnergy(100 * TeV); + G4GeneratorPrecompoundInterface* theCascade = new G4GeneratorPrecompoundInterface; + G4PreCompoundModel* thePreEquilib = new G4PreCompoundModel(); + theCascade->SetDeExcitation(thePreEquilib); + + G4TheoFSGenerator* theModel = new G4TheoFSGenerator("QGSP"); + theModel->SetTransport(theCascade); + theModel->SetHighEnergyGenerator(theStringModel); + theModel->SetMinEnergy(0.0); + theModel->SetMaxEnergy(100 * CLHEP::TeV); aP->RegisterMe(theModel); - aP->AddDataSet(new CMSSIMPInelasticXS()); } diff --git a/SimG4Core/CustomPhysics/src/CMSSIMPInelasticProcess.cc b/SimG4Core/CustomPhysics/src/CMSSIMPInelasticProcess.cc index b09948a00235d..37e473aa756c0 100644 --- a/SimG4Core/CustomPhysics/src/CMSSIMPInelasticProcess.cc +++ b/SimG4Core/CustomPhysics/src/CMSSIMPInelasticProcess.cc @@ -1,5 +1,6 @@ #include "SimG4Core/CustomPhysics/interface/CMSSIMPInelasticProcess.h" +#include "SimG4Core/CustomPhysics/interface/CMSSIMPInelasticXS.h" #include "SimG4Core/CustomPhysics/interface/CMSSIMP.h" #include "G4Types.hh" @@ -10,124 +11,29 @@ #include "G4Step.hh" #include "G4Element.hh" #include "G4ParticleChange.hh" -#include "G4TransportationManager.hh" -#include "G4Navigator.hh" -#include "G4ProcessVector.hh" -#include "G4ProcessManager.hh" -#include "G4StableIsotopes.hh" -#include "G4HadTmpUtil.hh" #include "G4NucleiProperties.hh" +#include "G4Nucleus.hh" #include "G4HadronicException.hh" #include "G4HadronicProcessStore.hh" - -#include -#include -#include - -#include +#include "G4HadronicInteraction.hh" #include "G4HadronInelasticDataSet.hh" #include "G4ParticleDefinition.hh" -// File-scope variable to capture environment variable at startup - -static const char* G4Hadronic_Random_File = getenv("G4HADRONIC_RANDOM_FILE"); - ////////////////////////////////////////////////////////////////// CMSSIMPInelasticProcess::CMSSIMPInelasticProcess(const G4String& processName) : G4HadronicProcess(processName, fHadronic) { - SetProcessSubType(fHadronInelastic); // Default unless subclass changes - - theTotalResult = new G4ParticleChange(); - theTotalResult->SetSecondaryWeightByProcess(true); - theInteraction = nullptr; - theCrossSectionDataStore = new G4CrossSectionDataStore(); - G4HadronicProcessStore::Instance()->Register(this); - aScaleFactor = 1; - xBiasOn = false; - CMSSIMPInelasticProcess_debug_flag = false; - - GetEnergyMomentumCheckEnvvars(); - - AddDataSet(new G4HadronInelasticDataSet()); + AddDataSet(new CMSSIMPInelasticXS()); theParticle = CMSSIMP::SIMP(); } -CMSSIMPInelasticProcess::~CMSSIMPInelasticProcess() { - G4HadronicProcessStore::Instance()->DeRegister(this); - delete theTotalResult; - delete theCrossSectionDataStore; -} +CMSSIMPInelasticProcess::~CMSSIMPInelasticProcess() {} G4bool CMSSIMPInelasticProcess::IsApplicable(const G4ParticleDefinition& aP) { return theParticle->GetParticleType() == aP.GetParticleType(); } -void CMSSIMPInelasticProcess::GetEnergyMomentumCheckEnvvars() { - levelsSetByProcess = false; - - epReportLevel = getenv("G4Hadronic_epReportLevel") ? strtol(getenv("G4Hadronic_epReportLevel"), nullptr, 10) : 0; - - epCheckLevels.first = - getenv("G4Hadronic_epCheckRelativeLevel") ? strtod(getenv("G4Hadronic_epCheckRelativeLevel"), nullptr) : DBL_MAX; - - epCheckLevels.second = - getenv("G4Hadronic_epCheckAbsoluteLevel") ? strtod(getenv("G4Hadronic_epCheckAbsoluteLevel"), nullptr) : DBL_MAX; -} - -void CMSSIMPInelasticProcess::RegisterMe(G4HadronicInteraction* a) { - if (!a) { - return; - } - try { - GetManagerPointer()->RegisterMe(a); - } catch (G4HadronicException& aE) { - G4ExceptionDescription ed; - aE.Report(ed); - ed << "Unrecoverable error in " << GetProcessName() << " to register " << a->GetModelName() << G4endl; - G4Exception("CMSSIMPInelasticProcess::RegisterMe", "had001", FatalException, ed); - } - G4HadronicProcessStore::Instance()->RegisterInteraction(this, a); -} - -void CMSSIMPInelasticProcess::PreparePhysicsTable(const G4ParticleDefinition& p) { - if (getenv("CMSSIMPInelasticProcess_debug")) { - CMSSIMPInelasticProcess_debug_flag = true; - } - G4HadronicProcessStore::Instance()->RegisterParticle(this, &p); -} - -void CMSSIMPInelasticProcess::BuildPhysicsTable(const G4ParticleDefinition& p) { - try { - theCrossSectionDataStore->BuildPhysicsTable(p); - } catch (G4HadronicException& aR) { - G4ExceptionDescription ed; - aR.Report(ed); - ed << " hadronic initialisation fails" << G4endl; - G4Exception("CMSSIMPInelasticProcess::BuildPhysicsTable", "had000", FatalException, ed); - } - G4HadronicProcessStore::Instance()->PrintInfo(&p); -} - -G4double CMSSIMPInelasticProcess::GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*) { - try { - theLastCrossSection = - aScaleFactor * theCrossSectionDataStore->GetCrossSection(aTrack.GetDynamicParticle(), aTrack.GetMaterial()); - } catch (G4HadronicException& aR) { - G4ExceptionDescription ed; - aR.Report(ed); - DumpState(aTrack, "GetMeanFreePath", ed); - ed << " Cross section is not available" << G4endl; - G4Exception("CMSSIMPInelasticProcess::GetMeanFreePath", "had002", FatalException, ed); - } - G4double res = DBL_MAX; - if (theLastCrossSection > 0.0) { - res = 1.0 / theLastCrossSection; - } - return res; -} - G4VParticleChange* CMSSIMPInelasticProcess::PostStepDoIt(const G4Track& aTrack, const G4Step&) { // if primary is not Alive then do nothing theTotalResult->Clear(); @@ -145,26 +51,9 @@ G4VParticleChange* CMSSIMPInelasticProcess::PostStepDoIt(const G4Track& aTrack, aParticle->SetPDGcode(2112); aParticle->SetDefinition(G4Neutron::Neutron()); - G4Material* aMaterial = aTrack.GetMaterial(); - - G4Element* anElement = nullptr; - try { - anElement = theCrossSectionDataStore->SampleZandA(aParticle, aMaterial, targetNucleus); - } catch (G4HadronicException& aR) { - G4ExceptionDescription ed; - aR.Report(ed); - DumpState(aTrack, "SampleZandA", ed); - ed << " PostStepDoIt failed on element selection" << G4endl; - G4Exception("CMSSIMPInelasticProcess::PostStepDoIt", "had003", FatalException, ed); - } - - // check only for charged particles - if (aParticle->GetDefinition()->GetPDGCharge() != 0.0) { - if (GetElementCrossSection(aParticle, anElement, aMaterial) <= 0.0) { - // No interaction - return theTotalResult; - } - } + G4Nucleus* target = GetTargetNucleusPointer(); + const G4Material* aMaterial = aTrack.GetMaterial(); + const G4Element* anElement = GetCrossSectionDataStore()->SampleZandA(aParticle, aMaterial, *target); // Next check for illegal track status // @@ -181,566 +70,73 @@ G4VParticleChange* CMSSIMPInelasticProcess::PostStepDoIt(const G4Track& aTrack, return theTotalResult; } - // Go on to regular case - // - G4double originalEnergy = aParticle->GetKineticEnergy(); - G4double kineticEnergy = originalEnergy; - - // Get kinetic energy per nucleon for ions - if (aParticle->GetParticleDefinition()->GetBaryonNumber() > 1.5) - kineticEnergy /= aParticle->GetParticleDefinition()->GetBaryonNumber(); - - try { - theInteraction = ChooseHadronicInteraction(kineticEnergy, aMaterial, anElement); - } catch (G4HadronicException& aE) { - G4ExceptionDescription ed; - aE.Report(ed); - ed << "Target element " << anElement->GetName() << " Z= " << targetNucleus.GetZ_asInt() - << " A= " << targetNucleus.GetA_asInt() << G4endl; - DumpState(aTrack, "ChooseHadronicInteraction", ed); - ed << " No HadronicInteraction found out" << G4endl; - G4Exception("CMSSIMPInelasticProcess::PostStepDoIt", "had005", FatalException, ed); - } - // Initialize the hadronic projectile from the track thePro.Initialise(aTrack); + G4HadronicInteraction* anInteraction = GetHadronicInteractionList()[0]; + G4HadFinalState* result = nullptr; G4int reentryCount = 0; do { try { - // Save random engine if requested for debugging - if (G4Hadronic_Random_File) { - CLHEP::HepRandom::saveEngineStatus(G4Hadronic_Random_File); - } // Call the interaction - result = theInteraction->ApplyYourself(thePro, targetNucleus); + result = anInteraction->ApplyYourself(thePro, *target); ++reentryCount; } catch (G4HadronicException& aR) { G4ExceptionDescription ed; aR.Report(ed); - ed << "Call for " << theInteraction->GetModelName() << G4endl; - ed << "Target element " << anElement->GetName() << " Z= " << targetNucleus.GetZ_asInt() - << " A= " << targetNucleus.GetA_asInt() << G4endl; + ed << "Call for " << anInteraction->GetModelName() << G4endl; + ed << "Target element " << anElement->GetName() << " Z= " << target->GetZ_asInt() + << " A= " << target->GetA_asInt() << G4endl; DumpState(aTrack, "ApplyYourself", ed); ed << " ApplyYourself failed" << G4endl; G4Exception("CMSSIMPInelasticProcess::PostStepDoIt", "had006", FatalException, ed); } // Check the result for catastrophic energy non-conservation - result = CheckResult(thePro, targetNucleus, result); + result = CheckResult(thePro, *target, result); if (reentryCount > 100) { G4ExceptionDescription ed; - ed << "Call for " << theInteraction->GetModelName() << G4endl; - ed << "Target element " << anElement->GetName() << " Z= " << targetNucleus.GetZ_asInt() - << " A= " << targetNucleus.GetA_asInt() << G4endl; + ed << "Call for " << anInteraction->GetModelName() << G4endl; + ed << "Target element " << anElement->GetName() << " Z= " << target->GetZ_asInt() + << " A= " << target->GetA_asInt() << G4endl; DumpState(aTrack, "ApplyYourself", ed); ed << " ApplyYourself does not completed after 100 attempts" << G4endl; G4Exception("CMSSIMPInelasticProcess::PostStepDoIt", "had006", FatalException, ed); } } while (!result); - - result->SetTrafoToLab(thePro.GetTrafoToLab()); - - ClearNumberOfInteractionLengthLeft(); - - FillResult(result, aTrack); - - if (epReportLevel != 0) { - CheckEnergyMomentumConservation(aTrack, targetNucleus); - } - return theTotalResult; -} - -void CMSSIMPInelasticProcess::ProcessDescription(std::ostream& outFile) const { - outFile << "The description for this process has not been written yet.\n"; -} - -G4double CMSSIMPInelasticProcess::XBiasSurvivalProbability() { - G4double result = 0; - G4double nLTraversed = GetTotalNumberOfInteractionLengthTraversed(); - G4double biasedProbability = 1. - std::exp(-nLTraversed); - G4double realProbability = 1 - std::exp(-nLTraversed / aScaleFactor); - result = (biasedProbability - realProbability) / biasedProbability; - return result; -} - -G4double CMSSIMPInelasticProcess::XBiasSecondaryWeight() { - G4double result = 0; - G4double nLTraversed = GetTotalNumberOfInteractionLengthTraversed(); - result = 1. / aScaleFactor * std::exp(-nLTraversed / aScaleFactor * (1 - 1. / aScaleFactor)); - return result; -} - -void CMSSIMPInelasticProcess::FillResult(G4HadFinalState* aR, const G4Track& aT) { - theTotalResult->ProposeLocalEnergyDeposit(aR->GetLocalEnergyDeposit()); - - G4double rotation = CLHEP::twopi * G4UniformRand(); - G4ThreeVector it(0., 0., 1.); - - G4double efinal = aR->GetEnergyChange(); - if (efinal < 0.0) { - efinal = 0.0; - } - - // check status of primary - if (aR->GetStatusChange() == stopAndKill) { - theTotalResult->ProposeTrackStatus(fStopAndKill); - theTotalResult->ProposeEnergy(0.0); - - // check its final energy - } else if (0.0 == efinal) { - theTotalResult->ProposeEnergy(0.0); - if (aT.GetParticleDefinition()->GetProcessManager()->GetAtRestProcessVector()->size() > 0) { - aParticleChange.ProposeTrackStatus(fStopButAlive); - } else { - aParticleChange.ProposeTrackStatus(fStopAndKill); - } - - // primary is not killed apply rotation and Lorentz transformation - } else { - theTotalResult->ProposeTrackStatus(fAlive); - G4double mass = aT.GetParticleDefinition()->GetPDGMass(); - G4double newE = efinal + mass; - G4double newP = std::sqrt(efinal * (efinal + 2 * mass)); - G4ThreeVector newPV = newP * aR->GetMomentumChange(); - G4LorentzVector newP4(newE, newPV); - newP4.rotate(rotation, it); - newP4 *= aR->GetTrafoToLab(); - theTotalResult->ProposeMomentumDirection(newP4.vect().unit()); - newE = newP4.e() - mass; - if (CMSSIMPInelasticProcess_debug_flag && newE <= 0.0) { - G4ExceptionDescription ed; - DumpState(aT, "Primary has zero energy after interaction", ed); - G4Exception("CMSSIMPInelasticProcess::FillResults", "had011", JustWarning, ed); - } - if (newE < 0.0) { - newE = 0.0; - } - theTotalResult->ProposeEnergy(newE); - } - - // check secondaries: apply rotation and Lorentz transformation - G4int nSec = aR->GetNumberOfSecondaries(); - theTotalResult->SetNumberOfSecondaries(nSec); - G4double weight = aT.GetWeight(); - + // Check whether kaon0 or anti_kaon0 are present between the secondaries: + // if this is the case, transform them into either kaon0S or kaon0L, + // with equal, 50% probability, keeping their dynamical masses (and + // the other kinematical properties). + // When this happens - very rarely - a "JustWarning" exception is thrown. + G4int nSec = result->GetNumberOfSecondaries(); if (nSec > 0) { - G4double time0 = aT.GetGlobalTime(); for (G4int i = 0; i < nSec; ++i) { - G4LorentzVector theM = aR->GetSecondary(i)->GetParticle()->Get4Momentum(); - theM.rotate(rotation, it); - theM *= aR->GetTrafoToLab(); - aR->GetSecondary(i)->GetParticle()->Set4Momentum(theM); - - // time of interaction starts from zero - G4double time = aR->GetSecondary(i)->GetTime(); - if (time < 0.0) { - time = 0.0; - } - - // take into account global time - time += time0; - - G4Track* track = new G4Track(aR->GetSecondary(i)->GetParticle(), time, aT.GetPosition()); - G4double newWeight = weight * aR->GetSecondary(i)->GetWeight(); - // G4cout << "#### ParticleDebug " - // <GetSecondary(i)->GetParticle()->GetDefinition()->GetParticleName()<<" " - // <GetSecondary(i)->GetWeight()<<" " - // <GetSecondary(i)->GetParticle()->Get4Momentum()<<" " - // <SetWeight(newWeight); - track->SetTouchableHandle(aT.GetTouchableHandle()); - theTotalResult->AddSecondary(track); - if (CMSSIMPInelasticProcess_debug_flag) { - G4double e = track->GetKineticEnergy(); - if (e <= 0.0) { - G4ExceptionDescription ed; - DumpState(aT, "Secondary has zero energy", ed); - ed << "Secondary " << track->GetDefinition()->GetParticleName() << G4endl; - G4Exception("CMSSIMPInelasticProcess::FillResults", "had011", JustWarning, ed); + G4DynamicParticle* dynamicParticle = result->GetSecondary(i)->GetParticle(); + const G4ParticleDefinition* particleDefinition = dynamicParticle->GetParticleDefinition(); + if (particleDefinition == G4KaonZero::Definition() || particleDefinition == G4AntiKaonZero::Definition()) { + G4ParticleDefinition* newPart; + if (G4UniformRand() > 0.5) { + newPart = G4KaonZeroShort::Definition(); + } else { + newPart = G4KaonZeroLong::Definition(); } + dynamicParticle->SetDefinition(newPart); + G4ExceptionDescription ed; + ed << " Hadronic model " << anInteraction->GetModelName() << G4endl; + ed << " created " << particleDefinition->GetParticleName() << G4endl; + ed << " -> forced to be " << newPart->GetParticleName() << G4endl; + G4Exception("G4HadronicProcess::PostStepDoIt", "had007", JustWarning, ed); } } } - aR->Clear(); - return; -} -/* -void -CMSSIMPInelasticProcess::FillTotalResult(G4HadFinalState* aR, const G4Track& aT) -{ - theTotalResult->Clear(); - theTotalResult->ProposeLocalEnergyDeposit(0.); - theTotalResult->Initialize(aT); - theTotalResult->SetSecondaryWeightByProcess(true); - theTotalResult->ProposeTrackStatus(fAlive); - G4double rotation = CLHEP::twopi*G4UniformRand(); - G4ThreeVector it(0., 0., 1.); - - if(aR->GetStatusChange()==stopAndKill) - { - if( xBiasOn && G4UniformRand()ProposeParentWeight( XBiasSurvivalProbability()*aT.GetWeight() ); - } - else - { - theTotalResult->ProposeTrackStatus(fStopAndKill); - theTotalResult->ProposeEnergy( 0.0 ); - } - } - else if(aR->GetStatusChange()!=stopAndKill ) - { - if(aR->GetStatusChange()==suspend) - { - theTotalResult->ProposeTrackStatus(fSuspend); - if(xBiasOn) - { - G4ExceptionDescription ed; - DumpState(aT,"FillTotalResult",ed); - G4Exception("CMSSIMPInelasticProcess::FillTotalResult", "had007", FatalException, - ed,"Cannot cross-section bias a process that suspends tracks."); - } - } else if (aT.GetKineticEnergy() == 0) { - theTotalResult->ProposeTrackStatus(fStopButAlive); - } - - if(xBiasOn && G4UniformRand()ProposeParentWeight( XBiasSurvivalProbability()*aT.GetWeight() ); - G4double newWeight = aR->GetWeightChange()*aT.GetWeight(); - G4double newM=aT.GetParticleDefinition()->GetPDGMass(); - G4double newE=aR->GetEnergyChange() + newM; - G4double newP=std::sqrt(newE*newE - newM*newM); - G4DynamicParticle * aNew = - new G4DynamicParticle(aT.GetParticleDefinition(), newE, newP*aR->GetMomentumChange()); - aR->AddSecondary(G4HadSecondary(aNew, newWeight)); - } - else - { - G4double newWeight = aR->GetWeightChange()*aT.GetWeight(); - theTotalResult->ProposeParentWeight(newWeight); // This is multiplicative - if(aR->GetEnergyChange()>-.5) - { - theTotalResult->ProposeEnergy(aR->GetEnergyChange()); - } - G4LorentzVector newDirection(aR->GetMomentumChange().unit(), 1.); - newDirection*=aR->GetTrafoToLab(); - theTotalResult->ProposeMomentumDirection(newDirection.vect()); - } - } - else - { - G4ExceptionDescription ed; - ed << "Call for " << theInteraction->GetModelName() << G4endl; - ed << "Target Z= " - << targetNucleus.GetZ_asInt() - << " A= " << targetNucleus.GetA_asInt() << G4endl; - DumpState(aT,"FillTotalResult",ed); - G4Exception("CMSSIMPInelasticProcess", "had008", FatalException, - "use of unsupported track-status."); - } - - if(GetProcessName() != "hElastic" && GetProcessName() != "HadronElastic" - && theTotalResult->GetTrackStatus()==fAlive - && aR->GetStatusChange()==isAlive) - { - // Use for debugging: G4double newWeight = theTotalResult->GetParentWeight(); - - G4double newKE = std::max(DBL_MIN, aR->GetEnergyChange()); - G4DynamicParticle* aNew = new G4DynamicParticle(aT.GetParticleDefinition(), - aR->GetMomentumChange(), - newKE); - aR->AddSecondary(aNew); - aR->SetStatusChange(stopAndKill); - - theTotalResult->ProposeTrackStatus(fStopAndKill); - theTotalResult->ProposeEnergy( 0.0 ); - - } - theTotalResult->ProposeLocalEnergyDeposit(aR->GetLocalEnergyDeposit()); - theTotalResult->SetNumberOfSecondaries(aR->GetNumberOfSecondaries()); - - if(aR->GetStatusChange() != stopAndKill) - { - G4double newM=aT.GetParticleDefinition()->GetPDGMass(); - G4double newE=aR->GetEnergyChange() + newM; - G4double newP=std::sqrt(newE*newE - newM*newM); - G4ThreeVector newPV = newP*aR->GetMomentumChange(); - G4LorentzVector newP4(newE, newPV); - newP4.rotate(rotation, it); - newP4*=aR->GetTrafoToLab(); - theTotalResult->ProposeMomentumDirection(newP4.vect().unit()); - } - - for(G4int i=0; iGetNumberOfSecondaries(); ++i) - { - G4LorentzVector theM = aR->GetSecondary(i)->GetParticle()->Get4Momentum(); - theM.rotate(rotation, it); - theM*=aR->GetTrafoToLab(); - aR->GetSecondary(i)->GetParticle()->Set4Momentum(theM); - G4double time = aR->GetSecondary(i)->GetTime(); - if(time<0) time = aT.GetGlobalTime(); - - G4Track* track = new G4Track(aR->GetSecondary(i)->GetParticle(), - time, - aT.GetPosition()); - - G4double newWeight = aT.GetWeight()*aR->GetSecondary(i)->GetWeight(); - if(xBiasOn) { newWeight *= XBiasSecondaryWeight(); } - track->SetWeight(newWeight); - track->SetTouchableHandle(aT.GetTouchableHandle()); - theTotalResult->AddSecondary(track); - } - - aR->Clear(); - return; -} -*/ - -void CMSSIMPInelasticProcess::BiasCrossSectionByFactor(G4double aScale) { - xBiasOn = true; - aScaleFactor = aScale; - G4String it = GetProcessName(); - if ((it != "PhotonInelastic") && (it != "ElectroNuclear") && (it != "PositronNuclear")) { - G4ExceptionDescription ed; - G4Exception("CMSSIMPInelasticProcess::BiasCrossSectionByFactor", - "had009", - FatalException, - ed, - "Cross-section biasing available only for gamma and electro nuclear reactions."); - } - if (aScale < 100) { - G4ExceptionDescription ed; - G4Exception("CMSSIMPInelasticProcess::BiasCrossSectionByFactor", - "had010", - JustWarning, - ed, - "Cross-section bias readjusted to be above safe limit. New value is 100"); - aScaleFactor = 100.; - } -} - -G4HadFinalState* CMSSIMPInelasticProcess::CheckResult(const G4HadProjectile& aPro, - const G4Nucleus& aNucleus, - G4HadFinalState* result) const { - // check for catastrophic energy non-conservation, to re-sample the interaction - - G4HadronicInteraction* theModel = GetHadronicInteraction(); - G4double nuclearMass(0); - if (theModel) { - // Compute final-state total energy - G4double finalE(0.); - G4int nSec = result->GetNumberOfSecondaries(); - - nuclearMass = G4NucleiProperties::GetNuclearMass(aNucleus.GetA_asInt(), aNucleus.GetZ_asInt()); - if (result->GetStatusChange() != stopAndKill) { - // Interaction didn't complete, returned "do nothing" state => reset nucleus - // or the primary survived the interaction (e.g. electro-nuclear ) => keep nucleus - finalE = result->GetLocalEnergyDeposit() + aPro.GetDefinition()->GetPDGMass() + result->GetEnergyChange(); - if (nSec == 0) { - // Since there are no secondaries, there is no recoil nucleus. - // To check energy balance we must neglect the initial nucleus too. - nuclearMass = 0.0; - } - } - for (G4int i = 0; i < nSec; i++) { - finalE += result->GetSecondary(i)->GetParticle()->GetTotalEnergy(); - } - G4double deltaE = nuclearMass + aPro.GetTotalEnergy() - finalE; - - std::pair checkLevels = theModel->GetFatalEnergyCheckLevels(); // (relative, absolute) - if (std::abs(deltaE) > checkLevels.second && std::abs(deltaE) > checkLevels.first * aPro.GetKineticEnergy()) { - // do not delete result, this is a pointer to a data member; - result = nullptr; - G4ExceptionDescription desc; - desc << "Warning: Bad energy non-conservation detected, will " - << (epReportLevel < 0 ? "abort the event" : "re-sample the interaction") << G4endl - << " Process / Model: " << GetProcessName() << " / " << theModel->GetModelName() << G4endl - << " Primary: " << aPro.GetDefinition()->GetParticleName() << " (" << aPro.GetDefinition()->GetPDGEncoding() - << ")," - << " E= " << aPro.Get4Momentum().e() << ", target nucleus (" << aNucleus.GetZ_asInt() << "," - << aNucleus.GetA_asInt() << ")" << G4endl << " E(initial - final) = " << deltaE << " MeV." << G4endl; - G4Exception("CMSSIMPInelasticProcess:CheckResult()", - "had012", - epReportLevel < 0 ? EventMustBeAborted : JustWarning, - desc); - } - } - return result; -} - -void CMSSIMPInelasticProcess::CheckEnergyMomentumConservation(const G4Track& aTrack, const G4Nucleus& aNucleus) { - G4int target_A = aNucleus.GetA_asInt(); - G4int target_Z = aNucleus.GetZ_asInt(); - G4double targetMass = G4NucleiProperties::GetNuclearMass(target_A, target_Z); - G4LorentzVector target4mom(0, 0, 0, targetMass); - - G4LorentzVector projectile4mom = aTrack.GetDynamicParticle()->Get4Momentum(); - G4int track_A = aTrack.GetDefinition()->GetBaryonNumber(); - G4int track_Z = G4lrint(aTrack.GetDefinition()->GetPDGCharge()); - - G4int initial_A = target_A + track_A; - G4int initial_Z = target_Z + track_Z; - - G4LorentzVector initial4mom = projectile4mom + target4mom; - - // Compute final-state momentum for scattering and "do nothing" results - G4LorentzVector final4mom; - G4int final_A(0), final_Z(0); - - G4int nSec = theTotalResult->GetNumberOfSecondaries(); - if (theTotalResult->GetTrackStatus() != fStopAndKill) { // If it is Alive - // Either interaction didn't complete, returned "do nothing" state - // or the primary survived the interaction (e.g. electro-nucleus ) - G4Track temp(aTrack); - - // Use the final energy / momentum - temp.SetMomentumDirection(*theTotalResult->GetMomentumDirection()); - temp.SetKineticEnergy(theTotalResult->GetEnergy()); - - if (nSec == 0) { - // Interaction didn't complete, returned "do nothing" state - // - or suppressed recoil (e.g. Neutron elastic ) - final4mom = temp.GetDynamicParticle()->Get4Momentum() + target4mom; - final_A = initial_A; - final_Z = initial_Z; - } else { - // The primary remains in final state (e.g. electro-nucleus ) - final4mom = temp.GetDynamicParticle()->Get4Momentum(); - final_A = track_A; - final_Z = track_Z; - // Expect that the target nucleus will have interacted, - // and its products, including recoil, will be included in secondaries. - } - } - if (nSec > 0) { - G4Track* sec; - - for (G4int i = 0; i < nSec; i++) { - sec = theTotalResult->GetSecondary(i); - final4mom += sec->GetDynamicParticle()->Get4Momentum(); - final_A += sec->GetDefinition()->GetBaryonNumber(); - final_Z += G4lrint(sec->GetDefinition()->GetPDGCharge()); - } - } - - // Get level-checking information (used to cut-off relative checks) - G4String processName = GetProcessName(); - G4HadronicInteraction* theModel = GetHadronicInteraction(); - G4String modelName("none"); - if (theModel) - modelName = theModel->GetModelName(); - std::pair checkLevels = epCheckLevels; - if (!levelsSetByProcess) { - if (theModel) - checkLevels = theModel->GetEnergyMomentumCheckLevels(); - checkLevels.first = std::min(checkLevels.first, epCheckLevels.first); - checkLevels.second = std::min(checkLevels.second, epCheckLevels.second); - } - - // Compute absolute total-energy difference, and relative kinetic-energy - G4bool checkRelative = (aTrack.GetKineticEnergy() > checkLevels.second); - - G4LorentzVector diff = initial4mom - final4mom; - G4double absolute = diff.e(); - G4double relative = checkRelative ? absolute / aTrack.GetKineticEnergy() : 0.; - - G4double absolute_mom = diff.vect().mag(); - G4double relative_mom = checkRelative ? absolute_mom / aTrack.GetMomentum().mag() : 0.; - - // Evaluate relative and absolute conservation - G4bool relPass = true; - G4String relResult = "pass"; - if (std::abs(relative) > checkLevels.first || std::abs(relative_mom) > checkLevels.first) { - relPass = false; - relResult = checkRelative ? "fail" : "N/A"; - } - - G4bool absPass = true; - G4String absResult = "pass"; - if (std::abs(absolute) > checkLevels.second || std::abs(absolute_mom) > checkLevels.second) { - absPass = false; - absResult = "fail"; - } - - G4bool chargePass = true; - G4String chargeResult = "pass"; - if ((initial_A - final_A) != 0 || (initial_Z - final_Z) != 0) { - chargePass = checkLevels.second < DBL_MAX ? false : true; - chargeResult = "fail"; - } - - G4bool conservationPass = (relPass || absPass) && chargePass; - - std::stringstream Myout; - G4bool Myout_notempty(false); - // Options for level of reporting detail: - // 0. off - // 1. report only when E/p not conserved - // 2. report regardless of E/p conservation - // 3. report only when E/p not conserved, with model names, process names, and limits - // 4. report regardless of E/p conservation, with model names, process names, and limits - // negative -1.., as above, but send output to stderr - - if (std::abs(epReportLevel) == 4 || (std::abs(epReportLevel) == 3 && !conservationPass)) { - Myout << " Process: " << processName << " , Model: " << modelName << G4endl; - Myout << " Primary: " << aTrack.GetParticleDefinition()->GetParticleName() << " (" - << aTrack.GetParticleDefinition()->GetPDGEncoding() << ")," - << " E= " << aTrack.GetDynamicParticle()->Get4Momentum().e() << ", target nucleus (" << aNucleus.GetZ_asInt() - << "," << aNucleus.GetA_asInt() << ")" << G4endl; - Myout_notempty = true; - } - if (std::abs(epReportLevel) == 4 || std::abs(epReportLevel) == 2 || !conservationPass) { - Myout << " " << relResult << " relative, limit " << checkLevels.first << ", values E/T(0) = " << relative - << " p/p(0)= " << relative_mom << G4endl; - Myout << " " << absResult << " absolute, limit (MeV) " << checkLevels.second / MeV - << ", values E / p (MeV) = " << absolute / MeV << " / " << absolute_mom / MeV - << " 3mom: " << (diff.vect()) * 1. / MeV << G4endl; - Myout << " " << chargeResult << " charge/baryon number balance " << (initial_Z - final_Z) << " / " - << (initial_A - final_A) << " " << G4endl; - Myout_notempty = true; - } - Myout.flush(); - if (Myout_notempty) { - if (epReportLevel > 0) - G4cout << Myout.str() << G4endl; - else if (epReportLevel < 0) - G4cerr << Myout.str() << G4endl; - } -} + result->SetTrafoToLab(thePro.GetTrafoToLab()); -void CMSSIMPInelasticProcess::DumpState(const G4Track& aTrack, const G4String& method, G4ExceptionDescription& ed) { - ed << "Unrecoverable error in the method " << method << " of " << GetProcessName() << G4endl; - ed << "TrackID= " << aTrack.GetTrackID() << " ParentID= " << aTrack.GetParentID() << " " - << aTrack.GetParticleDefinition()->GetParticleName() << G4endl; - ed << "Ekin(GeV)= " << aTrack.GetKineticEnergy() / CLHEP::GeV << "; direction= " << aTrack.GetMomentumDirection() - << G4endl; - ed << "Position(mm)= " << aTrack.GetPosition() / CLHEP::mm << ";"; + ClearNumberOfInteractionLengthLeft(); - if (aTrack.GetMaterial()) { - ed << " material " << aTrack.GetMaterial()->GetName(); - } - ed << G4endl; + FillResult(result, aTrack); - if (aTrack.GetVolume()) { - ed << "PhysicalVolume <" << aTrack.GetVolume()->GetName() << ">" << G4endl; - } -} -/* -G4ParticleDefinition* CMSSIMPInelasticProcess::GetTargetDefinition() -{ - const G4Nucleus* nuc = GetTargetNucleus(); - G4int Z = nuc->GetZ_asInt(); - G4int A = nuc->GetA_asInt(); - return G4ParticleTable::GetParticleTable()->GetIon(Z,A,0*eV); + return theTotalResult; } -*/ -/* end of file */ diff --git a/SimG4Core/CustomPhysics/src/CMSSIMPInelasticXS.cc b/SimG4Core/CustomPhysics/src/CMSSIMPInelasticXS.cc index bed58be7ab084..6fccfdbb03603 100644 --- a/SimG4Core/CustomPhysics/src/CMSSIMPInelasticXS.cc +++ b/SimG4Core/CustomPhysics/src/CMSSIMPInelasticXS.cc @@ -6,203 +6,44 @@ #include "G4ElementTable.hh" #include "G4PhysicsLogVector.hh" #include "G4PhysicsVector.hh" -#include "G4ComponentGGHadronNucleusXsc.hh" -#include "G4HadronNucleonXsc.hh" -#include "G4NistManager.hh" +#include "G4NeutronInelasticXS.hh" #include "G4Proton.hh" -#include "Randomize.hh" +#include "G4Neutron.hh" -#include -#include -#include - -using namespace std; - -const G4int CMSSIMPInelasticXS::amin[] = {0, 0, 0, 6, 0, 10, 12, 14, 16, 0, 0, //1-10 - 0, 0, 0, 28, 0, 0, 0, 36, 0, 40, //11-20 - 0, 0, 0, 0, 0, 54, 0, 58, 63, 64, //21-30 - 0, 70, 0, 0, 0, 0, 0, 0, 0, 90, //31-40 - 0, 0, 0, 0, 0, 0, 107, 106, 0, 112, //41-50 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //51-60 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //61-70 - 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, //71-80 - 0, 204, 0, 0, 0, 0, 0, 0, 0, 0, //81-90 - 0, 235}; -const G4int CMSSIMPInelasticXS::amax[] = {0, 0, 0, 7, 0, 11, 13, 15, 18, 0, 0, //1-10 - 0, 0, 0, 30, 0, 0, 0, 40, 0, 48, //11-20 - 0, 0, 0, 0, 0, 58, 0, 64, 65, 70, //21-30 - 0, 76, 0, 0, 0, 0, 0, 0, 0, 96, //31-40 - 0, 0, 0, 0, 0, 0, 109, 116, 0, 124, //41-50 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //51-60 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //61-70 - 0, 0, 0, 186, 0, 0, 0, 0, 0, 0, //71-80 - 0, 208, 0, 0, 0, 0, 0, 0, 0, 0, //81-90 - 0, 238}; - -CMSSIMPInelasticXS::CMSSIMPInelasticXS() : G4VCrossSectionDataSet("CMSSIMPInelasticXS"), proton(G4Proton::Proton()) { +CMSSIMPInelasticXS::CMSSIMPInelasticXS() : G4VCrossSectionDataSet("CMSSIMPInelasticXS"), neutron(G4Neutron::Neutron()) { verboseLevel = 1; - if (verboseLevel > 0) { - G4cout << "CMSSIMPInelasticXS::CMSSIMPInelasticXS Initialise for Z < " << MAXZINEL << G4endl; - } - data.SetName("SIMPInelastic"); - work.resize(13, nullptr); - temp.resize(13, 0.0); - coeff.resize(MAXZINEL, 1.0); - ggXsection = new G4ComponentGGHadronNucleusXsc(); - fNucleon = new G4HadronNucleonXsc(); + nXsection = new G4NeutronInelasticXS(); isInitialized = false; } -CMSSIMPInelasticXS::~CMSSIMPInelasticXS() { delete fNucleon; } - -void CMSSIMPInelasticXS::CrossSectionDescription(std::ostream& outFile) const { - outFile << "CMSSIMPInelasticXS calculates the SIMP inelastic scattering\n" - << "cross section on nuclei using data from the high precision\n" - << "neutron database. These data are simplified and smoothed over\n" - << "the resonance region in order to reduce CPU time.\n" - << "CMSSIMPInelasticXS is valid for energies up to 20 MeV, for\n" - << "nuclei through U.\n"; -} +CMSSIMPInelasticXS::~CMSSIMPInelasticXS() {} G4bool CMSSIMPInelasticXS::IsElementApplicable(const G4DynamicParticle*, G4int, const G4Material*) { return true; } -G4bool CMSSIMPInelasticXS::IsIsoApplicable( - const G4DynamicParticle*, G4int /*ZZ*/, G4int /*AA*/, const G4Element*, const G4Material*) { +G4bool CMSSIMPInelasticXS::IsIsoApplicable(const G4DynamicParticle*, G4int, G4int, const G4Element*, const G4Material*) { return true; } -G4double CMSSIMPInelasticXS::GetElementCrossSection(const G4DynamicParticle* aParticle, G4int Z, const G4Material*) { - G4double xs = 0.0; - G4double ekin = aParticle->GetKineticEnergy(); - - if (Z < 1 || Z >= MAXZINEL) { - return xs; - } - G4int Amean = G4lrint(G4NistManager::Instance()->GetAtomicMassAmu(Z)); - - G4PhysicsVector* pv = data.GetElementData(Z); - if (verboseLevel > 0) { - G4cout << "CMSSIMPInelasticXS::GetCrossSection e= " << ekin << " Z= " << Z << G4endl; - } - - // element was not initialised - if (!pv) { - Initialise(Z); - pv = data.GetElementData(Z); - if (!pv) { - return xs; - } - } - - G4double e1 = pv->Energy(0); - if (ekin <= e1) { - return xs; - } - - G4double e2 = pv->GetMaxEnergy(); - - if (ekin <= e2) { - xs = pv->Value(ekin); - } else if (1 == Z) { - fNucleon->GetHadronNucleonXscPDG(aParticle, proton); - xs = coeff[1] * fNucleon->GetInelasticHadronNucleonXsc(); - } else { - ggXsection->GetIsoCrossSection(aParticle, Z, Amean); - xs = coeff[Z] * ggXsection->GetInelasticGlauberGribovXsc(); - } - - if (verboseLevel > 0) { - G4cout << "ekin= " << ekin << ", XSinel= " << xs << G4endl; - } - return xs; -} - -G4double CMSSIMPInelasticXS::GetIsoCrossSection( - const G4DynamicParticle* aParticle, G4int Z, G4int A, const G4Isotope*, const G4Element*, const G4Material*) { - G4double xs = 0.0; - G4double ekin = aParticle->GetKineticEnergy(); - if (Z > 0 && Z < MAXZINEL) { - xs = IsoCrossSection(ekin, Z, A); - } - return xs; -} - -G4double CMSSIMPInelasticXS::IsoCrossSection(G4double ekin, G4int Z, G4int A) { - G4double xs = 0.0; - - G4PhysicsVector* pv = data.GetElementData(Z); - - // element was not initialised - if (!pv) { - Initialise(Z); - pv = data.GetElementData(Z); - if (!pv) { - return xs; - } - } - G4PhysicsVector* pviso = data.GetComponentDataByID(Z, A); - if (pviso) { - pv = pviso; - } - - xs = pv->Value(ekin); - - if (verboseLevel > 0) { - G4cout << "ekin= " << ekin << ", xs= " << xs << G4endl; - } - return xs; +G4double CMSSIMPInelasticXS::GetElementCrossSection(const G4DynamicParticle* aParticle, + G4int Z, + const G4Material* mat) { + return nXsection->GetElementCrossSection(aParticle, Z, mat); } -G4Isotope* CMSSIMPInelasticXS::SelectIsotope(const G4Element* anElement, G4double kinEnergy) { - G4int nIso = anElement->GetNumberOfIsotopes(); - G4IsotopeVector* isoVector = anElement->GetIsotopeVector(); - G4Isotope* iso = (*isoVector)[0]; - - // more than 1 isotope - if (1 < nIso) { - G4int Z = G4lrint(anElement->GetZ()); - if (Z >= MAXZINEL) { - Z = MAXZINEL - 1; - } - G4double* abundVector = anElement->GetRelativeAbundanceVector(); - G4double q = G4UniformRand(); - G4double sum = 0.0; - - // is there isotope wise cross section? - if (0 == amin[Z]) { - for (G4int j = 0; j < nIso; ++j) { - sum += abundVector[j]; - if (q <= sum) { - iso = (*isoVector)[j]; - break; - } - } - } else { - size_t nmax = data.GetNumberOfComponents(Z); - if (temp.size() < nmax) { - temp.resize(nmax, 0.0); - } - for (size_t i = 0; i < nmax; ++i) { - G4int A = (*isoVector)[i]->GetN(); - sum += abundVector[i] * IsoCrossSection(kinEnergy, Z, A); - temp[i] = sum; - } - sum *= q; - for (size_t j = 0; j < nmax; ++j) { - if (temp[j] >= sum) { - iso = (*isoVector)[j]; - break; - } - } - } - } - return iso; +G4double CMSSIMPInelasticXS::GetIsoCrossSection(const G4DynamicParticle* aParticle, + G4int Z, + G4int A, + const G4Isotope* iso, + const G4Element* elm, + const G4Material* mat) { + return nXsection->GetIsoCrossSection(aParticle, Z, A, iso, elm, mat); } void CMSSIMPInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p) { if (isInitialized) { return; } + nXsection->BuildPhysicsTable(p); if (verboseLevel > 0) { G4cout << "CMSSIMPInelasticXS::BuildPhysicsTable for " << p.GetParticleName() << G4endl; } @@ -214,131 +55,4 @@ void CMSSIMPInelasticXS::BuildPhysicsTable(const G4ParticleDefinition& p) { return; } isInitialized = true; - - // check environment variable - // Build the complete string identifying the file with the data set - char* path = getenv("G4NEUTRONXSDATA"); - - G4DynamicParticle* dynParticle = new G4DynamicParticle(CMSSIMP::SIMP(), G4ThreeVector(1, 0, 0), 1); - - // Access to elements - const G4ElementTable* theElmTable = G4Element::GetElementTable(); - size_t numOfElm = G4Element::GetNumberOfElements(); - if (numOfElm > 0) { - for (size_t i = 0; i < numOfElm; ++i) { - G4int Z = G4lrint(((*theElmTable)[i])->GetZ()); - if (Z < 1) { - Z = 1; - } else if (Z >= MAXZINEL) { - Z = MAXZINEL - 1; - } - //G4cout << "Z= " << Z << G4endl; - // Initialisation - if (!data.GetElementData(Z)) { - Initialise(Z, dynParticle, path); - } - } - } - delete dynParticle; -} - -void CMSSIMPInelasticXS::Initialise(G4int Z, G4DynamicParticle* dp, const char* p) { - if (data.GetElementData(Z)) { - return; - } - const char* path = p; - if (!p) { - // check environment variable - // Build the complete string identifying the file with the data set - path = getenv("G4NEUTRONXSDATA"); - if (!path) { - G4Exception("CMSSIMPInelasticXS::Initialise(..)", - "had013", - FatalException, - "Environment variable G4NEUTRONXSDATA is not defined"); - return; - } - } - G4DynamicParticle* dynParticle = dp; - if (!dp) { - dynParticle = new G4DynamicParticle(G4Neutron::Neutron(), G4ThreeVector(1, 0, 0), 1); - } - - G4int Amean = G4lrint(G4NistManager::Instance()->GetAtomicMassAmu(Z)); - - // upload element data - std::ostringstream ost; - ost << path << "/inelast" << Z; - G4PhysicsVector* v = RetrieveVector(ost, true); - data.InitialiseForElement(Z, v); - - // upload isotope data - if (amin[Z] > 0) { - size_t n = 0; - size_t i = 0; - size_t nmax = (size_t)(amax[Z] - amin[Z] + 1); - if (work.size() < nmax) { - work.resize(nmax, nullptr); - } - for (G4int A = amin[Z]; A <= amax[Z]; ++A) { - std::ostringstream ost1; - ost1 << path << "/cap" << Z << "_" << A; - G4PhysicsVector* v1 = RetrieveVector(ost1, false); - if (v1) { - ++n; - } - work[i] = v1; - ++i; - } - data.InitialiseForComponent(Z, n); - for (size_t j = 0; j < i; ++j) { - if (work[j]) { - data.AddComponent(Z, amin[Z] + j, work[j]); - } - } - } - - // smooth transition - G4double emax = v->GetMaxEnergy(); - G4double sig1 = (*v)[v->GetVectorLength() - 1]; - dynParticle->SetKineticEnergy(emax); - G4double sig2 = 0.0; - if (1 == Z) { - fNucleon->GetHadronNucleonXscPDG(dynParticle, proton); - sig2 = fNucleon->GetInelasticHadronNucleonXsc(); - } else { - ggXsection->GetIsoCrossSection(dynParticle, Z, Amean); - sig2 = ggXsection->GetInelasticGlauberGribovXsc(); - } - if (sig2 > 0.) { - coeff[Z] = sig1 / sig2; - } - if (!dp) { - delete dynParticle; - } -} - -G4PhysicsVector* CMSSIMPInelasticXS::RetrieveVector(std::ostringstream& ost, G4bool warn) { - G4PhysicsLogVector* v = nullptr; - std::ifstream filein(ost.str().c_str()); - if (!(filein)) { - if (!warn) { - return v; - } - G4ExceptionDescription ed; - ed << "Data file <" << ost.str().c_str() << "> is not opened!"; - G4Exception("CMSSIMPInelasticXS::RetrieveVector(..)", "had014", FatalException, ed, "Check G4NEUTRONXSDATA"); - } else { - if (verboseLevel > 1) { - G4cout << "File " << ost.str() << " is opened by CMSSIMPInelasticXS" << G4endl; - } - // retrieve data from DB - v = new G4PhysicsLogVector(); - if (!v->Retrieve(filein, true)) { - G4ExceptionDescription ed; - ed << "Data file <" << ost.str().c_str() << "> is not retrieved!"; - G4Exception("CMSSIMPInelasticXS::RetrieveVector(..)", "had015", FatalException, ed, "Check G4NEUTRONXSDATA"); - } - } - return v; } diff --git a/SimG4Core/CustomPhysics/src/CustomPhysicsList.cc b/SimG4Core/CustomPhysics/src/CustomPhysicsList.cc index 0fde1a55c93f1..67cd877c15ddd 100644 --- a/SimG4Core/CustomPhysics/src/CustomPhysicsList.cc +++ b/SimG4Core/CustomPhysics/src/CustomPhysicsList.cc @@ -61,10 +61,7 @@ void CustomPhysicsList::ConstructProcess() { G4ProcessManager* pmanager = particle->GetProcessManager(); if (pmanager) { CMSSIMPInelasticProcess* simpInelPr = new CMSSIMPInelasticProcess(); - CMSQGSPSIMPBuilder* theQGSPSIMPB = - new CMSQGSPSIMPBuilder(false); // false -> no QuasiElastic (not adapted for SIMP - crashes) - theQGSPSIMPB->SetMinEnergy(12.0 * - MeV); // normally this is GeV, but that leads to crashes with the massive SIMPs + CMSQGSPSIMPBuilder* theQGSPSIMPB = new CMSQGSPSIMPBuilder(); theQGSPSIMPB->Build(simpInelPr); pmanager->AddDiscreteProcess(simpInelPr); } else