diff --git a/NPSimulation/Process/ThreeBody.cc b/NPSimulation/Process/ThreeBody.cc new file mode 100644 index 0000000000000000000000000000000000000000..f8415e749b2f9520bd212ab1fbc6d06e8d617a87 --- /dev/null +++ b/NPSimulation/Process/ThreeBody.cc @@ -0,0 +1,532 @@ +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: Valerian Alcindor * + * contact address: valcindor@ikp.tu-darmstadt.de * + * * + * Creation Date : 2019 * + * Last update : August 2020 * + *---------------------------------------------------------------------------* + * Decription: * + * Generation of sequential three body decay from resonant states * + * * + * * + * * + *---------------------------------------------------------------------------* + * Comment: * + * * + *****************************************************************************/ + +#include "ThreeBody.hh" +#include "G4Electron.hh" +#include "G4Gamma.hh" +#include "G4IonTable.hh" +#include "G4ParticleTable.hh" +#include "G4SystemOfUnits.hh" +#include "G4VPhysicalVolume.hh" +#include "NPFunction.h" +#include "NPInputParser.h" +#include "NPOptionManager.h" +#include "Particle.hh" +#include "RootOutput.h" +#include "TGenPhaseSpace.h" +#include <iostream> +#include <string> +//////////////////////////////////////////////////////////////////////////////// +NPS::ThreeBody::ThreeBody(G4String modelName, G4Region* envelope) + : G4VFastSimulationModel(modelName, envelope) { + ReadConfiguration(); + m_PreviousEnergy = 0; + m_PreviousLength = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +NPS::ThreeBody::ThreeBody(G4String modelName) + : G4VFastSimulationModel(modelName) {} + +//////////////////////////////////////////////////////////////////////////////// +NPS::ThreeBody::~ThreeBody() {} + +//////////////////////////////////////////////////////////////////////////////// +void NPS::ThreeBody::AttachReactionConditions() { + // Reasssigned the branch address + if (RootOutput::getInstance()->GetTree()->FindBranch("ReactionConditions")) + RootOutput::getInstance()->GetTree()->SetBranchAddress( + "ReactionConditions", &m_ReactionConditions); +} + +//////////////////////////////////////////////////////////////////////////////// +void NPS::ThreeBody::ReadConfiguration() { + NPL::InputParser input(NPOptionManager::getInstance()->GetReactionFile()); + + vector<NPL::InputBlock*> blocks = input.GetAllBlocksWithToken("ThreeBody"); + if (blocks.size() > 0) { + m_active = true; + m_ReactionConditions = new TReactionConditions(); + AttachReactionConditions(); + if (!RootOutput::getInstance()->GetTree()->FindBranch("ReactionConditions")) + RootOutput::getInstance()->GetTree()->Branch( + "ReactionConditions", "TReactionConditions", &m_ReactionConditions); + + for (unsigned int i = 0; i < blocks.size(); i++) { + if (blocks[i]->HasToken("Type")) + m_type = blocks[i]->GetString("Type"); + + if (blocks[i]->HasToken("Beam")) + m_Beam = blocks[i]->GetString("Beam"); + + if (blocks[i]->HasToken("Target")) + m_TargetNucleus = blocks[i]->GetString("Target"); + + if (blocks[i]->HasToken("CompoundNucleusEnergy")) + m_CompoundNucleusEnergy + = blocks[i]->GetDouble("CompoundNucleusEnergy", "MeV"); + + if (blocks[i]->HasToken("CompoundNucleusStateWidth")) + m_CompoundNucleusStateWidth + = blocks[i]->GetDouble("CompoundNucleusStateWidth", "MeV"); + + if (blocks[i]->HasToken("IntermediaryNucleus")) + m_IntermediaryNucleus = blocks[i]->GetString("IntermediaryNucleus"); + + if (blocks[i]->HasToken("IntermediaryState")) + m_IntermediaryState = blocks[i]->GetDouble("IntermediaryState", "MeV"); + + if (blocks[i]->HasToken("IntermediaryStateWidth")) + m_IntermediaryStateWidth + = blocks[i]->GetDouble("IntermediaryStateWidth", "MeV"); + + if (blocks[i]->HasToken("Light1")) + m_Light1 = blocks[i]->GetString("Light1"); + + if (blocks[i]->HasToken("Heavy")) + m_Heavy = blocks[i]->GetString("Heavy"); + + if (blocks[i]->HasToken("Light2")) + m_Light2 = blocks[i]->GetString("Light2"); + + if (blocks[i]->HasToken("ExcitationEnergyHeavy")) + m_ExcitationEnergyHeavy + = blocks[i]->GetDouble("ExcitationEnergyHeavy", "MeV"); + + if (blocks[i]->HasToken("ShootLight1")) + m_ShootLight1 = blocks[i]->GetInt("ShootLight1"); + + if (blocks[i]->HasToken("ShootLight2")) + m_ShootLight2 = blocks[i]->GetInt("ShootLight2"); + + if (blocks[i]->HasToken("ShootHeavy")) + m_ShootHeavy = blocks[i]->GetInt("ShootHeavy"); + + m_UserEnergyCS = false; + if (blocks[i]->HasToken("UserEnergyCS")) { + m_UserEnergyCS = blocks[i]->GetInt("UserEnergyCS"); + + cout << m_UserEnergyCS << endl; + + if (blocks[i]->HasToken("EnergyCSPath")) + m_EnergyCSPath = blocks[i]->GetString("EnergyCSPath"); + + if (blocks[i]->HasToken("EnergyCSName")) + m_EnergyCSName = blocks[i]->GetString("EnergyCSName"); + + if (m_UserEnergyCS) { + m_FileEnergyCS = new TFile(m_EnergyCSPath.c_str(), "open"); + m_EnergyCS + = (TF1*)m_FileEnergyCS->FindObjectAny(m_EnergyCSName.c_str()); + m_EnergyCSMax = m_EnergyCS->GetMaximum(); + m_EnergyCS->SetNpx(1e6); + m_FileEnergyCS->Close(); + } + } else { + cout << "ERROR: check your input file formatting \033[0m" << endl; + exit(1); + } + } + m_BeamName = NPL::ChangeNameToG4Standard(m_Beam); + m_N1 = NPL::Particle(m_Beam); + m_N2 = NPL::Particle(m_TargetNucleus); + + m_N3 = NPL::Particle(m_Light1); + m_N4 = NPL::Particle(m_IntermediaryNucleus); + + m_N5 = NPL::Particle(m_Light2); + m_N6 = NPL::Particle(m_Heavy); + m_end = false; + m_previousE = -1000; + fIntermediaryStateEnergy = GetIntermediaryStateEnergy( + m_IntermediaryState, m_IntermediaryStateWidth); + } else + m_active = false; +} + +//////////////////////////////////////////////////////////////////////////////// +G4bool NPS::ThreeBody::IsApplicable(const G4ParticleDefinition& particleType) { + NPL::InputParser input(NPOptionManager::getInstance()->GetReactionFile()); + + vector<NPL::InputBlock*> blocks = input.GetAllBlocksWithToken("ThreeBody"); + if (!m_active) + return false; + if (!m_active) + return false; + else { + static std::string particleName; + particleName = particleType.GetParticleName(); + if (particleName.find(m_BeamName) != std::string::npos + && blocks.size() > 0) { + return true; + } + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +G4bool NPS::ThreeBody::ModelTrigger(const G4FastTrack& fastTrack) { + static bool shoot = false; + static double rand = 0; + const G4Track* PrimaryTrack = fastTrack.GetPrimaryTrack(); + G4ThreeVector V = PrimaryTrack->GetMomentum().unit(); + G4ThreeVector P = fastTrack.GetPrimaryTrackLocalPosition(); + G4VSolid* solid = fastTrack.GetPrimaryTrack() + ->GetVolume() + ->GetLogicalVolume() + ->GetSolid(); + double in = solid->DistanceToOut(P, V); + double out = solid->DistanceToOut(P, -V); + double ratio = in / (out + in); + + if (out == 0) { // first step of current event + rand = G4RandFlat::shoot(); + m_PreviousLength = m_StepSize; + m_PreviousEnergy = PrimaryTrack->GetKineticEnergy(); + // Clear Previous Event + m_ReactionConditions->Clear(); + shoot = true; + } else if (in == 0) { // last step + return true; + } + + // If the condition is met, the event is generated + if (ratio < rand) { + // Reset the static for next event + if (shoot) { + // && m_Reaction.IsAllowed(PrimaryTrack->GetKineticEnergy())) { + shoot = false; + return true; + } else { + return false; + } + } + + // Record the situation of the current step + // so it can be used in the next one + if (!PrimaryTrack->GetStep()->IsLastStepInVolume()) { + m_PreviousLength = PrimaryTrack->GetStep()->GetStepLength(); + m_PreviousEnergy = PrimaryTrack->GetKineticEnergy(); + } + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +void NPS::ThreeBody::DoIt(const G4FastTrack& fastTrack, G4FastStep& fastStep) { + // Get the track info + const G4Track* PrimaryTrack = fastTrack.GetPrimaryTrack(); + G4ThreeVector pdirection = PrimaryTrack->GetMomentum().unit(); + G4ThreeVector localdir = fastTrack.GetPrimaryTrackLocalDirection(); + + G4ThreeVector worldPosition = PrimaryTrack->GetPosition(); + G4ThreeVector localPosition = fastTrack.GetPrimaryTrackLocalPosition(); + + double energy = PrimaryTrack->GetKineticEnergy(); + double time = PrimaryTrack->GetGlobalTime(); + + ///////////////////////// + /// Beam Parameters ///// + ///////////////////////// + m_ReactionConditions->SetBeamParticleName( + PrimaryTrack->GetParticleDefinition()->GetParticleName()); + + G4ThreeVector U(1, 0, 0); + G4ThreeVector V(0, 1, 0); + G4ThreeVector ZZ(0, 0, 1); + m_ReactionConditions->SetBeamEmittanceTheta( + PrimaryTrack->GetMomentumDirection().theta() / deg); + m_ReactionConditions->SetBeamEmittancePhi( + PrimaryTrack->GetMomentumDirection().phi() / deg); + m_ReactionConditions->SetBeamEmittanceThetaX( + PrimaryTrack->GetMomentumDirection().angle(U) / deg); + m_ReactionConditions->SetBeamEmittancePhiY( + PrimaryTrack->GetMomentumDirection().angle(V) / deg); + + // Randomize within the step + // Assume energy loss is linear within the step + // Assume no scattering + double rand = G4RandFlat::shoot(); + double length = rand * (m_PreviousLength); + energy -= (1 - rand) * (m_PreviousEnergy - energy); + G4ThreeVector ldir = pdirection; + ldir *= length; + localPosition = localPosition - ldir; + + m_ReactionConditions->SetBeamReactionEnergy(energy); + m_ReactionConditions->SetVertexPositionX(localPosition.x()); + m_ReactionConditions->SetVertexPositionY(localPosition.y()); + m_ReactionConditions->SetVertexPositionZ(localPosition.z()); + + // Set the end of the step conditions + fastStep.SetPrimaryTrackFinalKineticEnergyAndDirection(0, pdirection); + fastStep.SetPrimaryTrackFinalPosition(worldPosition); + fastStep.SetTotalEnergyDeposited(0); + fastStep.SetPrimaryTrackFinalTime(time); + fastStep.KillPrimaryTrack(); + fastStep.SetPrimaryTrackPathLength(0.0); + + double Ecm = sqrt(m_N1.Mass() * m_N1.Mass() + m_N2.Mass() * m_N2.Mass() + + 2 * m_N2.Mass() * (energy + m_N1.Mass())) + - m_N1.Mass() - m_N2.Mass(); + if (m_UserEnergyCS == 0) { + Ecm = m_CompoundNucleusEnergy; + } + + bool Allowed = false; + if (Ecm < m_IntermediaryState) + Ecm = 0; + if (m_UserEnergyCS) { + double cs_value = m_EnergyCS->Eval(Ecm) / m_EnergyCSMax; + double rand_cs = G4RandFlat::shoot(); + if (rand_cs < cs_value) { + Allowed = true; + } + } else if (Ecm > m_IntermediaryState) { + Allowed = true; + } + + if (Allowed) { + ///////////////////////////////////////////////// + //////Define the kind of particle to shoot//////// + ////////////////////////////////////////////////// + + // Build the decaying particle four momenta vector: + double BeamEnergy = energy; + + G4ThreeVector BeamMomentumG4V = pdirection; + + // Before reaction + double m1 = m_N1.Mass(); + double m2 = m_N2.Mass(); + + // After first emission + double m3 = m_N3.Mass(); + + double IntermediaryStateEnergy = 0.; + double SpSn = m_N4.GetBindingEnergy() - m_N6.GetBindingEnergy(); + if (m_IntermediaryStateWidth == 0) { + IntermediaryStateEnergy = m_IntermediaryState; + } else { + while (true) { + IntermediaryStateEnergy = fIntermediaryStateEnergy->GetRandom(); + if (IntermediaryStateEnergy > SpSn && IntermediaryStateEnergy < Ecm) + break; + } + } + + m_N4.SetExcitationEnergy(IntermediaryStateEnergy); + double m4 = m_N4.Mass(); + + // After second emission + double m5 = m_N5.Mass(); + double m6 = m_N6.Mass(); + + std::vector<NPL::Particle> DaughterNuclei; + DaughterNuclei.push_back(m_N3); + DaughterNuclei.push_back(m_N5); + DaughterNuclei.push_back(m_N6); + + double T1 = BeamEnergy; + if (m_UserEnergyCS == 0) { + T1 = (pow((Ecm + m_N1.Mass() + m_N2.Mass()), 2.) + - (m_N1.Mass() * m_N1.Mass() + m_N2.Mass() * m_N2.Mass())) + / (2. * m_N2.Mass()) + - m_N1.Mass(); + } + + TVector3 p1(BeamMomentumG4V.x(), BeamMomentumG4V.y(), BeamMomentumG4V.z()); + + double gamma1 = T1 / m1 + 1.; + double Beta1 = sqrt(1. - 1. / (gamma1 * gamma1)); + p1.SetMag(gamma1 * m1 * Beta1); + TLorentzVector LV_1(p1.x(), p1.y(), p1.z(), T1 + m1); + + TVector3 p2(0, 0, 0); + TLorentzVector LV_2(p2.x(), p2.y(), p2.z(), m2); + + TLorentzVector LV_CN = LV_1 + LV_2; + + ///////////////////////// + // Sequential emission // + ///////////////////////// + + if (m_type == "sequential") { + // First particle emission + double T3, T4 = 0; + unsigned int nDecay = 2; + double* masses34 = new double[nDecay]; + masses34[0] = m3 / 1000.; + masses34[1] = m4 / 1000.; + double* T34 = new double[nDecay]; + double* theta34 = new double[nDecay]; + double* phi34 = new double[nDecay]; + + GetDecay(LV_CN.Vect(), LV_CN.E(), 2, masses34, T34, theta34, phi34); + TVector3 p3(0, 0, 1); + p3.SetTheta(theta34[0]); + p3.SetPhi(phi34[0]); + T3 = T34[0]; + double gamma3 = T3 / m3 + 1; + double Beta3 = sqrt(1 - 1 / (gamma3 * gamma3)); + p3.SetMag(gamma3 * m3 * Beta3); + G4ThreeVector p3G4 = G4ThreeVector(p3.x(), p3.y(), p3.z()); + + TVector3 p4(0, 0, 1); + p4.SetTheta(theta34[1]); + p4.SetPhi(phi34[1]); + T4 = T34[1]; + double gamma4 = T4 / m4 + 1; + double Beta4 = sqrt(1 - 1 / (gamma4 * gamma4)); + p4.SetMag(gamma4 * m4 * Beta4); + TLorentzVector LV_4(p4.x(), p4.y(), p4.z(), T4 + m4); + + // Second particle emission + double T5, T6 = 0; + nDecay = 2; + double* masses56 = new double[nDecay]; + masses56[0] = m5 / 1000.; + masses56[1] = m6 / 1000.; + double* T56 = new double[nDecay]; + double* theta56 = new double[nDecay]; + double* phi56 = new double[nDecay]; + GetDecay(LV_4.Vect(), LV_4.E(), 2, masses56, T56, theta56, phi56); + TVector3 p5(0, 0, 1); + p5.SetTheta(theta56[0]); + p5.SetPhi(phi56[0]); + T5 = T56[0]; + double gamma5 = T5 / m5 + 1; + double Beta5 = sqrt(1 - 1 / (gamma5 * gamma5)); + p5.SetMag(gamma5 * m5 * Beta5); + G4ThreeVector p5G4 = G4ThreeVector(p5.x(), p5.y(), p5.z()); + + TVector3 p6(0, 0, 1); + p6.SetTheta(theta56[1]); + p6.SetPhi(phi56[1]); + T6 = T56[1]; + double gamma6 = T6 / m6 + 1; + double Beta6 = sqrt(1 - 1 / (gamma6 * gamma6)); + p6.SetMag(gamma6 * m6 * Beta6); + G4ThreeVector p6G4 = G4ThreeVector(p6.x(), p6.y(), p6.z()); + + G4ParticleDefinition* Light1 + = G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon( + m_N3.GetZ(), m_N3.GetA(), 0); + + G4ParticleDefinition* Light2 + = G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon( + m_N5.GetZ(), m_N5.GetA(), 0); + + G4ParticleDefinition* Heavy + = G4ParticleTable::GetParticleTable()->GetIonTable()->GetIon( + m_N6.GetZ(), m_N6.GetA(), m_ExcitationEnergyHeavy); + + TLorentzVector LVproton1(p3.x(), p3.y(), p3.z(), T3 + m3); + TLorentzVector LVproton2(p5.x(), p5.y(), p5.z(), T5 + m5); + TLorentzVector LVHeavy(p6.x(), p6.y(), p6.z(), T6 + m6); + + TLorentzVector All = LVproton1 + LVproton2 + LVHeavy; + + // Emitt secondary + if (m_ShootLight1) { + G4DynamicParticle particleLight1(Light1, p3G4.unit(), T3); + fastStep.CreateSecondaryTrack(particleLight1, localPosition, time); + } + + if (m_ShootLight2) { + G4DynamicParticle particleLight2(Light2, p5G4.unit(), T5); + fastStep.CreateSecondaryTrack(particleLight2, localPosition, time); + } + if (m_ShootHeavy) { + G4DynamicParticle particleHeavy(Heavy, p6G4.unit(), T6); + fastStep.CreateSecondaryTrack(particleHeavy, localPosition, time); + } + /////////////////////////////////////// + ///// Emitted particle Parameters ///// + /////////////////////////////////////// + m_ReactionConditions->SetParticleName(Light1->GetParticleName()); + m_ReactionConditions->SetKineticEnergy(T3); + m_ReactionConditions->SetTheta(theta34[0] / deg); + if ((phi34[0] + pi) / deg > 360) + m_ReactionConditions->SetPhi((phi34[0] - pi) / deg); + else + m_ReactionConditions->SetPhi((phi34[0] + pi) / deg); + + m_ReactionConditions->SetParticleName(Light2->GetParticleName()); + m_ReactionConditions->SetKineticEnergy(T5); + m_ReactionConditions->SetTheta(theta56[0] / deg); + if ((phi56[0] + pi) / deg > 360) + m_ReactionConditions->SetPhi((phi56[0] - pi) / deg); + else + m_ReactionConditions->SetPhi((phi56[0] + pi) / deg); + + m_ReactionConditions->SetParticleName(Heavy->GetParticleName()); + m_ReactionConditions->SetKineticEnergy(T6); + m_ReactionConditions->SetTheta(theta56[1] / deg); + if ((phi56[1] + pi) / deg > 360) + m_ReactionConditions->SetPhi((phi56[1] - pi) / deg); + else + m_ReactionConditions->SetPhi((phi56[1] + pi) / deg); + } + } + + // Reinit for next event + m_PreviousEnergy = 0; + m_PreviousLength = 0; +} + +void NPS::ThreeBody::GetDecay(TVector3 p1, double Etot1, unsigned int nDecay, + double* masses, double* T, double* theta, + double* phi) { + TGenPhaseSpace PhaseSpace; + TLorentzVector NucleiToDecay(p1.x() / 1000., p1.y() / 1000., p1.z() / 1000., + Etot1 / 1000.); + + if (!PhaseSpace.SetDecay(NucleiToDecay, nDecay, masses)) { + cout << "FORBIDDEN PHASE SPACE CHECK ENERGIES" << endl; + for (unsigned int i = 0; i < nDecay; i++) { + T[i] = (PhaseSpace.GetDecay(i)->E() - masses[i]) * 1000.; + theta[i] = PhaseSpace.GetDecay(i)->Theta(); + phi[i] = PhaseSpace.GetDecay(i)->Phi(); + } + exit(1); + } else { + PhaseSpace.Generate(); + for (unsigned int i = 0; i < nDecay; i++) { + T[i] = (PhaseSpace.GetDecay(i)->E() - masses[i]) * 1000.; + theta[i] = PhaseSpace.GetDecay(i)->Theta(); + phi[i] = PhaseSpace.GetDecay(i)->Phi(); + } + } +} + +TF1* NPS::ThreeBody::GetIntermediaryStateEnergy(double Er, double Width) { + + TF1* f + = new TF1("f", "1. / (pow((x - [0]), 2.) + pow(([1] / 2.), 2.))", 0, 100); + f->SetParameter(0, Er); + f->SetParameter(1, Width); + f->SetNpx(1e6); + return f; +} diff --git a/NPSimulation/Process/ThreeBody.hh b/NPSimulation/Process/ThreeBody.hh new file mode 100644 index 0000000000000000000000000000000000000000..91a3ec1be96d7c7926e36edbb7ebe5e88dd85c62 --- /dev/null +++ b/NPSimulation/Process/ThreeBody.hh @@ -0,0 +1,107 @@ +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: Adrien MATTA contact address: matta@lpccaen.in2p3.fr * + * * + * Creation Date : Octobre 2017 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * Use to kill the beam track and replace it with the reaction product * + * * + * * + * * + *---------------------------------------------------------------------------* + * Comment: * + * * + *****************************************************************************/ + +#ifndef ThreeBody_h +#define ThreeBody_h + +#include "G4VFastSimulationModel.hh" +#include "NPReaction.h" +#include "PhysicsList.hh" +#include "TReactionConditions.h" + +#include "TF1.h" +#include "TFile.h" + +class G4VPhysicalVolume; +namespace NPS { +class ThreeBody : public G4VFastSimulationModel { +public: + ThreeBody(G4String, G4Region*); + ThreeBody(G4String); + ~ThreeBody(); + +public: + void ReadConfiguration(); + G4bool IsApplicable(const G4ParticleDefinition&); + G4bool ModelTrigger(const G4FastTrack&); + void DoIt(const G4FastTrack&, G4FastStep&); + +private: + NPL::Reaction m_Reaction; + string m_BeamName; + double m_PreviousEnergy; + double m_PreviousLength; + bool m_active; // is the process active + double m_StepSize; + +private: + TReactionConditions* m_ReactionConditions; + +public: + void AttachReactionConditions(); + void SetStepSize(double step) { m_StepSize = step; }; + +public: + bool m_end; + double m_previousE; + std::string m_type; + std::string m_Beam; + std::string m_TargetNucleus; + double m_CompoundNucleusEnergy; + double m_CompoundNucleusStateWidth; + std::string m_IntermediaryNucleus; + double m_IntermediaryState; + double m_IntermediaryStateWidth; + std::string m_Light1; + std::string m_Heavy; + std::string m_Light2; + double m_ExcitationEnergyHeavy; + int m_ShootLight1; + int m_ShootLight2; + int m_ShootHeavy; + NPL::Particle m_N1; + NPL::Particle m_N2; + + NPL::Particle m_N3; + NPL::Particle m_N4; + + NPL::Particle m_N5; + NPL::Particle m_N6; + + bool m_UserEnergyCS; + std::string m_EnergyCSPath; + std::string m_EnergyCSName; + TFile* m_FileEnergyCS; + TF1* m_EnergyCS; + double m_EnergyCSMax; + TF1* fIntermediaryStateEnergy; + +public: // Managing the decay + // Set everything for the decay + void GetDecay(TVector3 p, double Etot, unsigned int nDecay, double* masses, + double* T, double* theta, double* phi); + TF1* GetIntermediaryStateEnergy(double Er, double Width); +}; +} // namespace NPS + +#endif diff --git a/Projects/MultiParticleRES/.DS_Store b/Projects/MultiParticleRES/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..778fb5116f78b23a659c81f76fafdfb8fa17de68 Binary files /dev/null and b/Projects/MultiParticleRES/.DS_Store differ diff --git a/Projects/MultiParticleRES/Inputs/.DS_Store b/Projects/MultiParticleRES/Inputs/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 Binary files /dev/null and b/Projects/MultiParticleRES/Inputs/.DS_Store differ diff --git a/Projects/MultiParticleRES/Inputs/BW.root b/Projects/MultiParticleRES/Inputs/BW.root new file mode 100644 index 0000000000000000000000000000000000000000..2838ace698508d1f053ff30ce8ec6fab773189ca Binary files /dev/null and b/Projects/MultiParticleRES/Inputs/BW.root differ diff --git a/Projects/MultiParticleRES/Inputs/ExampleSequential15F.detector b/Projects/MultiParticleRES/Inputs/ExampleSequential15F.detector new file mode 100755 index 0000000000000000000000000000000000000000..bfc19a7ede9a20ab79fb30003940ba1806e8bc8e --- /dev/null +++ b/Projects/MultiParticleRES/Inputs/ExampleSequential15F.detector @@ -0,0 +1,75 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Target + THICKNESS= 106.5 micrometer + RADIUS= 30 mm + MATERIAL= CH2 + ANGLE= 0 deg + X= 0 mm + Y= 0 mm + Z= 0 cm + +% %%%%%%%%%%%%%%%%%%%%%%%%% +% % Experiment thickness = 34um +% beam_dump +% R= 830 mm +% THETA = 0 +% PHI = 0 +% Thickness= 45 micrometer +% +%%%%%%% Telescope 1 DSSD5 %%%%%%% +M2Telescope + X128_Y128= -12.05 104.5 147.54 + X128_Y1= -102.43 104.7 111.59 + X1_Y1= -114.08 12.53 140.36 + X1_Y128= -23.71 12.32 176.3 + SI= 1 + SILI= 0 + CSI= 1 + VIS= all + +%%%%%%% Telescope 2 DSSD 4 %%%%%%% +M2Telescope + X128_Y128= -114.49 -10.46 140.4 + X128_Y1= -103.09 -102.67 111.64 + X1_Y1= -12.56 -102.58 147.47 + X1_Y128= -23.97 -10.38 176.22 + SI= 1 + SILI= 0 + CSI= 1 + VIS= all + +%%%%%%% Telescope 3 DSSD 7 %%%%%%% +M2Telescope + X128_Y128= 13.11 -103.21 147.01 + X128_Y1= 103.38 -103.24 110.82 + X1_Y1= 114.96 -10.99 139.34 + X1_Y128= 24.66 -10.9 175.56 + SI= 1 + SILI= 0 + CSI= 1 + VIS= all + +%%%%%%% Telescope 4 DSSD 11 %%%%%%% +M2Telescope + X128_Y128= 115.09 11.03 140.54 + X128_Y1= 103.67 103.32 111.26 + X1_Y1= 13.52 103.53 147.05 + X1_Y128= 24.94 11.24 176.34 + SI= 1 + SILI= 0 + CSI= 1 + VIS= all + +% %%%%%%% Telescope 5 DSSD 2 %%%%%%% +% M2Telescope +% X128_Y128= -48.51 47.21 860.3 +% X128_Y1= -48.84 -50.07 860.45 +% X1_Y1= 48.45 -50.36 860.26 +% X1_Y128= 48.81 46.91 860.11 +% SI= 1 +% SILI= 0 +% CSI= 1 +% VIS= all + + + diff --git a/Projects/MultiParticleRES/Inputs/ExampleSequential15F.reaction b/Projects/MultiParticleRES/Inputs/ExampleSequential15F.reaction new file mode 100644 index 0000000000000000000000000000000000000000..de9c8857e273013f85d3f491dae93affd010a83e --- /dev/null +++ b/Projects/MultiParticleRES/Inputs/ExampleSequential15F.reaction @@ -0,0 +1,38 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Beam + Particle= 14O + Energy= 103.885 MeV + %Energy= 93.8 MeV + SigmaEnergy= 0.005 MeV + SigmaThetaX= 0. deg + SigmaPhiY= 0. deg + %SigmaX= 7 mm + %SigmaY= 7 mm + SigmaX= 8 mm + SigmaY= 8 mm + MeanThetaX= 0. deg + MeanPhiY= 0. deg + MeanX= -4. mm + MeanY= -1. mm + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +ThreeBody + Type= sequential + Beam= 14O + Target= 1H + CompoundNucleusEnergy= 6.3 MeV + CompoundNucleusStateWidth= 0.02 MeV + IntermediaryNucleus= 14O + IntermediaryState= 0 MeV + IntermediaryStateWidth= 0.01 MeV + Light1= 1H + Heavy= 13N + Light2= 1H + ExcitationEnergyHeavy= 0. MeV + ShootLight1= 1 + ShootLight2= 1 + ShootHeavy= 1 + UserEnergyCS= 1 + EnergyCSPath= $NPTOOL/Projects/MultiParticleRES/Inputs/BW.root + EnergyCSName= BW diff --git a/Projects/MultiParticleRES/Inputs/simu.mac b/Projects/MultiParticleRES/Inputs/simu.mac new file mode 100644 index 0000000000000000000000000000000000000000..add2e059e4e5a5806132ca1713ec1c5a75dd1a49 --- /dev/null +++ b/Projects/MultiParticleRES/Inputs/simu.mac @@ -0,0 +1,2 @@ +/run/beamOn 100000 + diff --git a/Projects/MultiParticleRES/simu.sh b/Projects/MultiParticleRES/simu.sh new file mode 100755 index 0000000000000000000000000000000000000000..b85e7e901680feaf0991af32d5e4456308ab9ea1 --- /dev/null +++ b/Projects/MultiParticleRES/simu.sh @@ -0,0 +1,2 @@ +npsimulation -D Inputs/ExampleSequential15F.detector -E Inputs/ExampleSequential15F.reaction -B Inputs/simu.mac -O testMultiParticuleRES + diff --git a/Projects/MultiParticleRES/utilities/BW.root b/Projects/MultiParticleRES/utilities/BW.root new file mode 100644 index 0000000000000000000000000000000000000000..2838ace698508d1f053ff30ce8ec6fab773189ca Binary files /dev/null and b/Projects/MultiParticleRES/utilities/BW.root differ diff --git a/Projects/MultiParticleRES/utilities/ThreeBodyCS.cc b/Projects/MultiParticleRES/utilities/ThreeBodyCS.cc new file mode 100644 index 0000000000000000000000000000000000000000..5674aae83cd7c69573a1d313117b4f4acec1ed56 --- /dev/null +++ b/Projects/MultiParticleRES/utilities/ThreeBodyCS.cc @@ -0,0 +1,267 @@ +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: V. Alcindor mail: valcindor@ikp.tu-darmstadt.de * + * * + * Creation Date : July 2022 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * This files is for the generation of 15F Breit Wigner shape in the case * + * of the sequential 2p emission 14O+p -> 15F -> 14O(1-) + p -> 13N + p * + * * + *---------------------------------------------------------------------------* + * Comment: * + * * + * * + * * + *****************************************************************************/ +#include <gsl/gsl_integration.h> +#include <gsl/gsl_sf_coulomb.h> + +// dirty way of avoiding a header or input file... +namespace input_conditions { +// Incoming beam, here 14O +NPL::Particle Beam(8, 14); +// Target particle, here protons +NPL::Particle Target(1, 1); +// Intermediate state in the sequential emission (14O(1-), Ex=5.173 MeV) +NPL::Particle Intermediate(8, 14); +double IntermediateState = 5.173; +// Final particle in the exit channel, here 13N +NPL::Particle Final(7, 13); +} // namespace input_conditions + +using namespace input_conditions; + +double CoulombFunction(std::string type, double E, double R, double mu, + Int_t Z1, Int_t Z2, double L, Int_t k = 0) { + gsl_sf_result F_res; + gsl_sf_result Fp_res; + gsl_sf_result G_res; + gsl_sf_result Gp_res; + double expF; + double expG; + double eta, rho; + eta = 0.15748 * Z1 * Z2 * sqrt(mu / E); + rho = 0.218735 * sqrt(mu * E) * R; + gsl_sf_coulomb_wave_FG_e(eta, rho, L, k, &F_res, &Fp_res, &G_res, &Gp_res, + &expF, &expG); + if (type == "F") + return F_res.val * exp(expF); + else if (type == "G") + return G_res.val * exp(expG); + else + return 1; +} + +double rho(double* E, double* par) { + double R = par[0]; + double mu_uma = par[1]; + + return R * .218735 * sqrt(mu_uma * E[0]); +} // computation of the reduced variable for the penetrability + +double P_l(double* E, double* par) { + + gsl_sf_result F_res; + gsl_sf_result Fp_res; + gsl_sf_result G_res; + gsl_sf_result Gp_res; + + double R = par[0]; + double mu_uma = par[1]; + double Z1 = par[2]; + double Z2 = par[3]; + double L = par[4]; + double par_P[2] = {par[0], par[1]}; + double coulF = CoulombFunction("F", E[0], R, mu_uma, Z1, Z2, L, 0); + double coulG = CoulombFunction("G", E[0], R, mu_uma, Z1, Z2, L, 0); + double Penetrability = rho(E, par_P) / (pow(coulF, 2.) + pow(coulG, 2.)); + + return Penetrability; +} // computation of the penetrability cf Abrahamovitz & Stegun Ch14 et C. + +double f_theoretical_proton_width(double* x, double* par) { + double Er = par[0]; + double l = par[1]; + double z = par[2]; + double a = par[3]; + double Z = par[4]; + double A = par[5]; + double E = x[0]; + + double r0 = 1.2; // fm + double R = r0 * (pow(A, 1. / 3.) + pow(a, 1. / 3.)); // fm + + double mBeam_uma = Beam.GetA(); + +Beam.GetMassExcess() / 1000.; + double mTarget_uma = Target.GetA(); + +Target.GetMassExcess() / 1000.; + double mCN_uma = (mBeam_uma * mTarget_uma) / (mBeam_uma + mTarget_uma); + + double P_par[5] = {R, mCN_uma, z, Z, l}; + double P = P_l(&E, P_par); + + double h_bar_c = 197.3; // MeV.fm + double max_proton_width + = 3. * pow(h_bar_c, 2.) / (((A * a) / (A + a) * 931.5) * pow(R, 2.)); + + double proton_width = max_proton_width * P; + + if (E > 3.339 && E < 3.99) { + double x1 = 3.339; + double x2 = 3.99; + P = P_l(&x1, P_par); + double y1 = max_proton_width * P; + P = P_l(&x2, P_par); + double y2 = max_proton_width * P; + + return (y1 - y2) / (x1 - x2) * E + (y2 - x2 * (y1 - y2) / (x1 - x2)); + } // trying to correct GSLCoulomb problem in this region + + return proton_width; +} // Computation of proton width using COULOMB function from GSL + +double f_proton_width(double* x, double* par) { + double Er = par[0]; + double res_width = par[1]; + double l = par[2]; + double z = par[3]; + double a = par[4]; + double Z = par[5]; + double A = par[6]; + double E = x[0]; + + double r0 = 1.2; // fm + double R = r0 * (pow(A, 1. / 3.) + pow(a, 1. / 3.)); // fm + + double mBeam_uma = Beam.GetA() + Beam.GetMassExcess() / 1000.; + double mTarget_uma = Target.GetA() + Target.GetMassExcess() / 1000.; + double mCN_uma = (mBeam_uma * mTarget_uma) / (mBeam_uma + mTarget_uma); + + double P_par[5] = {R, mCN_uma, z, Z, l}; + double P = P_l(&E, P_par); + double Pr = P_l(&Er, P_par); + + double proton_width = (res_width * P / Pr); + + if (E > 3.339 && E < 3.99) { + double x1 = 3.339; + double x2 = 3.99; + P = P_l(&x1, P_par); + double y1 = (res_width * P / Pr); + P = P_l(&x2, P_par); + double y2 = (res_width * P / Pr); + + return (y1 - y2) / (x1 - x2) * E + (y2 - x2 * (y1 - y2) / (x1 - x2)); + } // trying to correct GSLCoulomb problem in this region for 15F + + return proton_width; +} // Computation of proton width using COULOMB function from GSL + +double f_double_sequential_proton_cross_section(double* x, double* par) { + double E = x[0]; // MeV + if (E < 0.) { + std::cerr << "ENERGY IS NEGATIVE" << std::endl; + return 1.; + } else { + + double Er = par[0]; // MeV + double res_width = par[1]; // MeV + + double J1 = par[2]; + double J2 = par[3]; + double J = J1 + J2; + double w = (2. * J + 1.) / ((2. * J1 + 1.) * (2. * J2 + 1.)); + + double li = par[4]; + double lf = par[5]; + + double p = std::sqrt(2. * 14. / 15. * E); // MeV/c + double h = 4.14e-15 * 1.0e-6; // MeV.s + double lambda = (h / p); + + double EFinal = Beam.GetBindingEnergy() - Final.GetBindingEnergy(); + + // Width of the entrance channel + double x_Gp1[1] = {E}; + double par_Gp1[7] = {Er, + res_width, + li, + (double)Target.GetZ(), + (double)Target.GetA(), + (double)Beam.GetZ(), + (double)Beam.GetA()}; + double Gp1 = f_proton_width(x_Gp1, par_Gp1); + + // Width of the direct 2p channel + double Gp2 = 0.; + if (E - EFinal > 0.) { + double x_Gp2[1] = {E - EFinal}; + // 2*Target because I considered that 2p = 1H + 1H, so Z=2, A=2 + double par_Gp2[6] = {Er - EFinal, + lf, + 2 * (double)Target.GetZ(), + 2 * (double)Target.GetA(), + (double)Final.GetZ(), + (double)Final.GetA()}; + Gp2 = f_theoretical_proton_width(x_Gp2, par_Gp2); + } + + // Width of the sequential 2p channel + double EIntermediate = Intermediate.GetExcitationEnergy(); + Intermediate.SetExcitationEnergy(IntermediateState); + double Gp3 = 1.e-3; + if (E - EIntermediate < 0.) { + Gp3 = 0.; + } else if (E - EIntermediate > 0.) { + double x_Gp3[1] = {E - EIntermediate}; + double par_Gp3[6] = {Er - EIntermediate, lf, + (double)Target.GetZ(), (double)Target.GetA(), + (double)Beam.GetZ(), (double)Beam.GetA()}; + Gp3 = f_theoretical_proton_width(x_Gp3, par_Gp3); + } + + double Gt = Gp1 + Gp2 + Gp3; + + double mBeam_uma = Beam.GetA() + Beam.GetMassExcess() / 1000.; + double mTarget_uma = Target.GetA() + Target.GetMassExcess() / 1000.; + double mCN_uma = (mBeam_uma * mTarget_uma) / (mBeam_uma + mTarget_uma); + + double CN_formation = 0.657 / (mCN_uma * E) * w * (Gp1 * Gt) + / (pow((E - Er), 2.) + 1. / 4. * pow(Gt, 2.)); + double CN_decay = Gp3 / Gt; + double BW_cross_section = CN_formation * CN_decay; + return BW_cross_section; + } +} // Breit-Wigner cross section of the reaction 14O(p,p)14O(p)13N + +// "Main of thsd +void ThreeBodyCS(double Er = 6.3, double res_width = 0.02, int Npx = 1000) { + + // Generating BW cross section for the 15F sequential emission, here 14O is + // taken as the reference, E(14Og.s.) = 0 MeV, as a consequence, the ground + // state of 13N is 4.628 MeV. + + double J1 = 0.; + double J2 = 5. / 2.; + double li = 3.; + double lf = 2.; + + TF1* g_double_cross_section + = new TF1("g_double_sequential_cross_section", + f_double_sequential_proton_cross_section, 0.1, 10.1, 6, 1); + + g_double_cross_section->SetParameters(Er, res_width, J1, J2, li, lf); + g_double_cross_section->SetNpx(Npx); + g_double_cross_section->Draw(); + g_double_cross_section->SetName("BW"); + TFile* fout = new TFile("BW.root", "recreate"); + g_double_cross_section->Write(); +} diff --git a/Projects/MultiParticleRES/utilities/rootlogon.C b/Projects/MultiParticleRES/utilities/rootlogon.C new file mode 100644 index 0000000000000000000000000000000000000000..9f03d73f93c0f366dcbc03c47ac09054622d9b99 --- /dev/null +++ b/Projects/MultiParticleRES/utilities/rootlogon.C @@ -0,0 +1 @@ +{ int status = gSystem->Load("libgsl"); }