From a57f1662c67b58e58853c8dfaad26f2ff3afdbc3 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sat, 6 Jul 2024 00:21:32 +0300 Subject: [PATCH 01/78] add Jacobians --- src/Framework/Utils/KineUtils.cxx | 195 +++++++++++++++++++++- src/Physics/Common/PrimaryLeptonUtils.cxx | 43 ++++- 2 files changed, 226 insertions(+), 12 deletions(-) diff --git a/src/Framework/Utils/KineUtils.cxx b/src/Framework/Utils/KineUtils.cxx index 5b59171340..0f9400cbe3 100644 --- a/src/Framework/Utils/KineUtils.cxx +++ b/src/Framework/Utils/KineUtils.cxx @@ -154,8 +154,8 @@ double genie::utils::kinematics::Jacobian( << KinePhaseSpace::AsString(fromps) << " --> " << KinePhaseSpace::AsString(tops); - double J=0; - bool forward; + double J = 0; + bool forward = true; const Kinematics & kine = i->Kine(); // cover the simple case @@ -321,14 +321,201 @@ double genie::utils::kinematics::Jacobian( // (it will be inverted below for the inverse transformation) J = W / ( 2. * pv * pl * M ); } + + else if ( TransformMatched(fromps,tops, kPSyfEx, kPSQELEvGen, forward) ) + { + //TLorentzVector neutrino(*i->InitStatePtr()->GetProbeP4(kRfLab)); + //TLorentzVector nucleon(*i->InitStatePtr()->GetTgtP4(kRfLab)); + TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); + TLorentzVector* pi4 = i->InitStatePtr()->TgtPtr()->HitNucP4Ptr(); + //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + //std::cout << std::setprecision(18) << "Ek = " << ki4->Energy() << ", kx = " << ki4->Px() << ", ky = " << ki4->Py() << ", kz = " << ki4->Pz() << "\n"; + //std::cout << std::setprecision(18) << "Ep = " << pi4->Energy() << ", px = " << pi4->Px() << ", py = " << pi4->Py() << ", pz = " << pi4->Pz() << "\n"; + TLorentzVector totMom = *ki4 + *pi4; + TVector3 beta = totMom.BoostVector(); + TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); + kf4.Boost(-beta); + + //TVector3 lepton3Mom = lepton.Vect(); + TVector3 zvec(0., 0., 1.); + TVector3 rot = ( zvec.Cross(beta) ).Unit(); + double angle = beta.Angle( zvec ); + // Handle the edge case where beta is along z, so the + // cross product above vanishes + if ( beta.Perp() == 0. && beta.Z() < 0. ) + { + rot = TVector3(0., 1., 0.); + angle = genie::constants::kPi; + } + + if ( rot.Mag() > 0 ) + { + kf4.Rotate(angle, -rot); + } + + double kf4_mag = kf4.Vect().Mag(); + double theta_star = kf4.Theta(); + double phi_star = kf4.Phi(); + + //std::cout << std::setprecision(18) << "El = " << kf4.Energy() << ", kf4_mag = " << kf4_mag << "\n"; + + TLorentzVector kf4_dtheta(kf4_mag*TMath::Cos(phi_star)*TMath::Cos(theta_star), kf4_mag*TMath::Sin(phi_star)*TMath::Cos(theta_star), -kf4_mag*TMath::Sin(theta_star), 0); + TLorentzVector kf4_dphi( -kf4_mag*TMath::Sin(phi_star)*TMath::Sin(theta_star), kf4_mag*TMath::Cos(phi_star)*TMath::Sin(theta_star), 0, 0); + if ( theta_star <= 0 || theta_star >= genie::constants::kPi) + { + kf4_dphi = TLorentzVector( -kf4_mag*TMath::Sin(phi_star), kf4_mag*TMath::Cos(phi_star), 0, 0 ); + } + // to LAB frame + if ( rot.Mag() > 0 ) + { + kf4_dtheta.Rotate(angle, rot); + kf4_dphi.Rotate(angle, rot); + } + kf4_dtheta.Boost(beta); + kf4_dphi.Boost(beta); + kf4 = i->KinePtr()->FSLeptonP4(); + + double dQ2dtheta = 2*((*ki4)*kf4_dtheta); + double dQ2dphi = 2*((*ki4)*kf4_dphi); + + // to hit nucleon rest frame + TVector3 beta1 = pi4->BoostVector(); + kf4_dtheta.Boost(-beta1); + kf4_dphi.Boost(-beta1); + kf4.Boost(-beta1); + + ki4->Boost(-beta1); + TVector3 ki3 = ki4->Vect(); + TVector3 rot1 = ( ki3.Cross(zvec) ).Unit(); + double angle1 = zvec.Angle( ki3 ); + // Handle the edge case where beta is along z, so the + // cross product above vanishes + if ( ki3.Perp() == 0. && ki3.Z() < 0. ) + { + rot1 = TVector3(0., 1., 0.); + angle1 = genie::constants::kPi; + } + if ( rot1.Mag() > 0 ) + { + kf4_dtheta.Rotate(angle1, rot1); + kf4_dphi.Rotate(angle1, rot1); + kf4.Rotate(angle1, rot1); + } + double t = 1/( kf4.Px()*kf4.Px() + kf4.Py()*kf4.Py() ); + double dphi0dtheta = t*(kf4_dtheta.Py()*kf4.Px() - kf4_dtheta.Px()*kf4.Py()); + double dphi0dphi = t*(kf4_dphi.Py()*kf4.Px() - kf4_dphi.Px()*kf4.Py()); + + double Q2 = i->Kine().GetKV( kKVQ2 ); + // mass of initial nucleon + double Mi = i->InitStatePtr()->TgtPtr()->HitNucMass(); + // Look up the (on-shell) mass of the final nucleon + TDatabasePDG *tb = TDatabasePDG::Instance(); + double Mf = tb->GetParticle( i->RecoilNucleonPdg() )->Mass(); + // Mandelstam s for the probe/hit nucleon system + double s = TMath::Sq( i->InitState().CMEnergy() ); + double dydQ2 = (s - Mi*Mi)/TMath::Sq(s - Mf*Mf - Q2); + if ( theta_star <= 0 || theta_star >= genie::constants::kPi) + J = 1; + else + J = 1/TMath::Sin(theta_star); + + J = TMath::Abs(J*dydQ2*(dQ2dtheta*dphi0dphi - dQ2dphi*dphi0dtheta)/2/genie::constants::kPi); + + + + + //std::cout << std::setprecision(18) << "Q^2 = " << Q2 << "\n"; + //std::cout << std::setprecision(18) << "Ek' = " << kf4.Energy() << ", k'x = " << kf4.Px() << ", k'y = " << kf4.Py() << ", k'z = " << kf4.Pz() << ", phi0 = " << kf4.Phi() << "\n"; + //std::cout << std::setprecision(18) << "Computed values: theta = " << theta_star << ", phi = " << phi_star << "\n"; + //std::cout << std::setprecision(18) << "Computed values: dQ2dcostheta = " << -dQ2dtheta/TMath::Sin(theta_star) << ", dQ2dphi = " << dQ2dphi << "\n"; + //std::cout << std::setprecision(18) << "Computed values: dphi0dtheta = " << dphi0dtheta << ", dphi0dphi = " << dphi0dphi << "\n"; + //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + //std::cout << "Selected values: theta = " << TMath::ACos(costheta) << ", phi = " << phi << "\n"; + //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + delete ki4; + } + + else if ( TransformMatched(fromps,tops, kPSyfEx, kPSWQ2fE, forward) ) + { + double Q2 = i->Kine().GetKV( kKVQ2 ); + // mass of initial nucleon + double Mi = i->InitStatePtr()->TgtPtr()->HitNucMass(); + // Look up the (on-shell) mass of the final nucleon + TDatabasePDG *tb = TDatabasePDG::Instance(); + double Mf = tb->GetParticle( i->RecoilNucleonPdg() )->Mass(); + // Mandelstam s for the probe/hit nucleon system + double s = TMath::Sq( i->InitState().CMEnergy() ); + double dydQ2 = (s - Mi*Mi)/TMath::Sq(s - Mf*Mf - Q2); + J = dydQ2; + } + + else if ( TransformMatched(fromps,tops, kPSyfEx, kPSQ2vfE, forward) ) + { + TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); + TLorentzVector* pi4 = i->InitStatePtr()->TgtPtr()->HitNucP4Ptr(); + TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); + + // to hit nucleon rest frame + TVector3 beta = pi4->BoostVector(); + pi4->Boost(-beta); + ki4->Boost(-beta); + kf4.Boost(-beta); + + TVector3 ki3 = ki4->Vect(); + TVector3 zvec(0., 0., 1.); + TVector3 rot = ( ki3.Cross(zvec) ).Unit(); + double angle = zvec.Angle( ki3 ); + // Handle the edge case where beta is along z, so the + // cross product above vanishes + if ( ki3.Perp() == 0. && ki3.Z() < 0. ) + { + rot = TVector3(0., 1., 0.); + angle = genie::constants::kPi; + } + if ( rot.Mag() > 0 ) + { + ki4->Rotate(angle, rot); + kf4.Rotate(angle, rot); + } + + double kf4_mag = kf4.Vect().Mag(); + double theta_star = kf4.Theta(); + double phi_star = kf4.Phi(); + + TLorentzVector kf4_dphi( -kf4_mag*TMath::Sin(phi_star)*TMath::Sin(theta_star), kf4_mag*TMath::Cos(phi_star)*TMath::Sin(theta_star), 0, 0); + // to LAB frame + if ( rot.Mag() > 0 ) + { + kf4_dphi.Rotate(angle, -rot); + } + + kf4_dphi.Boost(beta); + double Q2 = i->Kine().GetKV( kKVQ2 ); + // mass of initial nucleon + double Mi = i->InitStatePtr()->TgtPtr()->HitNucMass(); + // Look up the (on-shell) mass of the final nucleon + TDatabasePDG *tb = TDatabasePDG::Instance(); + double Mf = tb->GetParticle( i->RecoilNucleonPdg() )->Mass(); + // Mandelstam s for the probe/hit nucleon system + double s = TMath::Sq( i->InitState().CMEnergy() ); + double dydQ2 = (s - Mi*Mi)/TMath::Sq(s - Mf*Mf - Q2); + J = TMath::Abs(dydQ2/kf4_dphi.Energy()/2/genie::constants::kPi); + + delete ki4; + } else { std::ostringstream msg; msg << "Can not compute Jacobian for transforming: " << KinePhaseSpace::AsString(fromps) << " --> " << KinePhaseSpace::AsString(tops); - SLOG("KineLimits", pFATAL) << "*** " << msg.str(); - throw genie::exceptions::InteractionException(msg.str()); + SLOG("KineLimits", pNOTICE) << msg.str() + << ". Set Jacbian equalto zero!"; + //SLOG("KineLimits", pFATAL) << "*** " << msg.str(); + //throw genie::exceptions::InteractionException(msg.str()); //exit(1); } diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 25ad55800b..360f9c54a8 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -15,6 +15,9 @@ #include "Framework/GHEP/GHepParticle.h" #include "Framework/Messenger/Messenger.h" #include "Framework/ParticleData/PDGUtils.h" +#include "Framework/EventGen/EventGeneratorI.h" +#include "Framework/EventGen/RunningThreadInfo.h" +#include "Framework/EventGen/XSecAlgorithmI.h" using namespace genie; using namespace genie::utils; @@ -26,11 +29,6 @@ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) // accessible for generators that use a more unified approach (e.g., // QELEventGenerator and MECGenerator). -- S. Gardiner -// Set the final state lepton polarization. A mass-less lepton would be fully -// polarized. This would be exact for neutrinos and a very good approximation -// for electrons for the energies this generator is going to be used. This is -// not the case for muons and, mainly, for taus. I need to refine this later. -// How? See Kuzmin, Lyubushkin and Naumov, hep-ph/0312107 // get the final state primary lepton GHepParticle * fsl = ev->FinalStatePrimaryLepton(); @@ -39,15 +37,39 @@ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) << "Final state lepton not set yet! \n" << *ev; return; } - + //-- Get the interaction + Interaction * interaction = ev->Summary(); + const ProcessInfo & proc_info = interaction->ProcInfo(); + // Polarization of final charged lepton according to Kuzmin, Lyubushkin and Naumov, hep-ph/0312107 + if ( proc_info.IsWeakCC() ) + { + //-- Access cross section algorithm for running thread + RunningThreadInfo * rtinfo = RunningThreadInfo::Instance(); + const EventGeneratorI * evg = rtinfo->RunningThread(); + const XSecAlgorithmI * xsec_alg = evg->CrossSectionAlg(); + interaction->SetBit(kISkipProcessChk); + Kinematics * kine = interaction->KinePtr(); + kine->UseSelectedKinematics(); + if ( proc_info.IsQuasiElastic() ) + { + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + double xsec = xsec_alg->XSec(interaction, kPSyfEx); + std::cout << "xsec = " << xsec << "\n"; + xsec = xsec_alg->XSec(interaction, kPSQELEvGen); + std::cout << "xsec = " << xsec << "\n"; + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << std::endl; + } + return; + } + // Get (px,py,pz) @ LAB TVector3 plab( fsl->Px(), fsl->Py(), fsl->Pz() ); // In the limit m/E->0: leptons are left-handed and their anti-particles // are right-handed int pdgc = fsl->Pdg(); - if ( pdg::IsNeutrino(pdgc) || pdg::IsElectron(pdgc) || - pdg::IsMuon(pdgc) || pdg::IsTau(pdgc) ) + if ( pdg::IsNeutrino(pdgc) || pdg::IsElectron(pdgc) || + pdg::IsMuon(pdgc) || pdg::IsTau(pdgc) ) { plab *= -1; // left-handed } @@ -62,4 +84,9 @@ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) << "Polarization (rad): Polar = " << fsl->PolzPolarAngle() << ", Azimuthal = " << fsl->PolzAzimuthAngle(); } + + // reset trust bits + interaction->ResetBit(kISkipProcessChk); + interaction->ResetBit(kISkipKinematicChk); + } From 24bae0db07a8e3d529e92653662aa4fba717414c Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sat, 6 Jul 2024 20:07:24 +0300 Subject: [PATCH 02/78] add new phase space kPSyphi0fEx, a Jacobian kPSyphi0fEx->kPSQ2vfE --- src/Framework/Conventions/KinePhaseSpace.h | 5 ++++- src/Framework/Utils/KineUtils.cxx | 14 ++++++++------ src/Physics/Common/PrimaryLeptonUtils.cxx | 8 ++++---- .../EventGen/QELEventGeneratorSM.cxx | 2 ++ .../Resonance/EventGen/SPPEventGenerator.cxx | 17 +++++++++-------- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/Framework/Conventions/KinePhaseSpace.h b/src/Framework/Conventions/KinePhaseSpace.h index a51c72addb..6d7a0813b2 100644 --- a/src/Framework/Conventions/KinePhaseSpace.h +++ b/src/Framework/Conventions/KinePhaseSpace.h @@ -75,7 +75,9 @@ typedef enum EKinePhaseSpace { kPSn1n2n3fE, kPSWQ2ctpphipfE, kPSWQ2ctpfE, - kPSQ2vpfE + kPSQ2vpfE, + kPSyphi0fEx // Phase space dimension to set lepton polarization properly + // for cases when an output of XSecModel depends on phase space dim. } KinePhaseSpace_t; class KinePhaseSpace @@ -137,6 +139,7 @@ class KinePhaseSpace case(kPSn1n2n3fE) : return "<{n1,n2,n3}|E>"; break; case(kPSWQ2ctpphipfE): return "<{W, Q2, cost(theta_pion), phi_pion}|E>"; break; case(kPSWQ2ctpfE) : return "<{W, Q2, cost(theta_pion)}|E>"; break; + case(kPSyphi0fEx) : return "<{y, phi0}|E,x>"; break; } return "** Undefined kinematic phase space **"; } diff --git a/src/Framework/Utils/KineUtils.cxx b/src/Framework/Utils/KineUtils.cxx index 0f9400cbe3..172db0e115 100644 --- a/src/Framework/Utils/KineUtils.cxx +++ b/src/Framework/Utils/KineUtils.cxx @@ -322,7 +322,7 @@ double genie::utils::kinematics::Jacobian( J = W / ( 2. * pv * pl * M ); } - else if ( TransformMatched(fromps,tops, kPSyfEx, kPSQELEvGen, forward) ) + else if ( TransformMatched(fromps,tops, kPSyphi0fEx, kPSQELEvGen, forward) ) { //TLorentzVector neutrino(*i->InitStatePtr()->GetProbeP4(kRfLab)); //TLorentzVector nucleon(*i->InitStatePtr()->GetTgtP4(kRfLab)); @@ -419,6 +419,7 @@ double genie::utils::kinematics::Jacobian( else J = 1/TMath::Sin(theta_star); + // It is not entirely correct to divide by 2 pi, but solely to simplify the code it is better to do it here (Igor Kakorin) J = TMath::Abs(J*dydQ2*(dQ2dtheta*dphi0dphi - dQ2dphi*dphi0dtheta)/2/genie::constants::kPi); @@ -438,7 +439,7 @@ double genie::utils::kinematics::Jacobian( delete ki4; } - else if ( TransformMatched(fromps,tops, kPSyfEx, kPSWQ2fE, forward) ) + else if ( TransformMatched(fromps,tops, kPSyphi0fEx, kPSQ2fE, forward) ) { double Q2 = i->Kine().GetKV( kKVQ2 ); // mass of initial nucleon @@ -452,7 +453,7 @@ double genie::utils::kinematics::Jacobian( J = dydQ2; } - else if ( TransformMatched(fromps,tops, kPSyfEx, kPSQ2vfE, forward) ) + else if ( TransformMatched(fromps,tops, kPSyphi0fEx, kPSQ2vfE, forward) ) { TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); TLorentzVector* pi4 = i->InitStatePtr()->TgtPtr()->HitNucP4Ptr(); @@ -482,10 +483,10 @@ double genie::utils::kinematics::Jacobian( } double kf4_mag = kf4.Vect().Mag(); - double theta_star = kf4.Theta(); - double phi_star = kf4.Phi(); + double theta0 = kf4.Theta(); + double phi0 = kf4.Phi(); - TLorentzVector kf4_dphi( -kf4_mag*TMath::Sin(phi_star)*TMath::Sin(theta_star), kf4_mag*TMath::Cos(phi_star)*TMath::Sin(theta_star), 0, 0); + TLorentzVector kf4_dphi( -kf4_mag*TMath::Sin(phi0)*TMath::Sin(theta0), kf4_mag*TMath::Cos(phi0)*TMath::Sin(theta0), 0, 0); // to LAB frame if ( rot.Mag() > 0 ) { @@ -502,6 +503,7 @@ double genie::utils::kinematics::Jacobian( // Mandelstam s for the probe/hit nucleon system double s = TMath::Sq( i->InitState().CMEnergy() ); double dydQ2 = (s - Mi*Mi)/TMath::Sq(s - Mf*Mf - Q2); + // It is not entirely correct to divide by 2 pi, but solely to simplify the code it is better to do it here (Igor Kakorin) J = TMath::Abs(dydQ2/kf4_dphi.Energy()/2/genie::constants::kPi); delete ki4; diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 360f9c54a8..5a2ee94480 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -53,10 +53,10 @@ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) if ( proc_info.IsQuasiElastic() ) { std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - double xsec = xsec_alg->XSec(interaction, kPSyfEx); - std::cout << "xsec = " << xsec << "\n"; - xsec = xsec_alg->XSec(interaction, kPSQELEvGen); - std::cout << "xsec = " << xsec << "\n"; + double xsec = xsec_alg->XSec(interaction, kPSyphi0fEx); + std::cout << "!!!xsec = " << xsec << "\n"; + //xsec = xsec_alg->XSec(interaction, kPSQELEvGen); + //std::cout << "xsec = " << xsec << "\n"; std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << std::endl; } return; diff --git a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx index 072f198075..3638a58097 100644 --- a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx +++ b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx @@ -286,6 +286,8 @@ void QELEventGeneratorSM::ProcessEventRecord(GHepRecord * evrec) const kinematics::WQ2toXY(E,M,W,Q2,x,y); // lock selected kinematics & clear running values + interaction->KinePtr()->SetFSLeptonP4(outLeptonMom); + interaction->KinePtr()->SetHadSystP4(outNucleonMom); interaction->KinePtr()->SetQ2(Q2, true); interaction->KinePtr()->SetW (W, true); interaction->KinePtr()->Setx (x, true); diff --git a/src/Physics/Resonance/EventGen/SPPEventGenerator.cxx b/src/Physics/Resonance/EventGen/SPPEventGenerator.cxx index 9bcf8d991d..a7a455cbbe 100644 --- a/src/Physics/Resonance/EventGen/SPPEventGenerator.cxx +++ b/src/Physics/Resonance/EventGen/SPPEventGenerator.cxx @@ -209,14 +209,6 @@ void SPPEventGenerator::ProcessEventRecord(GHepRecord * evrec) const // set the cross section for the selected kinematics evrec->SetDiffXSec(xsec,kPSWQ2ctpphipfE); - // lock selected kinematics & clear running values - interaction->KinePtr()->SetQ2(Q2, true); - interaction->KinePtr()->SetW (W, true); - interaction->KinePtr()->Setx (x, true); - interaction->KinePtr()->Sety (y, true); - interaction->KinePtr()->ClearRunningValues(); - - double W2 = W*W; // Kinematical values of all participating particles in the isobaric frame double Enu_isb = (Ev*M - (ml2 + Q2)/2)/W; @@ -262,6 +254,15 @@ void SPPEventGenerator::ProcessEventRecord(GHepRecord * evrec) const tgt->SetHitNucP4(p1_copy); + + // lock selected kinematics & clear running values + interaction->KinePtr()->SetFSLeptonP4(k2_isb); + interaction->KinePtr()->SetHadSystP4(p2_isb); + interaction->KinePtr()->SetQ2(Q2, true); + interaction->KinePtr()->SetW (W, true); + interaction->KinePtr()->Setx (x, true); + interaction->KinePtr()->Sety (y, true); + interaction->KinePtr()->ClearRunningValues(); TLorentzVector x4l(*(evrec->Probe())->X4()); // add final lepton From 232fb38077827d4ab76a45c696266748ca4fcd1f Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 7 Jul 2024 21:20:15 +0300 Subject: [PATCH 03/78] add two Jacobian kPSxyfE->kPSTlctl & kPSQ2vfE->kPSxyfE --- src/Framework/Utils/KineUtils.cxx | 91 +++++-------------- src/Physics/Common/PrimaryLeptonUtils.cxx | 25 +++-- .../Multinucleon/EventGen/MECGenerator.cxx | 6 ++ .../XSection/NievesSimoVacasMECPXSec2016.cxx | 14 +-- .../Multinucleon/XSection/SuSAv2MECPXSec.cxx | 8 +- .../EventGen/QELEventGeneratorSM.cxx | 3 + .../EventGen/QELEventGeneratorSuSA.cxx | 5 + .../QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 13 ++- 8 files changed, 67 insertions(+), 98 deletions(-) diff --git a/src/Framework/Utils/KineUtils.cxx b/src/Framework/Utils/KineUtils.cxx index 172db0e115..7c511cc379 100644 --- a/src/Framework/Utils/KineUtils.cxx +++ b/src/Framework/Utils/KineUtils.cxx @@ -324,19 +324,13 @@ double genie::utils::kinematics::Jacobian( else if ( TransformMatched(fromps,tops, kPSyphi0fEx, kPSQELEvGen, forward) ) { - //TLorentzVector neutrino(*i->InitStatePtr()->GetProbeP4(kRfLab)); - //TLorentzVector nucleon(*i->InitStatePtr()->GetTgtP4(kRfLab)); TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); TLorentzVector* pi4 = i->InitStatePtr()->TgtPtr()->HitNucP4Ptr(); - //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - //std::cout << std::setprecision(18) << "Ek = " << ki4->Energy() << ", kx = " << ki4->Px() << ", ky = " << ki4->Py() << ", kz = " << ki4->Pz() << "\n"; - //std::cout << std::setprecision(18) << "Ep = " << pi4->Energy() << ", px = " << pi4->Px() << ", py = " << pi4->Py() << ", pz = " << pi4->Pz() << "\n"; TLorentzVector totMom = *ki4 + *pi4; TVector3 beta = totMom.BoostVector(); TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); kf4.Boost(-beta); - //TVector3 lepton3Mom = lepton.Vect(); TVector3 zvec(0., 0., 1.); TVector3 rot = ( zvec.Cross(beta) ).Unit(); double angle = beta.Angle( zvec ); @@ -357,8 +351,6 @@ double genie::utils::kinematics::Jacobian( double theta_star = kf4.Theta(); double phi_star = kf4.Phi(); - //std::cout << std::setprecision(18) << "El = " << kf4.Energy() << ", kf4_mag = " << kf4_mag << "\n"; - TLorentzVector kf4_dtheta(kf4_mag*TMath::Cos(phi_star)*TMath::Cos(theta_star), kf4_mag*TMath::Sin(phi_star)*TMath::Cos(theta_star), -kf4_mag*TMath::Sin(theta_star), 0); TLorentzVector kf4_dphi( -kf4_mag*TMath::Sin(phi_star)*TMath::Sin(theta_star), kf4_mag*TMath::Cos(phi_star)*TMath::Sin(theta_star), 0, 0); if ( theta_star <= 0 || theta_star >= genie::constants::kPi) @@ -421,22 +413,8 @@ double genie::utils::kinematics::Jacobian( // It is not entirely correct to divide by 2 pi, but solely to simplify the code it is better to do it here (Igor Kakorin) J = TMath::Abs(J*dydQ2*(dQ2dtheta*dphi0dphi - dQ2dphi*dphi0dtheta)/2/genie::constants::kPi); - - - - - //std::cout << std::setprecision(18) << "Q^2 = " << Q2 << "\n"; - //std::cout << std::setprecision(18) << "Ek' = " << kf4.Energy() << ", k'x = " << kf4.Px() << ", k'y = " << kf4.Py() << ", k'z = " << kf4.Pz() << ", phi0 = " << kf4.Phi() << "\n"; - //std::cout << std::setprecision(18) << "Computed values: theta = " << theta_star << ", phi = " << phi_star << "\n"; - //std::cout << std::setprecision(18) << "Computed values: dQ2dcostheta = " << -dQ2dtheta/TMath::Sin(theta_star) << ", dQ2dphi = " << dQ2dphi << "\n"; - //std::cout << std::setprecision(18) << "Computed values: dphi0dtheta = " << dphi0dtheta << ", dphi0dphi = " << dphi0dphi << "\n"; - //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - - //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - //std::cout << "Selected values: theta = " << TMath::ACos(costheta) << ", phi = " << phi << "\n"; - //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - - delete ki4; + + delete ki4; } else if ( TransformMatched(fromps,tops, kPSyphi0fEx, kPSQ2fE, forward) ) @@ -453,58 +431,31 @@ double genie::utils::kinematics::Jacobian( J = dydQ2; } - else if ( TransformMatched(fromps,tops, kPSyphi0fEx, kPSQ2vfE, forward) ) + else if ( TransformMatched(fromps,tops, kPSxyfE, kPSTlctl, forward) ) { - TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); + TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(); TLorentzVector* pi4 = i->InitStatePtr()->TgtPtr()->HitNucP4Ptr(); TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); + // mass of initial nucleon + double Mi = i->InitStatePtr()->TgtPtr()->HitNucMass(); - // to hit nucleon rest frame TVector3 beta = pi4->BoostVector(); - pi4->Boost(-beta); - ki4->Boost(-beta); kf4.Boost(-beta); + double nu = ki4->Energy() - kf4.Energy(); + double Pf = kf4.Vect().Mag(); + J = TMath::Abs(Pf/Mi/nu); - TVector3 ki3 = ki4->Vect(); - TVector3 zvec(0., 0., 1.); - TVector3 rot = ( ki3.Cross(zvec) ).Unit(); - double angle = zvec.Angle( ki3 ); - // Handle the edge case where beta is along z, so the - // cross product above vanishes - if ( ki3.Perp() == 0. && ki3.Z() < 0. ) - { - rot = TVector3(0., 1., 0.); - angle = genie::constants::kPi; - } - if ( rot.Mag() > 0 ) - { - ki4->Rotate(angle, rot); - kf4.Rotate(angle, rot); - } - - double kf4_mag = kf4.Vect().Mag(); - double theta0 = kf4.Theta(); - double phi0 = kf4.Phi(); - - TLorentzVector kf4_dphi( -kf4_mag*TMath::Sin(phi0)*TMath::Sin(theta0), kf4_mag*TMath::Cos(phi0)*TMath::Sin(theta0), 0, 0); - // to LAB frame - if ( rot.Mag() > 0 ) - { - kf4_dphi.Rotate(angle, -rot); - } - - kf4_dphi.Boost(beta); - double Q2 = i->Kine().GetKV( kKVQ2 ); - // mass of initial nucleon - double Mi = i->InitStatePtr()->TgtPtr()->HitNucMass(); - // Look up the (on-shell) mass of the final nucleon - TDatabasePDG *tb = TDatabasePDG::Instance(); - double Mf = tb->GetParticle( i->RecoilNucleonPdg() )->Mass(); - // Mandelstam s for the probe/hit nucleon system - double s = TMath::Sq( i->InitState().CMEnergy() ); - double dydQ2 = (s - Mi*Mi)/TMath::Sq(s - Mf*Mf - Q2); - // It is not entirely correct to divide by 2 pi, but solely to simplify the code it is better to do it here (Igor Kakorin) - J = TMath::Abs(dydQ2/kf4_dphi.Energy()/2/genie::constants::kPi); + delete ki4; + } + + else if ( TransformMatched(fromps,tops, kPSQ2vfE, kPSxyfE, forward) ) + { + TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); + TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); + double Ev = ki4->Energy(); + double l = kf4.Vect().Mag(); + J = Jacobian(i, kPSTlctl, kPSxyfE); + J = TMath::Abs(J*2*Ev*l); delete ki4; } @@ -515,7 +466,7 @@ double genie::utils::kinematics::Jacobian( << KinePhaseSpace::AsString(fromps) << " --> " << KinePhaseSpace::AsString(tops); SLOG("KineLimits", pNOTICE) << msg.str() - << ". Set Jacbian equalto zero!"; + << ". Set Jacbian equal to zero!"; //SLOG("KineLimits", pFATAL) << "*** " << msg.str(); //throw genie::exceptions::InteractionException(msg.str()); //exit(1); diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 5a2ee94480..310a995652 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -47,18 +47,31 @@ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) RunningThreadInfo * rtinfo = RunningThreadInfo::Instance(); const EventGeneratorI * evg = rtinfo->RunningThread(); const XSecAlgorithmI * xsec_alg = evg->CrossSectionAlg(); + const AlgId & xsec_alg_id = xsec_alg->Id(); + std::string xsec_alg_name = xsec_alg_id.Name(); + std::string xsec_alg_config = xsec_alg_id.Config(); + std::string xsec_alg_key = xsec_alg_id.Key(); interaction->SetBit(kISkipProcessChk); Kinematics * kine = interaction->KinePtr(); kine->UseSelectedKinematics(); + std::cout << "\n\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << "Name: " << xsec_alg_name << ", Config: " << xsec_alg_config << ", Key: " << xsec_alg_key << "\n"; + double xsec; if ( proc_info.IsQuasiElastic() ) { - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - double xsec = xsec_alg->XSec(interaction, kPSyphi0fEx); - std::cout << "!!!xsec = " << xsec << "\n"; - //xsec = xsec_alg->XSec(interaction, kPSQELEvGen); - //std::cout << "xsec = " << xsec << "\n"; - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << std::endl; + if (xsec_alg_name != "genie::SmithMonizQELCCPXSec" && xsec_alg_name != "genie::SuSAv2QELPXSec" && xsec_alg_key != "genie::HybridXSecAlgorithm/SuSAv2-QEL") + { + xsec = xsec_alg->XSec(interaction, kPSyphi0fEx); + } } + xsec = xsec_alg->XSec(interaction, kPSxyfE); + //if ( proc_info.IsMEC() ) + //{ + //if (xsec_alg_name == "genie::NievesSimoVacasMECPXSec2016" || xsec_alg_name == "genie::SuSAv2MECPXSec" || xsec_alg_name == "genie::EmpiricalMECPXSec2015") + + //} + std::cout << "xsec = " << std::scientific << xsec << "\n"; + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return; } diff --git a/src/Physics/Multinucleon/EventGen/MECGenerator.cxx b/src/Physics/Multinucleon/EventGen/MECGenerator.cxx index d6d9ca9b98..9b35a121bc 100644 --- a/src/Physics/Multinucleon/EventGen/MECGenerator.cxx +++ b/src/Physics/Multinucleon/EventGen/MECGenerator.cxx @@ -378,6 +378,8 @@ void MECGenerator::AddFinalStateLepton(GHepRecord * event) const // Boost final state primary lepton to the lab frame p4l.Boost(beta); // active Lorentz transform + + interaction->KinePtr()->SetFSLeptonP4(p4l); // Figure out the final-state primary lepton PDG code int pdgc = interaction->FSPrimLepton()->PdgCode(); @@ -839,6 +841,7 @@ void MECGenerator::SelectNSVLeptonKinematics (GHepRecord * event) const interaction->KinePtr()->Sety(gy, true); interaction->KinePtr()->Setx(gx, true); interaction->KinePtr()->SetW(gW, true); + interaction->KinePtr()->ClearRunningValues(); interaction->KinePtr()->SetFSLeptonP4(p4l); // in later methods // will also set the four-momentum and W^2 of the hadron system. @@ -1113,12 +1116,15 @@ void MECGenerator::SelectSuSALeptonKinematics(GHepRecord* event) const interaction->KinePtr()->Sety(gy, true); interaction->KinePtr()->Setx(gx, true); interaction->KinePtr()->SetW(gW, true); + interaction->KinePtr()->ClearRunningValues(); interaction->KinePtr()->SetFSLeptonP4(p4l); // in later methods // will also set the four-momentum and W^2 of the hadron system. // -- Lepton event->AddParticle( pdgc, kIStStableFinalState, momidx, -1, -1, -1, p4l, v4 ); + + utils::SetPrimaryLeptonPolarization( event ); LOG("MEC", pDEBUG) << "~~~ LEPTON DONE ~~~"; } diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index 7c1b2d9042..ffc23d93e0 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -323,16 +323,10 @@ double NievesSimoVacasMECPXSec2016::XSec( if( fMECScaleAlg ) xsec *= fMECScaleAlg->GetScaling( * interaction ) ; - if ( kps != kPSTlctl && kps != kPSWQ2fE ) { - LOG("NievesSimoVacasMEC", pWARN) - << "Doesn't support transformation from " - << KinePhaseSpace::AsString(kPSTlctl) << " to " - << KinePhaseSpace::AsString(kps); - xsec = 0; - } - else if ( kps == kPSWQ2fE && xsec != 0. ) { - double J = utils::kinematics::Jacobian( interaction, kPSTlctl, kps ); - xsec *= J; + if ( kps != kPSTlctl ) { + // Compute the appropriate Jacobian for transformation to the requested phase space + double J = utils::kinematics::Jacobian(interaction, kPSTlctl, kps); + xsec *= J; } return xsec; diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index 180a4bf8a6..7266bcc8d8 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -160,11 +160,9 @@ double SuSAv2MECPXSec::XSec(const Interaction* interaction, if( fMECScaleAlg ) xsec *= fMECScaleAlg->GetScaling( * interaction ) ; if ( kps != kPSTlctl ) { - LOG("SuSAv2MEC", pWARN) - << "Doesn't support transformation from " - << KinePhaseSpace::AsString(kPSTlctl) << " to " - << KinePhaseSpace::AsString(kps); - xsec = 0.; + // Compute the appropriate Jacobian for transformation to the requested phase space + double J = utils::kinematics::Jacobian(interaction, kPSTlctl, kps); + xsec *= J; } return xsec; diff --git a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx index 3638a58097..a332a1541e 100644 --- a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx +++ b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx @@ -263,6 +263,9 @@ void QELEventGeneratorSM::ProcessEventRecord(GHepRecord * evrec) const outNucleonMom.Rotate(theta-theta_k, yvec); outNucleonMom.Rotate(phi, zvec); + // One can also rotate the neutrino by an angle psi in Z frame. + // The angles of incoing particles will be same, + // The angles of outgoing particles will be fi_p - psi outLeptonMom.Rotate(psi, unit_nudir); inNucleonMom.Rotate(psi, unit_nudir); outNucleonMom.Rotate(psi, unit_nudir); diff --git a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSuSA.cxx b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSuSA.cxx index 71ac4a97e1..28c67119b5 100644 --- a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSuSA.cxx +++ b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSuSA.cxx @@ -31,6 +31,7 @@ #include "Framework/ParticleData/PDGCodes.h" #include "Physics/QuasiElastic/EventGen/QELEventGeneratorSuSA.h" #include "Physics/Multinucleon/XSection/MECUtils.h" +#include "Physics/Common/PrimaryLeptonUtils.h" #include "Physics/NuclearState/NuclearModelI.h" #include "Framework/Numerical/MathUtils.h" @@ -276,10 +277,14 @@ void QELEventGeneratorSuSA::SelectLeptonKinematics (GHepRecord * event) const interaction->KinePtr()->Sety(gy, true); interaction->KinePtr()->Setx(gx, true); interaction->KinePtr()->SetW(gW, true); + interaction->KinePtr()->ClearRunningValues(); interaction->KinePtr()->SetFSLeptonP4(p4l); // -- Lepton event->AddParticle( pdgc, kIStStableFinalState, momidx, -1, -1, -1, p4l, v4); + + // Set its polarization + utils::SetPrimaryLeptonPolarization( event ); LOG("QELEvent",pDEBUG) << "~~~ LEPTON DONE ~~~"; } diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 99e1c90da9..3765c18813 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -470,13 +470,12 @@ double SuSAv2QELPXSec::XSec(const Interaction* interaction, xsec *= xsec_scale ; - if ( kps != kPSTlctl ) { - LOG("SuSAv2QE", pWARN) - << "Doesn't support transformation from " - << KinePhaseSpace::AsString(kPSTlctl) << " to " - << KinePhaseSpace::AsString(kps); - xsec = 0.; - } + if ( kps != kPSTlctl ) + { + // Compute the appropriate Jacobian for transformation to the requested phase space + double J = utils::kinematics::Jacobian(interaction, kPSTlctl, kps); + xsec *= J; + } return xsec; } From 6a98ce7d9d5c90df4082af46825c03ba79c0a791 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 7 Jul 2024 22:51:05 +0300 Subject: [PATCH 04/78] add a Jacobian kPSxyfE->kPSWQ2fE --- src/Framework/Utils/KineUtils.cxx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Framework/Utils/KineUtils.cxx b/src/Framework/Utils/KineUtils.cxx index 7c511cc379..9abbe4d9b0 100644 --- a/src/Framework/Utils/KineUtils.cxx +++ b/src/Framework/Utils/KineUtils.cxx @@ -437,13 +437,13 @@ double genie::utils::kinematics::Jacobian( TLorentzVector* pi4 = i->InitStatePtr()->TgtPtr()->HitNucP4Ptr(); TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); // mass of initial nucleon - double Mi = i->InitStatePtr()->TgtPtr()->HitNucMass(); + double M = i->InitStatePtr()->TgtPtr()->HitNucMass(); TVector3 beta = pi4->BoostVector(); kf4.Boost(-beta); double nu = ki4->Energy() - kf4.Energy(); double Pf = kf4.Vect().Mag(); - J = TMath::Abs(Pf/Mi/nu); + J = TMath::Abs(Pf/M/nu); delete ki4; } @@ -459,6 +459,18 @@ double genie::utils::kinematics::Jacobian( delete ki4; } + + else if ( TransformMatched(fromps,tops, kPSxyfE, kPSWQ2fE, forward) ) + { + const InitialState & init_state = i->InitState(); + double Ev = init_state.ProbeE(kRfHitNucRest); + double M = init_state.Tgt().HitNucMass(); + double M2 = M*M; + double W = kine.W(); + double W2 = W*W; + double Q2 = kine.Q2(); + J = TMath::Abs( W/(Ev*M*(W2 + Q2 - M2)) ); + } else { std::ostringstream msg; From 5423cdc2fc706737f3e16ffc9348c8c47d029280 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Wed, 11 Dec 2024 23:50:31 +0300 Subject: [PATCH 05/78] change framework;add LlewelynSmith,Nieves,SmithMoniz;Pais;transform MKFF to more common LwlynSmithIsoFFCC for isoscalar target and make related with it changes --- config/LwlynSmithIsoFFCC.xml | 64 ++ config/LwlynSmithQELCCPXSec.xml | 4 +- config/MKFFCC.xml | 32 - config/MKFFEM.xml | 24 - config/MKSPPPXSec2020.xml | 4 +- config/NievesQELCCPXSec.xml | 29 +- config/PaisQELLambdaPXSec.xml | 3 + config/SmithMonizQELCCPXSec.xml | 3 + config/master_config.xml | 5 +- src/Framework/EventGen/XSecAlgorithmI.cxx | 24 +- src/Framework/EventGen/XSecAlgorithmI.h | 7 + src/Framework/GHEP/GHepParticle.cxx | 70 +-- src/Framework/GHEP/GHepParticle.h | 17 +- src/Framework/GHEP/GHepRecord.cxx | 2 +- src/Framework/GHEP/GHepRecord.h | 2 +- src/Physics/Common/NormGenerator.cxx | 13 +- src/Physics/Common/NormGenerator.h | 3 +- src/Physics/Common/PrimaryLeptonUtils.cxx | 68 +-- src/Physics/QuasiElastic/XSection/LinkDef.h | 3 +- .../{MKFFCC.cxx => LwlynSmithIsoFFCC.cxx} | 63 +- .../{MKFFCC.h => LwlynSmithIsoFFCC.h} | 21 +- .../XSection/LwlynSmithQELCCPXSec.cxx | 304 +++++++++- .../XSection/LwlynSmithQELCCPXSec.h | 5 + src/Physics/QuasiElastic/XSection/MKFFEM.cxx | 149 ----- src/Physics/QuasiElastic/XSection/MKFFEM.h | 69 --- .../XSection/NievesQELCCPXSec.cxx | 551 ++++++++++++++++-- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 5 +- .../XSection/SmithMonizQELCCPXSec.cxx | 361 +++++++++--- .../XSection/SmithMonizQELCCPXSec.h | 9 + .../Strange/XSection/PaisQELLambdaPXSec.cxx | 211 +++++++ .../Strange/XSection/PaisQELLambdaPXSec.h | 5 + 31 files changed, 1544 insertions(+), 586 deletions(-) create mode 100644 config/LwlynSmithIsoFFCC.xml delete mode 100644 config/MKFFCC.xml delete mode 100644 config/MKFFEM.xml rename src/Physics/QuasiElastic/XSection/{MKFFCC.cxx => LwlynSmithIsoFFCC.cxx} (53%) rename src/Physics/QuasiElastic/XSection/{MKFFCC.h => LwlynSmithIsoFFCC.h} (70%) delete mode 100644 src/Physics/QuasiElastic/XSection/MKFFEM.cxx delete mode 100644 src/Physics/QuasiElastic/XSection/MKFFEM.h diff --git a/config/LwlynSmithIsoFFCC.xml b/config/LwlynSmithIsoFFCC.xml new file mode 100644 index 0000000000..e9e9432627 --- /dev/null +++ b/config/LwlynSmithIsoFFCC.xml @@ -0,0 +1,64 @@ + + + + + + + + WeakInt,MagnMoments,StrongInt,ElasticFF + + + + + + genie::DipoleAxialFormFactorModel/Default + + + + genie::ZExpAxialFormFactorModel/Default + + + + genie::MArunAxialFormFactorModel/Default + + + + genie::GalsterELFormFactorsModel/MK + genie::DipoleAxialFormFactorModel/MK + true + + + + genie::GalsterELFormFactorsModel/MK + genie::DipoleAxialFormFactorModel/MK + false + + + + + diff --git a/config/LwlynSmithQELCCPXSec.xml b/config/LwlynSmithQELCCPXSec.xml index 9dfa64588d..d6a28deec0 100644 --- a/config/LwlynSmithQELCCPXSec.xml +++ b/config/LwlynSmithQELCCPXSec.xml @@ -14,6 +14,8 @@ XSec-Integrator alg No CabibboAngle double No Cabibbo angle CommonParam[CKM] QEL-CC-XSecScale double yes XSec Scaling factor for CC 1. QEL-NC-XSecScale double yes XSec Scaling factor for NC 1. +PreciseLeptonPol bool Yes Do precise calculation of No + lepton polarization ..................................................................................................... Parameters needed when Integrating with this model to generate splines: @@ -40,7 +42,7 @@ IntegralNuclearInfluenceCutoffEnergy double No genie::PauliBlocker/Default true - + true diff --git a/config/MKFFCC.xml b/config/MKFFCC.xml deleted file mode 100644 index 4f19876c4e..0000000000 --- a/config/MKFFCC.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - WeakInt,MagnMoments,StrongInt,ElasticFF - genie::GalsterELFormFactorsModel/MK - genie::DipoleAxialFormFactorModel/MK - - - - - - diff --git a/config/MKFFEM.xml b/config/MKFFEM.xml deleted file mode 100644 index 03bdf7a45f..0000000000 --- a/config/MKFFEM.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - ElasticFF - - genie::GalsterELFormFactorsModel/MK - - - - - - diff --git a/config/MKSPPPXSec2020.xml b/config/MKSPPPXSec2020.xml index e029549c95..e89597151b 100644 --- a/config/MKSPPPXSec2020.xml +++ b/config/MKSPPPXSec2020.xml @@ -59,8 +59,8 @@ XSec-Integrator alg No 0.840 0.882856 - genie::MKFFCC/Default - genie::MKFFEM/Default + genie::LwlynSmithIsoFFCC/MK-CC + genie::LwlynSmithIsoFFCC/MK-EM genie::RSHelicityAmplModelCC/Default diff --git a/config/NievesQELCCPXSec.xml b/config/NievesQELCCPXSec.xml index 2f41146ef5..955e3fc0ba 100644 --- a/config/NievesQELCCPXSec.xml +++ b/config/NievesQELCCPXSec.xml @@ -16,6 +16,8 @@ RPA bool Yes Turn RPA effects on or off true Coulomb bool Yes Turn coulomb effects on or off true QEL-CC-XSecScale double Yes Scaling factor for CC GPL value QEL-NC-XSecScale double Yes Scaling factor for NC GPL value +PreciseLeptonPol bool Yes Do precise calculation of No + lepton polarization ..................................................................................................... Parameters needed when Integrating with this model to generate splines: @@ -51,6 +53,8 @@ RmaxMode string Yes Method to use to comput VertexGenerator + + true diff --git a/config/PaisQELLambdaPXSec.xml b/config/PaisQELLambdaPXSec.xml index 590af97be7..82bddf1e40 100644 --- a/config/PaisQELLambdaPXSec.xml +++ b/config/PaisQELLambdaPXSec.xml @@ -9,6 +9,8 @@ Algorithm Configurable Parameters: ...................................................................................................... Name Type Optional Comment Default ...................................................................................................... +PreciseLeptonPol bool Yes Do precise calculation of No + lepton polarization XSec-Integrator alg No xsection integration algorithm --> @@ -18,6 +20,7 @@ XSec-Integrator alg No xsection integration algorithm genie::LwlynSmithFFDeltaS/Default genie::QELXSec/Default + true diff --git a/config/SmithMonizQELCCPXSec.xml b/config/SmithMonizQELCCPXSec.xml index 2348c88db9..f2cecb992d 100644 --- a/config/SmithMonizQELCCPXSec.xml +++ b/config/SmithMonizQELCCPXSec.xml @@ -12,6 +12,8 @@ Name Type Optional Comment Default FormFactorsAlg alg No QEL form factors algorithm XSec-Integrator alg No Integrator CKM-Vud double No Vud element of CKM-matrix CommonParam[CKM] +PreciseLeptonPol bool Yes Do precise calculation of No + lepton polarization QEL-CC-XSecScale double yes XSec Scaling factor 1. --> @@ -23,6 +25,7 @@ QEL-CC-XSecScale double yes XSec Scaling factor 1. 1.000 genie::LwlynSmithFFCC/Default genie::SmithMonizQELCCXSec/Default + true diff --git a/config/master_config.xml b/config/master_config.xml index 15460c2891..b43cc93da7 100644 --- a/config/master_config.xml +++ b/config/master_config.xml @@ -138,8 +138,7 @@ ZExpAxialFormFactorModel.xml MArunAxialFormFactorModel.xml LwlynSmithFFCC.xml - MKFFEM.xml - MKFFCC.xml + LwlynSmithIsoFFCC.xml LwlynSmithFFDeltaS.xml TransverseEnhancementFFModel.xml LwlynSmithFFNC.xml @@ -217,7 +216,7 @@ ReinSehgalRESXSec.xml ReinSehgalSPPXSec.xml MKSPPPXSec2020.xml - SPPXSec.xml + SPPXSec.xml H3AMNuGammaPXSec.xml EmpiricalMECPXSec2015.xml NievesSimoVacasMECPXSec2016.xml diff --git a/src/Framework/EventGen/XSecAlgorithmI.cxx b/src/Framework/EventGen/XSecAlgorithmI.cxx index 6e370be0db..b7b540ef3f 100644 --- a/src/Framework/EventGen/XSecAlgorithmI.cxx +++ b/src/Framework/EventGen/XSecAlgorithmI.cxx @@ -10,6 +10,7 @@ #include "Framework/EventGen/XSecAlgorithmI.h" #include "Framework/Messenger/Messenger.h" +#include "Framework/ParticleData/PDGUtils.h" using namespace genie; @@ -17,19 +18,22 @@ using namespace genie; XSecAlgorithmI::XSecAlgorithmI() : Algorithm() { - + fFinalLeptonPolarization = TVector3(0, 0, 0); + fIsPreciseLeptonPolarization = false; } //___________________________________________________________________________ XSecAlgorithmI::XSecAlgorithmI(string name) : Algorithm(name) { - + fFinalLeptonPolarization = TVector3(0, 0, 0); + fIsPreciseLeptonPolarization = false; } //___________________________________________________________________________ XSecAlgorithmI::XSecAlgorithmI(string name, string config) : Algorithm(name, config) { - + fFinalLeptonPolarization = TVector3(0, 0, 0); + fIsPreciseLeptonPolarization = false; } //___________________________________________________________________________ XSecAlgorithmI::~XSecAlgorithmI() @@ -57,3 +61,17 @@ bool XSecAlgorithmI::ValidKinematics(const Interaction* interaction) const return true; } //___________________________________________________________________________ +const TVector3 & XSecAlgorithmI::FinalLeptonPolarization (const Interaction* i) const +{ + int pdg = i->FSPrimLeptonPdg(); + if ( pdg::IsNeutrino(pdg) || pdg::IsElectron(pdg) || pdg::IsMuon(pdg) || pdg::IsTau(pdg) ) + { + fFinalLeptonPolarization = TVector3(0, 0, -1); + } + else + { + fFinalLeptonPolarization = TVector3(0, 0, 1); + } + return fFinalLeptonPolarization; +} +//___________________________________________________________________________ diff --git a/src/Framework/EventGen/XSecAlgorithmI.h b/src/Framework/EventGen/XSecAlgorithmI.h index 2674ce60f6..43eaccf09a 100644 --- a/src/Framework/EventGen/XSecAlgorithmI.h +++ b/src/Framework/EventGen/XSecAlgorithmI.h @@ -18,6 +18,8 @@ #ifndef _XSEC_ALGORITHM_I_H_ #define _XSEC_ALGORITHM_I_H_ +#include "TVector3.h" + #include "Framework/Algorithm/Algorithm.h" #include "Framework/Conventions/KinePhaseSpace.h" #include "Framework/Interaction/Interaction.h" @@ -31,6 +33,8 @@ class XSecAlgorithmI : public Algorithm { //! Compute the cross section for the input interaction virtual double XSec (const Interaction* i, KinePhaseSpace_t k=kPSfE) const = 0; + + virtual const TVector3 & FinalLeptonPolarization (const Interaction* i) const; //! Integrate the model over the kinematic phase space available to the //! input interaction (kinematical cuts can be included) @@ -46,6 +50,9 @@ class XSecAlgorithmI : public Algorithm { XSecAlgorithmI(); XSecAlgorithmI(string name); XSecAlgorithmI(string name, string config); + + mutable TVector3 fFinalLeptonPolarization; + bool fIsPreciseLeptonPolarization; }; } // genie namespace diff --git a/src/Framework/GHEP/GHepParticle.cxx b/src/Framework/GHEP/GHepParticle.cxx index a34d0e9f01..0a36264dc9 100644 --- a/src/Framework/GHEP/GHepParticle.cxx +++ b/src/Framework/GHEP/GHepParticle.cxx @@ -68,10 +68,8 @@ fLastDaughter(daughter2) fP4 = new TLorentzVector(p); fX4 = new TLorentzVector(v); - + fPolarization = TVector3(0, 0, 0); fRescatterCode = -1; - fPolzTheta = -999; - fPolzPhi = -999; fIsBound = false; fRemovalEnergy = 0.; } @@ -92,10 +90,8 @@ fLastDaughter(daughter2) fP4 = new TLorentzVector(px,py,pz,En); fX4 = new TLorentzVector(x,y,z,t); - + fPolarization = TVector3(0, 0, 0); fRescatterCode = -1; - fPolzTheta = -999; - fPolzPhi = -999; fIsBound = false; fRemovalEnergy = 0.; } @@ -119,8 +115,7 @@ fFirstDaughter(-1), fLastDaughter(-1), fP4(0), fX4(0), -fPolzTheta(-999.), -fPolzPhi(-999.), +fPolarization( TVector3(0, 0, 0) ), fRemovalEnergy(0), fIsBound(false) { @@ -305,59 +300,6 @@ bool GHepParticle::IsOffMassShell(void) const return (! this->IsOnMassShell()); } //___________________________________________________________________________ -bool GHepParticle::PolzIsSet(void) const -{ -// checks whether the polarization angles have been set - - return (fPolzTheta > -999 && fPolzPhi > -999); -} -//___________________________________________________________________________ -void GHepParticle::GetPolarization(TVector3 & polz) -{ -// gets the polarization vector - - if(! this->PolzIsSet() ) { - polz.SetXYZ(0.,0.,0.); - return; - } - polz.SetX( TMath::Sin(fPolzTheta) * TMath::Cos(fPolzPhi) ); - polz.SetY( TMath::Sin(fPolzTheta) * TMath::Sin(fPolzPhi) ); - polz.SetZ( TMath::Cos(fPolzTheta) ); -} -//___________________________________________________________________________ -void GHepParticle::SetPolarization(double theta, double phi) -{ -// sets the polarization angles - - if(theta>=0 && theta<=kPi && phi>=0 && phi<2*kPi) - { - fPolzTheta = theta; - fPolzPhi = phi; - - } else { - LOG("GHepParticle", pERROR) - << "Invalid polarization angles (polar = " << theta - << ", azimuthal = " << phi << ")"; - } -} -//___________________________________________________________________________ -void GHepParticle::SetPolarization(const TVector3 & polz) -{ -// sets the polarization angles - - double p = polz.Mag(); - if(! (p>0) ) { - LOG("GHepParticle", pERROR) - << "Input polarization vector has non-positive norm! Ignoring it"; - return; - } - - double theta = TMath::ACos(polz.z()/p); - double phi = kPi + TMath::ATan2(-polz.y(), -polz.x()); - - this->SetPolarization(theta,phi); -} -//___________________________________________________________________________ void GHepParticle::SetBound(bool bound) { // only set it for p or n @@ -394,8 +336,7 @@ void GHepParticle::Init(void) fLastMother = -1; fFirstDaughter = -1; fLastDaughter = -1; - fPolzTheta = -999; - fPolzPhi = -999; + fPolarization = TVector3(0, 0, 0); fIsBound = false; fRemovalEnergy = 0.; fP4 = new TLorentzVector(0,0,0,0); @@ -525,8 +466,7 @@ void GHepParticle::Copy(const GHepParticle & particle) this->SetMomentum (*particle.P4()); this->SetPosition (*particle.X4()); - this->fPolzTheta = particle.fPolzTheta; - this->fPolzPhi = particle.fPolzPhi; + this->fPolarization = particle.fPolarization; this->fIsBound = particle.fIsBound; this->fRemovalEnergy = particle.fRemovalEnergy; diff --git a/src/Framework/GHEP/GHepParticle.h b/src/Framework/GHEP/GHepParticle.h index 6d70af7a9c..f6576bdccc 100644 --- a/src/Framework/GHEP/GHepParticle.h +++ b/src/Framework/GHEP/GHepParticle.h @@ -116,10 +116,10 @@ public : // Get the polarization. Most likely it is only the f/s primary lepton // for which this is usefull and might be set during event generation - double PolzPolarAngle (void) const { return fPolzTheta; } - double PolzAzimuthAngle (void) const { return fPolzPhi; } - bool PolzIsSet (void) const; - void GetPolarization (TVector3 & polz); + double PolzPolarAngle (void) const { return fPolarization.Mag()>0?fPolarization.Theta():0; } + double PolzAzimuthAngle (void) const { return fPolarization.Mag()>0?fPolarization.Phi():0; } + bool PolzIsSet (void) const { return fPolarization.Mag()>0;} + const TVector3 & GetPolarization (void) const {return fPolarization;} // Set pdg code and status codes void SetPdgCode (int c); @@ -144,9 +144,7 @@ public : void SetPy (double py); void SetPz (double pz); - // Set the polarization angles - void SetPolarization(double theta, double phi); - void SetPolarization(const TVector3 & polz); + void SetPolarization(const TVector3 & polz) { fPolarization = polz;} // Set the bould flag & removal energy (bound flag set automatically // if a positive removal energy is set) @@ -180,12 +178,11 @@ public : int fLastDaughter; ///< last daughter idx TLorentzVector * fP4; ///< momentum 4-vector (GeV) TLorentzVector * fX4; ///< position 4-vector (in the target nucleus coordinate system / x,y,z in fm / t from the moment of the primary interaction in ys(yocto second = 10^-24 s) - double fPolzTheta; ///< polar polarization angle (rad) - double fPolzPhi; ///< azimuthal polarization angle (rad) + TVector3 fPolarization; ///< polarization vector of final lepton double fRemovalEnergy; ///< removal energy for bound nucleons (GeV) bool fIsBound; ///< 'is it a bound particle?' flag -ClassDef(GHepParticle, 2) +ClassDef(GHepParticle, 3) }; diff --git a/src/Framework/GHEP/GHepRecord.cxx b/src/Framework/GHEP/GHepRecord.cxx index cef32032df..5b9e3cfdbe 100644 --- a/src/Framework/GHEP/GHepRecord.cxx +++ b/src/Framework/GHEP/GHepRecord.cxx @@ -1048,7 +1048,7 @@ void GHepRecord::Print(ostream & stream) const << p->P4()->M() << " "; if (p->PolzIsSet()) { - p->GetPolarization(polarization); + polarization = p->GetPolarization(); stream << "P = (" << polarization.x() << "," << polarization.y() << "," << polarization.z() << ")"; } diff --git a/src/Framework/GHEP/GHepRecord.h b/src/Framework/GHEP/GHepRecord.h index 03f4013bb5..b497e52d13 100644 --- a/src/Framework/GHEP/GHepRecord.h +++ b/src/Framework/GHEP/GHepRecord.h @@ -197,7 +197,7 @@ public : private: -ClassDef(GHepRecord, 2) +ClassDef(GHepRecord, 3) }; diff --git a/src/Physics/Common/NormGenerator.cxx b/src/Physics/Common/NormGenerator.cxx index 1107c298fc..f6f9fb081b 100644 --- a/src/Physics/Common/NormGenerator.cxx +++ b/src/Physics/Common/NormGenerator.cxx @@ -30,8 +30,14 @@ EventRecordVisitorI("genie::NormGenerator") } //___________________________________________________________________________ -NormGenerator::NormGenerator(string config): -EventRecordVisitorI("genie::NormGenerator") +NormGenerator::NormGenerator(string name): +EventRecordVisitorI(name) +{ + +} +//___________________________________________________________________________ +NormGenerator::NormGenerator(string name, string config): +EventRecordVisitorI(name, config) { } @@ -44,8 +50,7 @@ NormGenerator::~NormGenerator() void NormGenerator::ProcessEventRecord(GHepRecord * evrec) const { Interaction * interaction = evrec->Summary(); - const InitialState & init_state = interaction -> InitState(); - + // Access cross section algorithm for running thread RunningThreadInfo * rtinfo = RunningThreadInfo::Instance(); const EventGeneratorI * evg = rtinfo->RunningThread(); diff --git a/src/Physics/Common/NormGenerator.h b/src/Physics/Common/NormGenerator.h index 49cc5388e2..d3b0d63ab6 100644 --- a/src/Physics/Common/NormGenerator.h +++ b/src/Physics/Common/NormGenerator.h @@ -34,7 +34,8 @@ namespace genie { public : NormGenerator(); - NormGenerator(string config); + NormGenerator(string name); + NormGenerator(string name, string config); ~NormGenerator(); // implement the EventRecordVisitorI interface diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 310a995652..bf281a4a20 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -8,8 +8,13 @@ */ //____________________________________________________________________________ +#include "TLorentzVector.h" #include "TVector3.h" +#include "TMath.h" +#include "TMatrixD.h" + #include "TDecompSVD.h" +#include "Framework/Conventions/Constants.h" #include "Physics/Common/PrimaryLeptonUtils.h" #include "Framework/GHEP/GHepRecord.h" #include "Framework/GHEP/GHepParticle.h" @@ -18,9 +23,11 @@ #include "Framework/EventGen/EventGeneratorI.h" #include "Framework/EventGen/RunningThreadInfo.h" #include "Framework/EventGen/XSecAlgorithmI.h" +#include "Framework/ParticleData/PDGLibrary.h" using namespace genie; using namespace genie::utils; +using namespace genie::constants; //___________________________________________________________________________ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) @@ -29,7 +36,6 @@ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) // accessible for generators that use a more unified approach (e.g., // QELEventGenerator and MECGenerator). -- S. Gardiner - // get the final state primary lepton GHepParticle * fsl = ev->FinalStatePrimaryLepton(); if ( !fsl ) { @@ -39,67 +45,19 @@ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) } //-- Get the interaction Interaction * interaction = ev->Summary(); - const ProcessInfo & proc_info = interaction->ProcInfo(); - // Polarization of final charged lepton according to Kuzmin, Lyubushkin and Naumov, hep-ph/0312107 - if ( proc_info.IsWeakCC() ) - { - //-- Access cross section algorithm for running thread - RunningThreadInfo * rtinfo = RunningThreadInfo::Instance(); - const EventGeneratorI * evg = rtinfo->RunningThread(); - const XSecAlgorithmI * xsec_alg = evg->CrossSectionAlg(); - const AlgId & xsec_alg_id = xsec_alg->Id(); - std::string xsec_alg_name = xsec_alg_id.Name(); - std::string xsec_alg_config = xsec_alg_id.Config(); - std::string xsec_alg_key = xsec_alg_id.Key(); - interaction->SetBit(kISkipProcessChk); - Kinematics * kine = interaction->KinePtr(); - kine->UseSelectedKinematics(); - std::cout << "\n\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << "Name: " << xsec_alg_name << ", Config: " << xsec_alg_config << ", Key: " << xsec_alg_key << "\n"; - double xsec; - if ( proc_info.IsQuasiElastic() ) - { - if (xsec_alg_name != "genie::SmithMonizQELCCPXSec" && xsec_alg_name != "genie::SuSAv2QELPXSec" && xsec_alg_key != "genie::HybridXSecAlgorithm/SuSAv2-QEL") - { - xsec = xsec_alg->XSec(interaction, kPSyphi0fEx); - } - } - xsec = xsec_alg->XSec(interaction, kPSxyfE); - //if ( proc_info.IsMEC() ) - //{ - //if (xsec_alg_name == "genie::NievesSimoVacasMECPXSec2016" || xsec_alg_name == "genie::SuSAv2MECPXSec" || xsec_alg_name == "genie::EmpiricalMECPXSec2015") - - //} - std::cout << "xsec = " << std::scientific << xsec << "\n"; - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - return; - } - - // Get (px,py,pz) @ LAB - TVector3 plab( fsl->Px(), fsl->Py(), fsl->Pz() ); - - // In the limit m/E->0: leptons are left-handed and their anti-particles - // are right-handed - int pdgc = fsl->Pdg(); - if ( pdg::IsNeutrino(pdgc) || pdg::IsElectron(pdgc) || - pdg::IsMuon(pdgc) || pdg::IsTau(pdgc) ) - { - plab *= -1; // left-handed - } - + //-- Access cross section algorithm for running thread + RunningThreadInfo * rtinfo = RunningThreadInfo::Instance(); + const EventGeneratorI * evg = rtinfo->RunningThread(); + const XSecAlgorithmI * xsec_alg = evg->CrossSectionAlg(); + fsl->SetPolarization(xsec_alg->FinalLeptonPolarization(interaction)); + LOG("LeptonicVertex", pINFO) << "Setting polarization angles for particle: " << fsl->Name(); - fsl->SetPolarization( plab ); - if ( fsl->PolzIsSet() ) { LOG("LeptonicVertex", pINFO) << "Polarization (rad): Polar = " << fsl->PolzPolarAngle() << ", Azimuthal = " << fsl->PolzAzimuthAngle(); } - // reset trust bits - interaction->ResetBit(kISkipProcessChk); - interaction->ResetBit(kISkipKinematicChk); - } diff --git a/src/Physics/QuasiElastic/XSection/LinkDef.h b/src/Physics/QuasiElastic/XSection/LinkDef.h index 85c97a998b..4ed7a11be0 100644 --- a/src/Physics/QuasiElastic/XSection/LinkDef.h +++ b/src/Physics/QuasiElastic/XSection/LinkDef.h @@ -23,8 +23,7 @@ #pragma link C++ class genie::LwlynSmithFFCC; #pragma link C++ class genie::LwlynSmithFFNC; #pragma link C++ class genie::LwlynSmithFF; -#pragma link C++ class genie::MKFFEM; -#pragma link C++ class genie::MKFFCC; +#pragma link C++ class genie::LwlynSmithIsoFFCC; #pragma link C++ class genie::GalsterELFormFactorsModel; #pragma link C++ class genie::LwlynSmithFFDeltaS; #pragma link C++ class genie::AxialFormFactorModelI; diff --git a/src/Physics/QuasiElastic/XSection/MKFFCC.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithIsoFFCC.cxx similarity index 53% rename from src/Physics/QuasiElastic/XSection/MKFFCC.cxx rename to src/Physics/QuasiElastic/XSection/LwlynSmithIsoFFCC.cxx index d637ae2edb..5af4e0c194 100644 --- a/src/Physics/QuasiElastic/XSection/MKFFCC.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithIsoFFCC.cxx @@ -14,7 +14,7 @@ Author: Igor Kakorin , Joint Institute for Nuclear Research //____________________________________________________________________________ #include "Framework/Conventions/Constants.h" -#include "Physics/QuasiElastic/XSection/MKFFCC.h" +#include "Physics/QuasiElastic/XSection/LwlynSmithIsoFFCC.h" #include "Framework/Messenger/Messenger.h" #include "Framework/ParticleData/PDGLibrary.h" #include "Framework/ParticleData/PDGCodes.h" @@ -23,44 +23,72 @@ using namespace genie; using namespace genie::constants; //____________________________________________________________________________ -MKFFCC::MKFFCC() : -LwlynSmithFF("genie::MKFFCC") +LwlynSmithIsoFFCC::LwlynSmithIsoFFCC() : +LwlynSmithFF("genie::LwlynSmithIsoFFCC") { } //____________________________________________________________________________ -MKFFCC::MKFFCC(string config) : -LwlynSmithFF("genie::MKFFCC", config) +LwlynSmithIsoFFCC::LwlynSmithIsoFFCC(string config) : +LwlynSmithFF("genie::LwlynSmithIsoFFCC", config) { } //____________________________________________________________________________ -MKFFCC::~MKFFCC() +LwlynSmithIsoFFCC::~LwlynSmithIsoFFCC() { } //____________________________________________________________________________ -double MKFFCC::F1V(const Interaction * interaction) const +double LwlynSmithIsoFFCC::F1V(const Interaction * interaction) const { - return LwlynSmithFF::F1V(interaction); + if (fIsCC) + return LwlynSmithFF::F1V(interaction); + + double F1p = this->F1P(interaction); + double F1n = this->F1N(interaction); + double _F1V = F1p + F1n; + return _F1V; } //____________________________________________________________________________ -double MKFFCC::xiF2V(const Interaction * interaction) const +double LwlynSmithIsoFFCC::xiF2V(const Interaction * interaction) const { - return LwlynSmithFF::xiF2V(interaction); + if (fIsCC) + return LwlynSmithFF::xiF2V(interaction); + + double F2p = this->F2P(interaction); + double F2n = this->F2N(interaction); + double _xiF2V = F2p + F2n; + return _xiF2V; } //____________________________________________________________________________ -double MKFFCC::FA(const Interaction * interaction) const +double LwlynSmithIsoFFCC::FA(const Interaction * interaction) const { return LwlynSmithFF::FA(interaction); } //____________________________________________________________________________ -double MKFFCC::Fp(const Interaction * interaction) const +double LwlynSmithIsoFFCC::Fp(const Interaction * interaction) const { - return LwlynSmithFF::Fp(interaction); + // get momentum transfer + const Kinematics & kine = interaction->Kine(); + double q2 = kine.q2(); + + // get struck nucleon mass & set pion mass + PDGLibrary * pdglib = PDGLibrary::Instance(); + double M = (pdglib->Find(kPdgProton)->Mass() + pdglib->Find(kPdgNeutron)->Mass())/2; + double M2 = M*M; + double Mpi = kPionMass; + double Mpi2 = TMath::Power(Mpi, 2); + + // calculate FA + double fa = this->FA(interaction); + + // calculate Fp + double _Fp = 2. * M2 * fa/(Mpi2-q2); + return _Fp; } //____________________________________________________________________________ -double MKFFCC::tau(const Interaction * interaction) const +double LwlynSmithIsoFFCC::tau(const Interaction * interaction) const { // computes q^2 / (4 * Misoscalar^2) @@ -75,6 +103,11 @@ double MKFFCC::tau(const Interaction * interaction) const //-- calculate q^2 / (4*Mnuc^2) return q2/(4*M*M); } - +//____________________________________________________________________________ +void LwlynSmithIsoFFCC::LoadConfig(void) +{ + LwlynSmithFF::LoadConfig(); + GetParamDef( "IsCCFormFactors", fIsCC, true); +} diff --git a/src/Physics/QuasiElastic/XSection/MKFFCC.h b/src/Physics/QuasiElastic/XSection/LwlynSmithIsoFFCC.h similarity index 70% rename from src/Physics/QuasiElastic/XSection/MKFFCC.h rename to src/Physics/QuasiElastic/XSection/LwlynSmithIsoFFCC.h index a582c32f95..b8c6228590 100644 --- a/src/Physics/QuasiElastic/XSection/MKFFCC.h +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithIsoFFCC.h @@ -1,10 +1,11 @@ //____________________________________________________________________________ /*! -\class genie::MKFFCC +\class genie::LwlynSmithIsoFFCC \brief Is a concrete implementation of the QELFormFactorsModelI: - Form Factors for MK SPP model. + Form Factors for Quasi Elastic CC vN scattering according to + Llewellyn-Smith model for isoscalar nucleon. \author Igor Kakorin , Joint Institute for Nuclear Research \n @@ -20,19 +21,19 @@ */ //____________________________________________________________________________ -#ifndef _MK_CC_FORM_FACTOR_MODEL_H_ -#define _MK_CC_FORM_FACTOR_MODEL_H_ +#ifndef _LLEWELLYN_SMITH_ISO_CC_FORM_FACTOR_MODEL_H_ +#define _LLEWELLYN_SMITH_ISO_CC_FORM_FACTOR_MODEL_H_ #include "Physics/QuasiElastic/XSection/LwlynSmithFF.h" namespace genie { -class MKFFCC : public LwlynSmithFF { +class LwlynSmithIsoFFCC : public LwlynSmithFF { public: - MKFFCC(); - MKFFCC(string config); - virtual ~MKFFCC(); + LwlynSmithIsoFFCC(); + LwlynSmithIsoFFCC(string config); + virtual ~LwlynSmithIsoFFCC(); // QELFormFactorModelI interface implementation double F1V (const Interaction * interaction) const; @@ -41,6 +42,10 @@ class MKFFCC : public LwlynSmithFF { double Fp (const Interaction * interaction) const; double tau (const Interaction * interaction) const; +protected: + virtual void LoadConfig (void); + bool fIsCC; + }; diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index 5d743afbcd..8ca54a5f47 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -36,6 +36,7 @@ using namespace genie; using namespace genie::constants; using namespace genie::utils; +using namespace std::complex_literals; //____________________________________________________________________________ LwlynSmithQELCCPXSec::LwlynSmithQELCCPXSec() : @@ -209,7 +210,7 @@ double LwlynSmithQELCCPXSec::FullDifferentialXSec(const Interaction* interactio double mNi = init_state.Tgt().HitNucMass(); // Hadronic matrix element for CC neutrino interactions should really use - // the "nucleon mass," i.e., the mean of the proton and neutrino masses. + // the "nucleon mass," i.e., the mean of the proton and neutron masses. // This expression would also work for NC and EM scattering (since the // initial and final on-shell nucleon masses would be the same) double mNucleon = ( mNi + interaction->RecoilNucleon()->Mass() ) / 2.; @@ -260,8 +261,8 @@ double LwlynSmithQELCCPXSec::FullDifferentialXSec(const Interaction* interactio double tau = Q2tilde / (4 * std::pow(mNucleon, 2)); double h1 = FA*FA*(1 + tau) + tau*(F1V + xiF2V)*(F1V + xiF2V); double h2 = FA*FA + F1V*F1V + tau*xiF2V*xiF2V; - double h3 = 2.0 * FA * (F1V + xiF2V); - double h4 = 0.25 * xiF2V*xiF2V *(1-tau) + 0.5*F1V*xiF2V + FA*Fp - tau*Fp*Fp; + double h3 = 2.0 * FA * (F1V + xiF2V); // toghether with sign of FA ("-") will give correct total sign + double h4 = (0.25 * xiF2V*xiF2V *(1-tau) + 0.5*F1V*xiF2V + FA*Fp - tau*Fp*Fp); bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); int sign = (is_neutrino) ? -1 : 1; @@ -427,6 +428,9 @@ void LwlynSmithQELCCPXSec::LoadConfig(void) // Cross section scaling factor GetParam( "QEL-CC-XSecScale", fXSecCCScale ) ; GetParam( "QEL-NC-XSecScale", fXSecNCScale ) ; + + // Do precise calculation of lepton polarization + GetParamDef( "PreciseLeptonPol", fIsPreciseLeptonPolarization, false ) ; double thc ; GetParam( "CabibboAngle", thc ) ; @@ -474,3 +478,297 @@ void LwlynSmithQELCCPXSec::LoadConfig(void) // Decide whether or not it should be used in FullDifferentialXSec GetParamDef( "DoPauliBlocking", fDoPauliBlocking, true ); } +//____________________________________________________________________________ +const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const +{ + if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + const QELFormFactorsModelI* qel_ff_mod = dynamic_cast (this->SubAlg("FormFactorsAlg")); + const AlgId & qel_ff_mod_id = qel_ff_mod->Id(); + std::string qel_ff_mod_name = qel_ff_mod_id.Name(); + bool isosymmetry = true; + if (qel_ff_mod_name == "genie::LwlynSmithFFCC") isosymmetry = false; + if (qel_ff_mod_name == "genie::LwlynSmithIsoFFCC") isosymmetry = true; + + double ml = interaction->FSPrimLepton()->Mass(); + // First we need access to all of the particles in the interaction + // The particles were stored in the lab frame + const Kinematics& kinematics = interaction -> Kine(); + const InitialState& init_state = interaction -> InitState(); + const Target& tgt = init_state.Tgt(); + + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + + // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial + // struck nucleon + double Mi_onshell = tgt.HitNucMass(); + + // On-shell mass of final nucleon (from PDGLibrary) + double Mf = interaction->RecoilNucleon()->Mass(); + + // Isoscalar mass of nucleon + double Miso = (Mi_onshell + Mf)/2; + + // Note that GetProbeP4 defaults to returning the probe 4-momentum in the + // struck nucleon rest frame, so we have to explicitly ask for the lab frame + // here + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + TLorentzVector inNucleonMom(*init_state.TgtPtr()->HitNucP4Ptr()); + TLorentzVector inNucleonMomOnShell(inNucleonMom); + + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + const TLorentzVector outNucleonMom = kinematics.HadSystP4(); + TLorentzVector outNucleonMomOnShell(outNucleonMom); + + // Apply Pauli blocking if enabled + if ( fDoPauliBlocking && tgt.IsNucleus() && !interaction->TestBit(kIAssumeFreeNucleon) ) { + int final_nucleon_pdg = interaction->RecoilNucleonPdg(); + double kF = fPauliBlocker->GetFermiMomentum(tgt, final_nucleon_pdg, tgt.HitNucPosition()); + double pNf = outNucleonMom.P(); + if ( pNf < kF ) + { + LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + } + + if (isosymmetry) + { + double inNucleonOnShellEnergy = TMath::Hypot(Miso, inNucleonMomOnShell.P() ); + double outNucleonOnShellEnergy = TMath::Hypot(Miso, outNucleonMomOnShell.P() ); + inNucleonMomOnShell.SetE(inNucleonOnShellEnergy); + outNucleonMomOnShell.SetE(outNucleonOnShellEnergy); + } + else + { + double inNucleonOnShellEnergy = TMath::Hypot(Mi_onshell, inNucleonMomOnShell.P() ); + inNucleonMomOnShell.SetE(inNucleonOnShellEnergy); + } + + // Ordinary 4-momentum transfer + TLorentzVector qP4 = neutrinoMom - leptonMom; + double Q2 = -qP4.Mag2(); + + // Effective 4-momentum transfer (according to the deForest prescription) for + // use in computing the hadronic tensor + TLorentzVector qTildeP4 = outNucleonMomOnShell - inNucleonMomOnShell; + // If the binding energy correction causes an unphysical value + // of q0Tilde or Q2tilde, just return 0. + if ( qTildeP4.E() < 0 && init_state.Tgt().IsNucleus() && !interaction->TestBit(kIAssumeFreeNucleon) ) + { + LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + double Q2tilde = -qTildeP4.Mag2(); + if ( Q2tilde < 0 ) + { + LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // Store Q2tilde in the kinematic variable representing Q2. + // This will ensure that the form factors are calculated correctly + // using the de Forest prescription (Q2tilde instead of Q2). + interaction->KinePtr()->SetQ2(Q2tilde); + + // Calculate the QEL form factors + fFormFactors.Calculate(interaction); + + double FV = fFormFactors.F1V(); + double FM = fFormFactors.xiF2V(); + double FA = fFormFactors.FA(); + double FP = 2*fFormFactors.Fp(); + double FS = 2*0; + double FT = 0; + double FFV = FV*FV; + double FFM = FM*FM; + double FFT = FT*FT; + double FFS = FS*FS; + double FFVM = (FV + FM)*(FV + FM); + double FFAT = (FA + FT)*(FA + FT); + double FFMS = (FM - FS)*(FM - FS); + double FFTP = (FT - FP)*(FT - FP); + + // Restore Q2 in the interaction's kinematic variables + // now that the form factors have been computed + interaction->KinePtr()->SetQ2(Q2); + + // Off shell mass of initial nucleon + double Mi = inNucleonMom.M(); + double Mi2 = inNucleonMom.M2(); + double M = (Mi + Mf)/2; + double M2 = M*M; + double r = (Mi - Mf)/2/M; + double r2 = r*r; + double mr2 = Mi2/M2; + + double tau = Q2/4/M2; + double w01 = (1 + tau)*FFAT + tau*FFVM; + double w21 = FFVM; + double w02 = FFV + FFAT + tau*(FFM + FFT); + double w12 = 2*FT*(FA + FT); + double w22 = FFT; + double w03 = -2*(FV + FM )*(FA + FT); + double w04 = 1/4.*(FFS - FFM + 2*(FV*(FS - FM) + (FT - FP)*(FA + FT)) + tau*(FFMS + FFTP)); + double w14 = 1/2.*((FV + FM)*(FS - FM) + (FA + FT)*(FT - FP)); + double w24 = 1/4.*FFTP; + double w05 = w02 + FS*(FV - tau*FM) + FT*(FA + FT - tau*FP); + double w15 = w12 - FM*(FV + FM) - FP*(FA + FT); + double w25 = w22 - FP*FT; + + // common factor 2M^2V^2 will be cancelled in the calculation of rho + double W1 = (w01 + + w21*r2); + double W2 = (w02 + w12*r + w22*r2)*mr2; + double W3 = (w03 )*mr2; + double W4 = (w04 + w14*r + w24*r2)*mr2; + double W5 = (w05 + w15*r + w25*r2)*mr2; + + double p[4], q[4], epq[4][4], k[4], l[4], s[4], eskl[4]; + std::complex jp[4], jm[4]; + + p[0] = inNucleonMom.E(); + p[1] = inNucleonMom.Px(); + p[2] = inNucleonMom.Py(); + p[3] = inNucleonMom.Pz(); + + q[0] = qP4.E(); + q[1] = qP4.Px(); + q[2] = qP4.Py(); + q[3] = qP4.Pz(); + + k[0] = neutrinoMom.E(); + k[1] = -neutrinoMom.Px(); + k[2] = -neutrinoMom.Py(); + k[3] = -neutrinoMom.Pz(); + + l[0] = leptonMom.E(); + l[1] = -leptonMom.Px(); + l[2] = -leptonMom.Py(); + l[3] = -leptonMom.Pz(); + + s[0] = leptonMom.P()/ml; + s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; + s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; + s[3] = -leptonMom.Vect().Unit().Z()*leptonMom.E()/ml; + + // epsilon^\alpha\beta\gamma\delta p_\gamma q_\delta + for (int a = 0; a < 4; a++) + { + for (int b = 0; b < 4; b++) + { + epq[a][b] = 0; + if (b == a) continue; + for (int g = 0; g < 4; g++) + { + if (g == b || g == a) continue; + for (int d = 0; d < 4; d++) + { + if (d == g || d == b || d == a) continue; + epq[a][b] += e(a,b,g,d)*(a == 0?1:-1)*(b == 0?1:-1)*p[g]*q[d]; + } + } + } + } + + // epsilon_\alpha\beta\gamma\delta s^\beta k^\gamma l^\delta + for (int a = 0; a < 4; a++) + { + eskl[a] = 0; + for (int b = 0; b < 4; b++) + { + if (b == a) continue; + for (int g = 0; g < 4; g++) + { + if (g == b || g == a) continue; + for (int d = 0; d < 4; d++) + { + if (d == g || d == b || d == a) continue; + double sb = s[b]*(b == 0?1:-1); + double kg = k[g]*(g == 0?1:-1); + double ld = l[d]*(d == 0?1:-1); + eskl[a] += e(a,b,g,d)*sb*kg*ld; + } + } + } + } + + double kl = k[0]*l[0] - k[1]*l[1] - k[2]*l[2] - k[3]*l[3]; + double ks = k[0]*s[0] - k[1]*s[1] - k[2]*s[2] - k[3]*s[3]; + + for (int a = 0; a < 4; a++) + { + if (is_neutrino) + { + jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha + jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha + } + else + { + jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha + jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha + } + } + + + //Additional constants and variables + std::complex Wmunu, Wnumu, LWpp(0, 0), LWpm(0, 0), LWmp(0, 0), LWmm(0, 0); + for(int mu = 0; mu < 4; mu++) + { + for(int nu = mu;nu < 4; nu++) + { + double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/Mi2 + q[mu]*q[nu]*W4/Mi2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/Mi2; + double Wimag = epq[mu][nu]*W3/2/Mi2; + Wmunu = Wreal - 1i*Wimag; // W^\mu\nu + LWpp += jp[mu]*std::conj(jp[nu])*Wmunu; // Lpp_\mu\nu*W^\mu\nu + LWpm += jp[mu]*std::conj(jm[nu])*Wmunu; // Lpm_\mu\nu*W^\mu\nu + LWmp += jm[mu]*std::conj(jp[nu])*Wmunu; // Lmp_\mu\nu*W^\mu\nu + LWmm += jm[mu]*std::conj(jm[nu])*Wmunu; // Lmm_\mu\nu*W^\mu\nu + if (mu != nu) + { + Wnumu = Wreal + 1i*Wimag; + LWpp += jp[nu]*std::conj(jp[mu])*Wnumu; // Lpp_\mu\nu*W^\mu\nu + LWpm += jp[nu]*std::conj(jm[mu])*Wnumu; // Lpm_\mu\nu*W^\mu\nu + LWmp += jm[nu]*std::conj(jp[mu])*Wnumu; // Lmp_\mu\nu*W^\mu\nu + LWmm += jm[nu]*std::conj(jm[mu])*Wnumu; // Lmm_\mu\nu*W^\mu\nu + } + } + } + std::complex LWppmm = LWpp + LWmm; + std::complex rhopp = LWpp/LWppmm; + std::complex rhopm = LWpm/LWppmm; + std::complex rhomp = LWmp/LWppmm; + std::complex rhomm = LWmm/LWppmm; + double PL = std::real(rhopp - rhomm); + double PP = std::real(rhopm + rhomp); + double PT = std::imag(rhomp - rhopm); + + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + TVector3 Pz = leptonMom3.Unit(); + TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); + TVector3 Py = Pz.Cross(Px); + TVector3 pol = PT*Px + PP*Py + PL*Pz; + fFinalLeptonPolarization = pol; + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << "PL = " << PL << ", PT = " << PT << ", PP = " << PP << "\n"; + std::cout << fFinalLeptonPolarization.Mag() << "\n"; + std::cout << "LW@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + return fFinalLeptonPolarization; +} +//____________________________________________________________________________ +inline int LwlynSmithQELCCPXSec::g(int a, int b) const +{ + return (a==b)*(2*(a==0) - 1); +} +//____________________________________________________________________________ +inline int LwlynSmithQELCCPXSec::e(int a, int b, int c, int d) const +{ + return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; +} +//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h index 49bbb8f36b..b78f7e7ce1 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h @@ -23,6 +23,8 @@ #ifndef _LLEWELLYN_SMITH_QELCC_CROSS_SECTION_H_ #define _LLEWELLYN_SMITH_QELCC_CROSS_SECTION_H_ +#include + #include "Physics/NuclearState/NuclearModelI.h" #include "Framework/EventGen/XSecAlgorithmI.h" #include "Physics/QuasiElastic/XSection/QELFormFactors.h" @@ -45,6 +47,9 @@ class LwlynSmithQELCCPXSec : public XSecAlgorithmI { double XSec (const Interaction * i, KinePhaseSpace_t k) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; + const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + int e(int a, int b, int c, int d) const; + int g(int a, int b) const; // Override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Physics/QuasiElastic/XSection/MKFFEM.cxx b/src/Physics/QuasiElastic/XSection/MKFFEM.cxx deleted file mode 100644 index f96749e7c2..0000000000 --- a/src/Physics/QuasiElastic/XSection/MKFFEM.cxx +++ /dev/null @@ -1,149 +0,0 @@ -//____________________________________________________________________________ -/* - Copyright (c) 2003-2019, The GENIE Collaboration - For the full text of the license visit http://copyright.genie-mc.org - or see $GENIE/LICENSE - - Author: Igor Kakorin , Joint Institute for Nuclear Research - based on code of Costas Andreopoulos - University of Liverpool & STFC Rutherford Appleton Lab - - For the class documentation see the corresponding header file. - - -*/ -//____________________________________________________________________________ - -#include - -#include "Framework/Algorithm/AlgConfigPool.h" -#include "Framework/Algorithm/AlgFactory.h" -#include "Physics/QuasiElastic/XSection/ELFormFactors.h" -#include "Physics/QuasiElastic/XSection/ELFormFactorsModelI.h" -#include "Physics/QuasiElastic/XSection/MKFFEM.h" -#include "Framework/Conventions/Constants.h" -#include "Framework/Messenger/Messenger.h" -#include "Framework/ParticleData/PDGLibrary.h" -#include "Framework/ParticleData/PDGCodes.h" - -using namespace genie; -using namespace genie::constants; - -//____________________________________________________________________________ -MKFFEM::MKFFEM() : -QELFormFactorsModelI("genie::MKFFEM") -{ - -} -//____________________________________________________________________________ -MKFFEM::MKFFEM(string config) : -QELFormFactorsModelI("genie::MKFFEM", config) -{ - -} -//____________________________________________________________________________ -MKFFEM::~MKFFEM() -{ - -} -//____________________________________________________________________________ -double MKFFEM::F1P(const Interaction * interaction) const -{ - fELFF.Calculate(interaction); - double t = this->tau(interaction); - double T = 1 / (1 - t); - return T * (fELFF.Gep() - t * fELFF.Gmp()); -} -//____________________________________________________________________________ -double MKFFEM::F2P(const Interaction * interaction) const -{ - fELFF.Calculate(interaction); - double t = this->tau(interaction); - double T = 1 / (1 - t); - return T * (fELFF.Gmp() - fELFF.Gep()); -} -//____________________________________________________________________________ -double MKFFEM::F1N(const Interaction * interaction) const -{ - fELFF.Calculate(interaction); - double t = this->tau(interaction); - double T = 1 / (1 - t); - return T * (fELFF.Gen() - t * fELFF.Gmn()); -} -//____________________________________________________________________________ -double MKFFEM::F2N(const Interaction * interaction) const -{ - fELFF.Calculate(interaction); - double t = this->tau(interaction); - double T = 1 / (1 - t); - return T * (fELFF.Gmn() - fELFF.Gen()); -} -//____________________________________________________________________________ -double MKFFEM::F1V(const Interaction * interaction) const -{ - double F1p = this->F1P(interaction); - double F1n = this->F1N(interaction); - - double _F1V = F1p + F1n; - return _F1V; -} -//____________________________________________________________________________ -double MKFFEM::xiF2V(const Interaction * interaction) const -{ - double F2p = this->F2P(interaction); - double F2n = this->F2N(interaction); - - double _xiF2V = F2p + F2n; - return _xiF2V; -} -//____________________________________________________________________________ -double MKFFEM::FA(const Interaction * /*interaction*/ ) const -{ - return 0.; -} -//____________________________________________________________________________ -double MKFFEM::Fp(const Interaction * /*interaction*/ ) const -{ - return 0.; -} -//____________________________________________________________________________ -void MKFFEM::Configure(const Registry & config) -{ - Algorithm::Configure(config); - this->LoadConfig(); -} -//____________________________________________________________________________ -void MKFFEM::Configure(string config) -{ - Algorithm::Configure(config); - this->LoadConfig(); -} -//____________________________________________________________________________ -void MKFFEM::LoadConfig(void) -{ -// Load configuration data from its configuration Registry (or global defaults) -// to private data members - fElFFModel = - dynamic_cast (this->SubAlg("ElasticFormFactorsModel")); - assert(fElFFModel); - fELFF.SetModel(fElFFModel); - - -} -//____________________________________________________________________________ -double MKFFEM::tau(const Interaction * interaction) const -{ -// computes q^2 / (4 * MNucl^2) - - //-- get kinematics & initial state parameters - const Kinematics & kinematics = interaction->Kine(); - // const InitialState & init_state = interaction->InitState(); - double q2 = kinematics.q2(); - - PDGLibrary * pdglib = PDGLibrary::Instance(); - double M = (pdglib->Find(kPdgProton)->Mass() + pdglib->Find(kPdgNeutron)->Mass())/2; - - //-- calculate q^2 / (4*Mnuc^2) - return q2/(4*M*M); -} -//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/MKFFEM.h b/src/Physics/QuasiElastic/XSection/MKFFEM.h deleted file mode 100644 index 9e65d43f04..0000000000 --- a/src/Physics/QuasiElastic/XSection/MKFFEM.h +++ /dev/null @@ -1,69 +0,0 @@ -//____________________________________________________________________________ -/*! - -\class genie::MKFFEM - -\brief Electromagnetic form factors for MK SPP model - - -\author Igor Kakorin , Joint Institute for Nuclear Research \n - based on code of - Costas Andreopoulos - University of Liverpool & STFC Rutherford Appleton Lab - -\created Nov 12, 2019 - -\cpright Copyright (c) 2003-2019, The GENIE Collaboration - For the full text of the license visit http://copyright.genie-mc.org - or see $GENIE/LICENSE -*/ -//____________________________________________________________________________ - -#ifndef _MK_EM_FORM_FACTOR_MODEL_H_ -#define _MK_EM_FORM_FACTOR_MODEL_H_ - -#include "Physics/QuasiElastic/XSection/QELFormFactorsModelI.h" -#include "Physics/QuasiElastic/XSection/ELFormFactors.h" - -namespace genie { - -class ELFormFactorsModelI; - -class MKFFEM : public QELFormFactorsModelI { - -public: - MKFFEM(); - MKFFEM(string name); - ~MKFFEM(); - - double F1V (const Interaction * interaction) const; - double xiF2V (const Interaction * interaction) const; - double FA (const Interaction * interaction) const; - double Fp (const Interaction * interaction) const; - - // Overload the Algorithm::Configure() methods to load private data - // members from configuration options - void Configure(const Registry & config); - void Configure(string config); - -private: - - void LoadConfig (void); - - double tau (const Interaction * interaction) const; - - double F1P (const Interaction * interaction) const; - double F2P (const Interaction * interaction) const; - double F1N (const Interaction * interaction) const; - double F2N (const Interaction * interaction) const; - - const ELFormFactorsModelI * fElFFModel; - - mutable ELFormFactors fELFF; - -}; - -} // genie namespace - -#endif - diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index afe33592fe..b47367bba2 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -13,7 +13,6 @@ #include #include #include -#include #include "Framework/Algorithm/AlgConfigPool.h" #include "Physics/XSectionIntegration/XSecIntegratorI.h" @@ -48,6 +47,7 @@ using namespace genie; using namespace genie::constants; using namespace genie::controls; using namespace genie::utils; +using namespace std::complex_literals; //____________________________________________________________________________ NievesQELCCPXSec::NievesQELCCPXSec() : @@ -403,6 +403,9 @@ void NievesQELCCPXSec::LoadConfig(void) double thc; GetParam( "CabibboAngle", thc ) ; fCos8c2 = TMath::Power(TMath::Cos(thc), 2); + + // Do precise calculation of lepton polarization + GetParamDef( "PreciseLeptonPol", fIsPreciseLeptonPolarization, false ) ; // Cross section scaling factor GetParam( "QEL-CC-XSecScale", fXSecCCScale ) ; @@ -797,18 +800,17 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, TMath::Power(qcmp,3)/srotp*(m+TMath::Sqrt(m2+TMath::Power(qcmp,2)))/mpi2; } //}//End if statement - const std::complex iNum(0,1.0); std::complex z(md/(q_mod*k_fermi)*(q_zero-q_mod2/(2.0*md) - -wr +iNum*gamma/2.0)); + -wr +1i*gamma/2.0)); std::complex zp(md/(q_mod*k_fermi)*(-q_zero-q_mod2/(2.0*md) - -wr +iNum*gammap/2.0)); + -wr +1i*gammap/2.0)); std::complex pzeta(0.0); if(abs(z) > 50.0){ pzeta = 2.0/(3.0*z)+2.0/(15.0*z*z*z); }else if(abs(z) < TMath::Power(10.0,-2)){ - pzeta = 2.0*z-2.0/3.0*z*z*z-iNum*kPi/2.0*(1.0-z*z); + pzeta = 2.0*z-2.0/3.0*z*z*z-1i*kPi/2.0*(1.0-z*z); }else{ pzeta = z + (1.0-z*z) * log((z+1.0)/(z-1.0))/2.0; } @@ -817,7 +819,7 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, if(abs(zp) > 50.0){ pzetap = 2.0/(3.0*zp)+2.0/(15.0*zp*zp*zp); }else if(abs(zp) < TMath::Power(10.0,-2)){ - pzetap = 2.0*zp-2.0/3.0*zp*zp*zp-iNum*kPi/2.0*(1.0-zp*zp); + pzetap = 2.0*zp-2.0/3.0*zp*zp*zp-1i*kPi/2.0*(1.0-zp*zp); }else{ pzetap = zp+ (1.0-zp*zp) * log((zp+1.0)/(zp-1.0))/2.0; } @@ -888,35 +890,9 @@ double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const{ } } //____________________________________________________________________________ -int NievesQELCCPXSec::leviCivita(int input[]) const{ - int copy[4] = {input[0],input[1],input[2],input[3]}; - int permutations = 0; - int temp; - - for(int i=0;i<4;i++){ - for(int j=i+1;j<4;j++){ - //If any two elements are equal return 0 - if(input[i] == input[j]) - return 0; - //If a larger number is before a smaller one, use permutations - //(exchanges of two adjacent elements) to move the smaller element - //so it is before the larger element, eg 2341->2314->2134->1234 - if(copy[i]>copy[j]){ - temp = copy[j]; - for(int k=j;k>i;k--){ - copy[k] = copy[k-1]; - permutations++; - } - copy[i] = temp; - } - } - } - - if(permutations % 2 == 0){ - return 1; - }else{ - return -1; - } +int NievesQELCCPXSec::leviCivita(int input[]) const +{ + return e(input[0], input[1], input[2], input[3]); } //____________________________________________________________________________ // Calculates the constraction of the leptonic and hadronic tensors. The @@ -964,7 +940,6 @@ const Target& target, bool assumeFreeNucleon) const // Calculate auxiliary parameters double M2 = TMath::Power(M, 2); double FA2 = TMath::Power(FA, 2); - double Fp2 = TMath::Power(Fp, 2); double F1V2 = TMath::Power(F1V, 2); double xiF2V2 = TMath::Power(xiF2V, 2); double q02 = TMath::Power(q[0], 2); @@ -979,7 +954,8 @@ const Target& target, bool assumeFreeNucleon) const if ( imU > kASmallNum ) return 0.; - + + if ( !fRPA || assumeFreeNucleon ) { CN = 1.0; CT = 1.0; @@ -1035,7 +1011,6 @@ const Target& target, bool assumeFreeNucleon) const //Additional constants and variables const int g[4][4] = {{1,0,0,0},{0,-1,0,0},{0,0,-1,0},{0,0,0,-1}}; - const std::complex iNum(0,1); int leviCivitaIndexArray[4]; double imaginaryPart = 0; @@ -1071,25 +1046,22 @@ const Target& target, bool assumeFreeNucleon) const } //real(Lmunu) is symmetric, and imag(Lmunu) is antisymmetric //std::complex num(g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu]+g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu],imaginaryPart); - Lmunu = g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu]+g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu] + iNum*imaginaryPart; - Lnumu = g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu]+g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu ]- iNum*imaginaryPart; + Lmunu = g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu]+g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu] + 1i*imaginaryPart; + Lnumu = g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu]+g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu ]- 1i*imaginaryPart; } // End Lmunu calculation - + double aux1 = 2*CL*Fp*(Fp*q2 + 4*FA*M); if(mu ==0 && nu == 0){ Amunu = 16.0*F1V2*(2.0*rulin[0][0]*CN+2.0*q[0]*tulin[0]+q2/2.0)+ 2.0*q2*xiF2V2* (4.0-4.0*rulin[0][0]/M2-4.0*q[0]*tulin[0]/M2-q02*(4.0/q2+1.0/M2)) + 4.0*FA2*(2.0*rulin[0][0]+2.0*q[0]*tulin[0]+(q2/2.0-2.0*M2))- - (2.0*CL*Fp2*q2+8.0*FA*Fp*CL*M)*q02-16.0*F1V*xiF2V*(-q2+q02)*CN; + aux1*q02-16.0*F1V*xiF2V*(-q2+q02)*CN; a00 = real(Amunu); // TESTING CODE sum += Lmunu*Amunu; }else if(mu == 0 && nu == 3){ Amunu = 16.0*F1V2*((2.0*rulin[0][3]+tulin[0]*dq)*CN+tulin[3]*q[0])+ - 2.0*q2*xiF2V2* - (-4.0*rulin[0][3]/M2-2.0*(dq*tulin[0]+q[0]*tulin[3])/M2-dq*q[0]*(4.0/q2+1.0/M2))+ - 4.0*FA2*((2.0*rulin[0][3]+dq*tulin[0])*CL+q[0]*tulin[3])- - (2.0*CL*Fp2*q2+8.0*FA*Fp*CL*M)*dq*q[0]- - 16.0*F1V*xiF2V*dq*q[0]; + -4.0*q2*xiF2V2*(2.0*rulin[0][3]/M2+(dq*tulin[0]+q[0]*tulin[3])/M2+dq*q[0]*(2.0/q2+0.5/M2))+ + 4.0*FA2*((2.0*rulin[0][3]+dq*tulin[0])*CL+q[0]*tulin[3])-dq*q[0]*(aux1+16.0*F1V*xiF2V); a0z= real(Amunu); // TESTING CODE Anumu = Amunu; sum += Lmunu*Anumu + Lnumu*Amunu; @@ -1097,8 +1069,7 @@ const Target& target, bool assumeFreeNucleon) const Amunu = 16.0*F1V2*(2.0*rulin[3][3]+2.0*dq*tulin[3]-q2/2.0)+ 2.0*q2*xiF2V2*(-4.0-4.0*rulin[3][3]/M2-4.0*dq*tulin[3]/M2-dq2*(4.0/q2+1.0/M2))+ 4.0*FA2*(2.0*rulin[3][3]+2.0*dq*tulin[3]-(q2/2.0-2.0*CL*M2))- - (2.0*CL*Fp2*q2+8.0*FA*Fp*CL*M)*dq2- - 16.0*F1V*xiF2V*(q2+dq2); + aux1*dq2-16.0*F1V*xiF2V*q02; azz = real(Amunu); // TESTING CODE sum += Lmunu*Amunu; }else if(mu ==1 && nu == 1){ @@ -1117,7 +1088,7 @@ const Target& target, bool assumeFreeNucleon) const 16.0*F1V*xiF2V*CT*q2; sum += Lmunu*Amunu; }else if(mu ==1 && nu == 2){ - Amunu = sign*16.0*iNum*FA*(xiF2V+F1V)*(-dq*tulin[0]*CT + q[0]*tulin[3]); + Amunu = sign*16.0*1i*FA*(xiF2V+F1V)*(-dq*tulin[0]*CT + q[0]*tulin[3]); Anumu = -Amunu; // Im(A) is antisymmetric axy = imag(Amunu); // TESTING CODE sum += Lmunu*Anumu+Lnumu*Amunu; @@ -1327,3 +1298,483 @@ void NievesQELCCPXSec::CompareNievesTensors(const Interaction* in) return; } // END TESTING CODE //____________________________________________________________________________ +const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const +{ + + if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + + // Get kinematics and init-state parameters + const Kinematics & kinematics = interaction -> Kine(); + const InitialState & init_state = interaction -> InitState(); + const Target & target = init_state.Tgt(); + + // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial + // struck nucleon + double Mi_onshell = target.HitNucMass(); + + // On-shell mass of final nucleon (from PDGLibrary) + double Mf = interaction->RecoilNucleon()->Mass(); + + // Isoscalar mass of nucleon + double M = (Mi_onshell + Mf)/2; + + // Note that GetProbeP4 defaults to returning the probe 4-momentum in the + // struck nucleon rest frame, so we have to explicitly ask for the lab frame + // here + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + TLorentzVector inNucleonMom(*init_state.TgtPtr()->HitNucP4Ptr()); + TLorentzVector inNucleonMomOnShell(inNucleonMom); + + TLorentzVector leptonMom = kinematics.FSLeptonP4(); + TLorentzVector outNucleonMom = kinematics.HadSystP4(); + + // Apply Pauli blocking if enabled + if ( fDoPauliBlocking && target.IsNucleus() && !interaction->TestBit(kIAssumeFreeNucleon) ) { + int final_nucleon_pdg = interaction->RecoilNucleonPdg(); + double kF = fPauliBlocker->GetFermiMomentum(target, final_nucleon_pdg, target.HitNucPosition()); + double pNf = outNucleonMom.P(); + if ( pNf < kF ) + { + LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + } + + double outNucleonEnergy = outNucleonMom.E(); + double inNucleonOnShellEnergy = TMath::Hypot(M, inNucleonMomOnShell.P() ); + outNucleonEnergy = TMath::Hypot(M, outNucleonMom.P() ); + inNucleonMomOnShell.SetE(inNucleonOnShellEnergy); + + // Calculate Coulomb corrections + double ml = interaction->FSPrimLepton()->Mass(); + double ml2 = ml*ml; + double plLocal = leptonMom.P(); + + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + int sign = is_neutrino ? 1 : -1; + double r = target.HitNucPosition(); + if ( fCoulomb ) + { + // Coulomb potential + double Vc = vcr(& target, r); + + // Outgoing lepton energy and momentum including Coulomb potential + double El = leptonMom.E(); + double ElLocal = El - sign*Vc; + + if ( ElLocal - ml <= 0. ) + { + LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // The Coulomb correction factor blows up as pl -> 0. To guard against + // unphysically huge corrections here, require that the lepton kinetic energy + // (at infinity) is larger than the magnitude of the Coulomb potential + // (should be around a few MeV) + double KEl = El - ml; + if ( KEl <= TMath::Abs(Vc) ) + { + LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // Local value of the lepton 3-momentum magnitude for the Coulomb correction + plLocal = TMath::Sqrt(ElLocal*ElLocal - ml2); + + } + + // When computing the contraction of the leptonic and hadronic tensors, + // we need to use an effective value of the 4-momentum transfer q. + // The energy transfer (q0) needs to be modified to account for the binding + // energy of the struck nucleon, while the 3-momentum transfer needs to + // be corrected for Coulomb effects. + // + // See the original Valencia model paper: + // https://journals.aps.org/prc/abstract/10.1103/PhysRevC.70.055503 + double q0Tilde = outNucleonEnergy - inNucleonMomOnShell.E(); + + // Shift the q0Tilde if required: + if( fQvalueShifter ) q0Tilde *= (1 + fQvalueShifter->Shift(*interaction) ) ; + + // If binding energy effects pull us into an unphysical region, return + // zero for the differential cross section + if ( q0Tilde <= 0 && target.IsNucleus() && !interaction->TestBit(kIAssumeFreeNucleon) ) + { + LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // Note that we're working in the lab frame (i.e., the rest frame + // of the target nucleus). We can therefore use Nieves' explicit + // form of the Amunu tensor if we rotate the 3-momenta so that + // qTilde is in the +z direction + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + TVector3 inNucleonMom3 = inNucleonMom.Vect(); + TVector3 outNucleonMom3 = outNucleonMom.Vect(); + + // If Coulomb corrections are being used, adjust the lepton 3-momentum used + // to get q3VecTilde so that its magnitude matches the local + // Coulomb-corrected value calculated earlier. Note that, although the + // treatment of Coulomb corrections by Nieves et al. doesn't change the + // direction of the lepton 3-momentum, it *does* change the direction of the + // 3-momentum transfer, and so the correction should be applied *before* + // rotating coordinates into a frame where q3VecTilde lies along the positive + // z axis. + TVector3 leptonMomCoulomb3 = !fCoulomb ? leptonMom3: plLocal*leptonMom3*(1/leptonMom3.Mag()); + TVector3 q3VecTilde = neutrinoMom3 - leptonMomCoulomb3; + + // Find the rotation angle needed to put q3VecTilde along z + TVector3 zvec(0, 0, 1); + TVector3 rot = ( q3VecTilde.Cross(zvec) ).Unit(); // Vector to rotate about + // Angle between the z direction and q + double angle = zvec.Angle( q3VecTilde ); + + // Handle the edge case where q3VecTilde is along -z, so the + // cross product above vanishes + if ( q3VecTilde.Perp() == 0. && q3VecTilde.Z() < 0. ) + { + rot = TVector3(0., 1., 0.); + angle = kPi; + } + + // Rotate if the rotation vector is not 0 + if ( rot.Mag() > 0 ) + { + neutrinoMom3.Rotate(angle,rot); + neutrinoMom.SetVect(neutrinoMom3); + leptonMom3.Rotate(angle,rot); + leptonMom.SetVect(leptonMom3); + inNucleonMom3.Rotate(angle,rot); + inNucleonMom.SetVect(inNucleonMom3); + inNucleonMomOnShell.SetVect(inNucleonMom3); + outNucleonMom3.Rotate(angle,rot); + outNucleonMom.SetVect(outNucleonMom3); + } + + // Calculate q and qTilde + TLorentzVector qP4 = neutrinoMom - leptonMom; + TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); + + double Q2 = -qP4.Mag2(); + double Q2tilde = -qTildeP4.Mag2(); + + // Check that Q2tilde > 0 (accounting for rounding errors) + if (Q2tilde < 0) + { + LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // Store Q2tilde in the kinematic variable representing Q2. + // This will ensure that the form factors are calculated correctly + // using the de Forest prescription (Q2tilde instead of Q2). + interaction->KinePtr()->SetQ2(Q2tilde); + // Calculate form factors + fFormFactors.Calculate( interaction ); + // Now that the form factors have been calculated, store Q2 + // in the event instead of Q2tilde + interaction->KinePtr()->SetQ2(Q2); + + bool tgtIsNucleus = target.IsNucleus(); + int tgt_pdgc = target.Pdg(); + int A = target.A(); + int Z = target.Z(); + int N = target.N(); + bool hitNucIsProton = pdg::IsProton( target.HitNucPdg() ); + + + // Get the QEL form factors (were calculated before this method was called) + double F1V = 0.5*fFormFactors.F1V(); + double xiF2V = 0.5*fFormFactors.xiF2V(); + double FA = fFormFactors.FA(); + // According to Nieves' paper, Fp = 2.0*M*FA/(kPionMass2-q2), but Llewelyn- + // Smith uses Fp = 2.0*M^2*FA/(kPionMass2-q2), so I divide by M + // This gives units of GeV^-1 + double Fp = fFormFactors.Fp()/M; + + + double t0,r00; + double CN(1), CT(1), CL(1), imU(0); + CNCTCLimUcalc(qTildeP4, M, r, is_neutrino, tgtIsNucleus, + tgt_pdgc, A, Z, N, hitNucIsProton, CN, CT, CL, imU, + t0, r00, interaction->TestBit( kIAssumeFreeNucleon )); + + if ( imU > 0 ) + { + LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + if ( !fRPA || interaction->TestBit( kIAssumeFreeNucleon ) ) { + CN = 1.0; + CT = 1.0; + CL = 1.0; + } + + // Calculate auxiliary parameters + // Off shell mass of initial nucleon + double M2 = M*M; + double FA2 = FA*FA; + double F1V2 = F1V*F1V; + double xiF2V2 = xiF2V*xiF2V; +// const double q[4] = {qTildeP4.E(),qTildeP4.Px(),qTildeP4.Py(),qTildeP4.Pz()}; + double q[4] = {qTildeP4.E(),qTildeP4.Px(),qTildeP4.Py(),qTildeP4.Pz()}; + double q0 = q[0]; + double dq = TMath::Sqrt(q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + double q02 = q0*q0; + double dq2 = dq*dq; + double q2 = q02 - dq2; + + double tulin[4], k[4], l[4], s[4], eskl[4]; + double rulin[4][4]; + std::complex jp[4], jm[4]; + + // For normal code execulation, tulin is the initial nucleon momentum + tulin[0] = inNucleonMomOnShell.E(); + tulin[1] = inNucleonMomOnShell.Px(); + tulin[2] = inNucleonMomOnShell.Py(); + tulin[3] = inNucleonMomOnShell.Pz(); + + + k[0] = neutrinoMom.E(); + k[1] = -neutrinoMom.Px(); + k[2] = -neutrinoMom.Py(); + k[3] = -neutrinoMom.Pz(); + + l[0] = leptonMom.E(); + l[1] = -leptonMom.Px(); + l[2] = -leptonMom.Py(); + l[3] = -leptonMom.Pz(); + + s[0] = leptonMom.P()/ml; + s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; + s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; + s[3] = -leptonMom.Vect().Unit().Z()*leptonMom.E()/ml; + + for (int a = 0; a < 4; a++) + { + eskl[a] = 0; + for (int b = 0; b < 4; b++) + { + if (b == a) continue; + for (int g = 0; g < 4; g++) + { + if (g == b || g == a) continue; + for (int d = 0; d < 4; d++) + { + if (d == g || d == b || d == a) continue; + double sb = s[b]*(b == 0?1:-1); + double kg = k[g]*(g == 0?1:-1); + double ld = l[d]*(d == 0?1:-1); + eskl[a] += e(a,b,g,d)*sb*kg*ld; + } + } + } + } + + double kl = neutrinoMom*leptonMom; + double ks = k[0]*s[0] - k[1]*s[1] - k[2]*s[2] - k[3]*s[3]; + + for(int i = 0; i < 4; i++) + for(int j = i; j < 4; j++) + rulin[i][j] = rulin[j][i] = tulin[i]*tulin[j]; + + for (int a = 0; a < 4; a++) + { + if (is_neutrino) + { + jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha + jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha + } + else + { + jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha + jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha + } + } + + //Additional constants and variables + std::complex Amunu, Anumu, LWpp(0, 0), LWpm(0, 0), LWmp(0, 0), LWmm(0, 0); + double aux1 = 2*CL*Fp*(Fp*q2 + 4*FA*M); + double aux2 = 8*(FA2 + 4*F1V2 - xiF2V2*q2/M2); + for(int mu = 0; mu < 4; mu++) + { + for(int nu = mu;nu < 4; nu++) + { + if (mu == 0 && nu == 0) + { + Amunu = 32*F1V2*(rulin[0][0]*CN + q[0]*tulin[0] + q2/4)+ + 8*q2*xiF2V2*(1 - rulin[0][0]/M2 - q[0]*tulin[0]/M2 - q02*(1/q2 + 1/4./M2)) + + 8*FA2*(rulin[0][0] + q[0]*tulin[0] + q2/4 - M2)-aux1*q02-16*F1V*xiF2V*(q02 - q2)*CN; + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + } + if (mu == 1 && nu == 1) + { + Amunu = 32*F1V2*(rulin[1][1] - q2/4)- + 8*q2*xiF2V2*(CT + rulin[1][1]/M2) + + 8*FA2*(rulin[1][1] + CT*M2 - q2/4)- + 16*F1V*xiF2V*CT*q2; + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + } + if (mu == 2 && nu == 2) + { + Amunu = 32*F1V2*(rulin[2][2] - q2/4)- + 8*q2*xiF2V2*(CT + rulin[2][2]/M2) + + 8*FA2*(rulin[2][2] + CT*M2 - q2/4)- + 16*F1V*xiF2V*CT*q2; + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + } + if (mu == 3 && nu == 3) + { + Amunu = 32*F1V2*(rulin[3][3] + dq*tulin[3] - q2/4)- + 8*q2*xiF2V2*(1 + rulin[3][3]/M2 + dq*tulin[3]/M2 + dq2*(1/q2 + 1/4./M2))+ + 8*FA2*(rulin[3][3] + dq*tulin[3] + CL*M2 - q2/4) - aux1*dq2 - 16*F1V*xiF2V*q02; + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + } + if (mu == 0 && nu == 1) + { + Amunu = aux2*(rulin[0][1] + tulin[1]*q[0]/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[2]*dq; + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + + Anumu = aux2*(rulin[0][1] + tulin[1]*q[0]/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[2]*dq; + LWpp += jp[nu]*std::conj(jp[mu])*Anumu; + LWpm += jp[nu]*std::conj(jm[mu])*Anumu; + LWmp += jm[nu]*std::conj(jp[mu])*Anumu; + LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + } + if (mu == 0 && nu == 2) + { + Amunu = aux2*(rulin[0][2] + tulin[2]*q[0]/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[1]*dq; + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + + Anumu = aux2*(rulin[0][2] + tulin[2]*q[0]/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[1]*dq; + LWpp += jp[nu]*std::conj(jp[mu])*Anumu; + LWpm += jp[nu]*std::conj(jm[mu])*Anumu; + LWmp += jm[nu]*std::conj(jp[mu])*Anumu; + LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + } + if (mu == 0 && nu == 3) + { + Amunu = 16*F1V2*((2*rulin[0][3] + tulin[0]*dq)*CN + tulin[3]*q[0])+ + -4*q2*xiF2V2*(2*rulin[0][3]/M2 + (dq*tulin[0] + q[0]*tulin[3])/M2 + dq*q[0]*(2/q2 + 0.5/M2))+ + 4*FA2*((2*rulin[0][3] + dq*tulin[0])*CL + q[0]*tulin[3]) - dq*q[0]*(aux1 + 16*F1V*xiF2V); + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + + Anumu = Amunu; + LWpp += jp[nu]*std::conj(jp[mu])*Anumu; + LWpm += jp[nu]*std::conj(jm[mu])*Anumu; + LWmp += jm[nu]*std::conj(jp[mu])*Anumu; + LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + } + if (mu == 1 && nu == 2) + { + Amunu = -1i*16.*FA*(xiF2V+F1V)*(q[0]*tulin[3] - dq*tulin[0]*CT) + 8.*rulin[1][2]*(FA2 + 4*F1V2 - xiF2V2*q2/M2); + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + + Anumu = 1i*16.*FA*(xiF2V+F1V)*(q[0]*tulin[3] - dq*tulin[0]*CT) + 8.*rulin[1][2]*(FA2 + 4*F1V2 - xiF2V2*q2/M2); + LWpp += jp[nu]*std::conj(jp[mu])*Anumu; + LWpm += jp[nu]*std::conj(jm[mu])*Anumu; + LWmp += jm[nu]*std::conj(jp[mu])*Anumu; + LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + } + if (mu == 1 && nu == 3) + { + Amunu = aux2*(rulin[1][3] + tulin[1]*dq/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[2]*q[0]; + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + + Anumu = aux2*(rulin[1][3] + tulin[1]*dq/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[2]*q[0]; + LWpp += jp[nu]*std::conj(jp[mu])*Anumu; + LWpm += jp[nu]*std::conj(jm[mu])*Anumu; + LWmp += jm[nu]*std::conj(jp[mu])*Anumu; + LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + } + + if (mu == 2 && nu == 3) + { + Amunu = aux2*(rulin[2][3] + tulin[2]*dq/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[1]*q[0]; + LWpp += jp[mu]*std::conj(jp[nu])*Amunu; + LWpm += jp[mu]*std::conj(jm[nu])*Amunu; + LWmp += jm[mu]*std::conj(jp[nu])*Amunu; + LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + + Anumu = aux2*(rulin[2][3] + tulin[2]*dq/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[1]*q[0]; + LWpp += jp[nu]*std::conj(jp[mu])*Anumu; + LWpm += jp[nu]*std::conj(jm[mu])*Anumu; + LWmp += jm[nu]*std::conj(jp[mu])*Anumu; + LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + } + } + } + + std::complex LWppmm = LWpp + LWmm; + std::complex rhopp = LWpp/LWppmm; + std::complex rhopm = LWpm/LWppmm; + std::complex rhomp = LWmp/LWppmm; + std::complex rhomm = LWmm/LWppmm; + double PL = std::real(rhopp - rhomm); + double PP = std::real(rhopm + rhomp); + double PT = std::imag(rhomp - rhopm); + + neutrinoMom3 = neutrinoMom.Vect(); + leptonMom3 = leptonMom.Vect(); + TVector3 Pz = leptonMom3.Unit(); + TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); + TVector3 Py = Pz.Cross(Px); + TVector3 pol = PT*Px + PP*Py + PL*Pz; + fFinalLeptonPolarization = pol; + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << "PL = " << PL << ", PT = " << PT << ", PP = " << PP << "\n"; + std::cout << fFinalLeptonPolarization.Mag() << "\n"; + std::cout << "NV@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + return fFinalLeptonPolarization; +} +//____________________________________________________________________________ +inline int NievesQELCCPXSec::g(int a, int b) const +{ + return (a==b)*(2*(a==0) - 1); +} +//____________________________________________________________________________ +inline int NievesQELCCPXSec::e(int a, int b, int c, int d) const +{ + return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; +} +//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index b0707e0db9..e16132df15 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -7,7 +7,7 @@ with RPA corrections Is a concrete implementation of the XSecAlgorithmI interface. \n -\ref Physical Review C 70, 055503 (2004) +\ref 1. Physical Review C 70, 055503 (2004) \author Joe Johnston, University of Pittsburgh Steven Dytman, University of Pittsburgh @@ -56,6 +56,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double XSec (const Interaction * i, KinePhaseSpace_t k) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; + const TVector3 & FinalLeptonPolarization (const Interaction* i) const; // Override the Algorithm::Configure methods to load configuration // data to private data members @@ -144,6 +145,8 @@ class NievesQELCCPXSec : public XSecAlgorithmI { //-1 if input is an odd permutation of 0123, and 0 if any two elements //are equal int leviCivita(int input[]) const; + int e(int a, int b, int c, int d) const; + int g(int a, int b) const; double LmunuAnumu(const TLorentzVector neutrinoMom, const TLorentzVector inNucleonMom, const TLorentzVector leptonMom, diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index e30dd52167..95f9864997 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -55,18 +55,18 @@ using std::ostringstream; SmithMonizQELCCPXSec::SmithMonizQELCCPXSec() : XSecAlgorithmI("genie::SmithMonizQELCCPXSec") { - + InitGaussIntArrays(); } //____________________________________________________________________________ SmithMonizQELCCPXSec::SmithMonizQELCCPXSec(string config) : XSecAlgorithmI("genie::SmithMonizQELCCPXSec", config) { - + InitGaussIntArrays(); } //____________________________________________________________________________ SmithMonizQELCCPXSec::~SmithMonizQELCCPXSec() { - + InitGaussIntArrays(); } //____________________________________________________________________________ double SmithMonizQELCCPXSec::XSec( @@ -174,6 +174,9 @@ void SmithMonizQELCCPXSec::LoadConfig(void) // Cross section scaling factor GetParamDef( "QEL-CC-XSecScale", fXSecScale, 1. ) ; + + // Do precise calculation of lepton polarization + GetParamDef( "PreciseLeptonPol", fIsPreciseLeptonPolarization, false ) ; double Vud; GetParam( "CKM-Vud", Vud ) ; @@ -210,16 +213,11 @@ double SmithMonizQELCCPXSec::d3sQES_dQ2dvdkF_SM(const Interaction * interaction) double v = kinematics.GetKV(kKVv); double kF = kinematics.GetKV(kKVPn); double kkF = kF*kF; - int nucl_pdg_ini = target.HitNucPdg(); - int nucl_pdg_fin = genie::pdg::SwitchProtonNeutron(nucl_pdg_ini); - PDGLibrary * pdglib = PDGLibrary::Instance(); - TParticlePDG * nucl_fin = pdglib->Find( nucl_pdg_fin ); - double E_BIN = sm_utils->GetBindingEnergy(); double m_ini = target.HitNucMass(); double mm_ini = m_ini*m_ini; - double m_fin = nucl_fin -> Mass(); // Mass of final hadron or hadron system (GeV) + double m_fin = interaction->RecoilNucleon()->Mass(); // Mass of final hadron or hadron system (GeV) double mm_fin = m_fin*m_fin; double m_tar = target.Mass(); // Mass of target nucleus (GeV) double mm_tar = m_tar*m_tar; @@ -238,7 +236,7 @@ double SmithMonizQELCCPXSec::d3sQES_dQ2dvdkF_SM(const Interaction * interaction) return 0.0; } - double pF = TMath::Sqrt(kkF+(2*kF*qv)*cosT_p+qqv); + double pF = TMath::Sqrt(kkF + 2*kF*qv*cosT_p + qqv); double E_lep = E_nu-v; double m_lep = interaction->FSPrimLepton()->Mass(); @@ -247,35 +245,35 @@ double SmithMonizQELCCPXSec::d3sQES_dQ2dvdkF_SM(const Interaction * interaction) { return 0.0; } - double P_lep = TMath::Sqrt(E_lep*E_lep-mm_lep); - double k6 = (Q2+mm_lep)/(2*E_nu); - double cosT_lep= (E_lep-k6)/P_lep; + double P_lep = TMath::Sqrt(E_lep*E_lep - mm_lep); + double k6 = (Q2 + mm_lep)/(2*E_nu); + double cosT_lep= (E_lep - k6)/P_lep; if (cosT_lep < -1.0 || cosT_lep > 1.0 ) return 0.0; - double cosT_k = (v+k6)/qv; + double cosT_k = (v + k6)/qv; if (cosT_k < -1.0 || cosT_k > 1.0 ) return 0.0; - double b2_flux = (E_p-kF*cosT_k*cosT_p)*(E_p-kF*cosT_k*cosT_p); - double c2_flux = kkF*(1-cosT_p*cosT_p)*(1-cosT_k*cosT_k); - - double k1 = fVud2*kNucleonMass2*kPi; + double b2_flux = TMath::Sq(E_p - kF*cosT_k*cosT_p); + double c2_flux = kkF*(1 - cosT_p*cosT_p)*(1 - cosT_k*cosT_k); + + double k1 = fVud2*mm_ini*kPi; double k2 = mm_lep/(2*mm_tar); double k7 = P_lep*cosT_lep; double P_Fermi = sm_utils->GetFermiMomentum(); - double FV_SM = 4.0*TMath::Pi()/3*TMath::Power(P_Fermi, 3); + double FV_SM = 4.0*kPi/3*TMath::Power(P_Fermi, 3); double factor = k1*(m_tar*kF/(FV_SM*qv*TMath::Sqrt(b2_flux-c2_flux)))*SmithMonizUtils::rho(P_Fermi, 0.0, kF)*(1-SmithMonizUtils::rho(P_Fermi, 0.01, pF)); - double a2 = kkF/kNucleonMass2; + double a2 = kkF/mm_ini; double a3 = a2*cosT_p*cosT_p; - double a6 = kF*cosT_p/kNucleonMass; - double a7 = E_p/kNucleonMass; + double a6 = kF*cosT_p/m_ini; + double a7 = E_p/m_ini; double a4 = a7*a7; double a5 = 2*a7*a6; double k3 = v/qv; double k4 = (3*a3-a2)/qqv; - double k5 = (a7-a6*k3)*m_tar/kNucleonMass; + double k5 = (a7-a6*k3)*m_tar/m_ini; // Calculate the QEL form factors fFormFactors.Calculate(interaction); @@ -287,17 +285,17 @@ double SmithMonizQELCCPXSec::d3sQES_dQ2dvdkF_SM(const Interaction * interaction) double FF_M = F_M*F_M; double FF_A = F_A*F_A; - double t = Q2/(4*kNucleonMass2); + double t = Q2/(4*mm_ini); double W_1 = FF_A*(1+t)+t*(F_V+F_M)*(F_V+F_M); //Ref.[1], \tilde{T}_1 double W_2 = FF_A+FF_V+t*FF_M; //Ref.[1], \tilde{T}_2 double W_3 =-2*F_A*(F_V+F_M); //Ref.[1], \tilde{T}_8 double W_4 =-0.5*F_V*F_M-F_A*F_P+t*F_P*F_P-0.25*(1-t)*FF_M; //Ref.[1], \tilde{T}_\alpha - double W_5 = FF_V+t*FF_M+FF_A; - + double W_5 = W_2; + double T_1 = 1.0*W_1+(a2-a3)*0.5*W_2; //Ref.[1], W_1 double T_2 = ((a2-a3)*Q2/(2*qqv)+a4-k3*(a5-k3*a3))*W_2; //Ref.[1], W_2 double T_3 = k5*W_3; //Ref.[1], W_8 - double T_4 = mm_tar*(0.5*W_2*k4+1.0*W_4/kNucleonMass2+a6*W_5/(kNucleonMass*qv)); //Ref.[1], W_\alpha + double T_4 = mm_tar*(0.5*W_2*k4+1.0*W_4/mm_ini+a6*W_5/(m_ini*qv)); //Ref.[1], W_\alpha double T_5 = k5*W_5+m_tar*(a5/qv-v*k4)*W_2; double xsec = kGF2*factor*((E_lep-k7)*(T_1+k2*T_4)/m_tar+(E_lep+k7)*T_2/(2*m_tar) @@ -326,68 +324,16 @@ double SmithMonizQELCCPXSec::d2sQES_dQ2dv_SM(const Interaction * interaction) co const Target & target = init_state.Tgt(); - - -// Gaussian quadratures integrate over Fermi momentum - double R[48]= { 0.16276744849602969579e-1,0.48812985136049731112e-1, - 0.81297495464425558994e-1,1.13695850110665920911e-1, - 1.45973714654896941989e-1,1.78096882367618602759e-1, - 2.10031310460567203603e-1,2.41743156163840012328e-1, - 2.73198812591049141487e-1,3.04364944354496353024e-1, - 3.35208522892625422616e-1,3.65696861472313635031e-1, - 3.95797649828908603285e-1,4.25478988407300545365e-1, - 4.54709422167743008636e-1,4.83457973920596359768e-1, - 5.11694177154667673586e-1,5.39388108324357436227e-1, - 5.66510418561397168404e-1,5.93032364777572080684e-1, - 6.18925840125468570386e-1,6.44163403784967106798e-1, - 6.68718310043916153953e-1,6.92564536642171561344e-1, - 7.15676812348967626225e-1,7.38030643744400132851e-1, - 7.59602341176647498703e-1,7.80369043867433217604e-1, - 8.00308744139140817229e-1,8.19400310737931675539e-1, - 8.37623511228187121494e-1,8.54959033434601455463e-1, - 8.71388505909296502874e-1,8.86894517402420416057e-1, - 9.01460635315852341319e-1,9.15071423120898074206e-1, - 9.27712456722308690965e-1,9.39370339752755216932e-1, - 9.50032717784437635756e-1,9.59688291448742539300e-1, - 9.68326828463264212174e-1,9.75939174585136466453e-1, - 9.82517263563014677447e-1,9.88054126329623799481e-1, - 9.92543900323762624572e-1,9.95981842987209290650e-1, - 9.98364375863181677724e-1,9.99689503883230766828e-1}; - - double W[48]= { 0.00796792065552012429e-1,0.01853960788946921732e-1, - 0.02910731817934946408e-1,0.03964554338444686674e-1, - 0.05014202742927517693e-1,0.06058545504235961683e-1, - 0.07096470791153865269e-1,0.08126876925698759217e-1, - 0.09148671230783386633e-1,0.10160770535008415758e-1, - 0.11162102099838498591e-1,0.12151604671088319635e-1, - 0.13128229566961572637e-1,0.14090941772314860916e-1, - 0.15038721026994938006e-1,0.15970562902562291381e-1, - 0.16885479864245172450e-1,0.17782502316045260838e-1, - 0.18660679627411467395e-1,0.19519081140145022410e-1, - 0.20356797154333324595e-1,0.21172939892191298988e-1, - 0.21966644438744349195e-1,0.22737069658329374001e-1, - 0.23483399085926219842e-1,0.24204841792364691282e-1, - 0.24900633222483610288e-1,0.25570036005349361499e-1, - 0.26212340735672413913e-1,0.26826866725591762198e-1, - 0.27412962726029242823e-1,0.27970007616848334440e-1, - 0.28497411065085385646e-1,0.28994614150555236543e-1, - 0.29461089958167905970e-1,0.29896344136328385984e-1, - 0.30299915420827593794e-1,0.30671376123669149014e-1, - 0.31010332586313837423e-1,0.31316425596861355813e-1, - 0.31589330770727168558e-1,0.31828758894411006535e-1, - 0.32034456231992663218e-1,0.32206204794030250669e-1, - 0.32343822568575928429e-1,0.32447163714064269364e-1, - 0.32516118713868835987e-1,0.32550614492363166242e-1}; - + int d = fR.size(); double Sum = 0; - for(int i = 0;i<48;i++) + for(int i = 0; i < d ;i++) { - double kF = 0.5*(-R[i]*(rkF.max-rkF.min)+rkF.min+rkF.max); + double kF = 0.5*(-fR[i]*(rkF.max-rkF.min)+rkF.min+rkF.max); kinematics->SetKV(kKVPn, kF); - Sum+=d3sQES_dQ2dvdkF_SM(interaction)*W[47-i]; - kF = 0.5*(R[i]*(rkF.max-rkF.min)+rkF.min+rkF.max); + Sum+=d3sQES_dQ2dvdkF_SM(interaction)*fW[d - 1 - i]; + kF = 0.5*(fR[i]*(rkF.max-rkF.min)+rkF.min+rkF.max); kinematics->SetKV(kKVPn, kF); - Sum+=d3sQES_dQ2dvdkF_SM(interaction)*W[47-i]; + Sum+=d3sQES_dQ2dvdkF_SM(interaction)*fW[d - 1 - i]; } double xsec = 0.5*Sum*(rkF.max-rkF.min); @@ -482,7 +428,6 @@ double SmithMonizQELCCPXSec::dsQES_dQ2_SM(const Interaction * interaction) const const double mp2 = kProtonMass2; const double mn2 = kNeutronMass2; const double Ee = E + ( (q2 - mn2 + mp2) / 2.0 / mp ); - assert(Ee > 0.0); // must be non-zero and positive rc = 6.0 + (1.5 * TMath::Log(kProtonMass / 2.0 / Ee)); rc += 1.2 * TMath::Power((kElectronMass / Ee), 1.5); rc *= kAem / kPi; @@ -492,3 +437,247 @@ double SmithMonizQELCCPXSec::dsQES_dQ2_SM(const Interaction * interaction) const xsec *= rc; return xsec; } +//____________________________________________________________________________ + void SmithMonizQELCCPXSec::InitGaussIntArrays(void) + { + // Gaussian quadratures integrate over Fermi momentum + fR = { 0.16276744849602969579e-1,0.48812985136049731112e-1, + 0.81297495464425558994e-1,1.13695850110665920911e-1, + 1.45973714654896941989e-1,1.78096882367618602759e-1, + 2.10031310460567203603e-1,2.41743156163840012328e-1, + 2.73198812591049141487e-1,3.04364944354496353024e-1, + 3.35208522892625422616e-1,3.65696861472313635031e-1, + 3.95797649828908603285e-1,4.25478988407300545365e-1, + 4.54709422167743008636e-1,4.83457973920596359768e-1, + 5.11694177154667673586e-1,5.39388108324357436227e-1, + 5.66510418561397168404e-1,5.93032364777572080684e-1, + 6.18925840125468570386e-1,6.44163403784967106798e-1, + 6.68718310043916153953e-1,6.92564536642171561344e-1, + 7.15676812348967626225e-1,7.38030643744400132851e-1, + 7.59602341176647498703e-1,7.80369043867433217604e-1, + 8.00308744139140817229e-1,8.19400310737931675539e-1, + 8.37623511228187121494e-1,8.54959033434601455463e-1, + 8.71388505909296502874e-1,8.86894517402420416057e-1, + 9.01460635315852341319e-1,9.15071423120898074206e-1, + 9.27712456722308690965e-1,9.39370339752755216932e-1, + 9.50032717784437635756e-1,9.59688291448742539300e-1, + 9.68326828463264212174e-1,9.75939174585136466453e-1, + 9.82517263563014677447e-1,9.88054126329623799481e-1, + 9.92543900323762624572e-1,9.95981842987209290650e-1, + 9.98364375863181677724e-1,9.99689503883230766828e-1}; + + fW = { 0.00796792065552012429e-1,0.01853960788946921732e-1, + 0.02910731817934946408e-1,0.03964554338444686674e-1, + 0.05014202742927517693e-1,0.06058545504235961683e-1, + 0.07096470791153865269e-1,0.08126876925698759217e-1, + 0.09148671230783386633e-1,0.10160770535008415758e-1, + 0.11162102099838498591e-1,0.12151604671088319635e-1, + 0.13128229566961572637e-1,0.14090941772314860916e-1, + 0.15038721026994938006e-1,0.15970562902562291381e-1, + 0.16885479864245172450e-1,0.17782502316045260838e-1, + 0.18660679627411467395e-1,0.19519081140145022410e-1, + 0.20356797154333324595e-1,0.21172939892191298988e-1, + 0.21966644438744349195e-1,0.22737069658329374001e-1, + 0.23483399085926219842e-1,0.24204841792364691282e-1, + 0.24900633222483610288e-1,0.25570036005349361499e-1, + 0.26212340735672413913e-1,0.26826866725591762198e-1, + 0.27412962726029242823e-1,0.27970007616848334440e-1, + 0.28497411065085385646e-1,0.28994614150555236543e-1, + 0.29461089958167905970e-1,0.29896344136328385984e-1, + 0.30299915420827593794e-1,0.30671376123669149014e-1, + 0.31010332586313837423e-1,0.31316425596861355813e-1, + 0.31589330770727168558e-1,0.31828758894411006535e-1, + 0.32034456231992663218e-1,0.32206204794030250669e-1, + 0.32343822568575928429e-1,0.32447163714064269364e-1, + 0.32516118713868835987e-1,0.32550614492363166242e-1}; + } +//____________________________________________________________________________ +const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const +{ + if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + // Assuming that variables Enu, Q2, \nu and kF are within allowable kinematic region + // which are specified in methods: genie::utils::gsl::d2Xsec_dQ2dv::DoEval and QELEventGeneratorSM::ProcessEventRecord + // Get kinematics & init-state parameters + const Kinematics & kinematics = interaction -> Kine(); + sm_utils->SetInteraction(interaction); + const InitialState & init_state = interaction -> InitState(); + const Target & target = init_state.Tgt(); + double Enu = init_state.ProbeE(kRfLab); + double Q2 = kinematics.Q2(true); + double v = kinematics.GetKV(kKVv); + Range1D_t rkF = sm_utils->kFQES_SM_lim(Q2,v); + + + double E_BIN = sm_utils->GetBindingEnergy(); + double m_ini = target.HitNucMass(); + double mm_ini = m_ini*m_ini; + double m_fin = interaction->RecoilNucleon()->Mass(); // Mass of final hadron or hadron system (GeV) + double mm_fin = m_fin*m_fin; + double m_tar = target.Mass(); // Mass of target nucleus (GeV) + + //|\vec{q}| + double qqv = v*v + Q2; + double qv = TMath::Sqrt(qqv); + + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + int sign = (is_neutrino) ? +1 : -1; + + double El = Enu - v; + double ml = interaction->FSPrimLepton()->Mass(); + double ml2 = ml*ml; + if (El < ml) + { + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + double Pl = TMath::Sqrt(El*El - ml2); + double k6 = (Q2 + ml2)/(2*Enu); + double cos_theta = (El - k6)/Pl; + if (cos_theta < -1.0 || cos_theta > 1.0 ) + { + LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + double sin_theta = TMath::Sqrt(1 - cos_theta*cos_theta); + // cos^2(theta/2) + double cs2th = (1 + cos_theta)/2; + // sin^2(theta/2) + double sn2th = (1 - cos_theta)/2; + + double cosT_k = (v + k6)/qv; + if (cosT_k < -1.0 || cosT_k > 1.0 ) + { + LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + double P_Fermi = sm_utils->GetFermiMomentum(); + + int d = fR.size(); + double a1(0), a2(0), a3(0), a4(0), a5(0), a6(0), a7(0); + double Tf(0.01); + if (rkF.max > 0) + { + for(int i = 0; i < d ;i++) + { + double kF = 0.5*(-fR[i]*(rkF.max - rkF.min) + rkF.min + rkF.max); + double kkF = kF*kF; + double E_p = TMath::Sqrt(mm_ini + kkF) - E_BIN; + double cosT_p = ((v - E_BIN)*(2*E_p + v + E_BIN) - qqv + mm_ini - mm_fin)/(2*kF*qv); //\cos\theta_p + if (cosT_p < -1.0 || cosT_p > 1.0 ) + { + LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + double pF = TMath::Sqrt(kkF + 2*kF*qv*cosT_p + qqv); + double b2_flux = TMath::Sq(E_p - kF*cosT_k*cosT_p); + double c2_flux = kkF*(1 - cosT_p*cosT_p)*(1 - cosT_k*cosT_k); + // factor fVud2*mm_ini*kPi*m_tar/qv/FV_SM will be cancelled when dividing by R + double factor = kF/TMath::Sqrt(b2_flux - c2_flux)*SmithMonizUtils::rho(P_Fermi, 0, kF)*(1 - SmithMonizUtils::rho(P_Fermi, Tf, pF))*fW[d - 1 - i]; + a1 += factor; + a2 += factor*kkF/mm_ini; + a3 += factor*kkF*cosT_p*cosT_p/mm_ini; + a4 += factor*E_p*E_p/mm_ini; + a5 += factor*2*E_p*kF*cosT_p/mm_ini; + a6 += factor*kF*cosT_p/m_ini; + a7 += factor*E_p/m_ini; + + kF = 0.5*(fR[i]*(rkF.max - rkF.min) + rkF.min + rkF.max); + kkF = kF*kF; + E_p = TMath::Sqrt(mm_ini + kkF)-E_BIN; + cosT_p = ((v - E_BIN)*(2*E_p + v + E_BIN) - qqv + mm_ini - mm_fin)/(2*kF*qv); //\cos\theta_p + if (cosT_p < -1.0 || cosT_p > 1.0 ) + { + LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + pF = TMath::Sqrt(kkF + 2*kF*qv*cosT_p + qqv); + b2_flux = TMath::Sq(E_p - kF*cosT_k*cosT_p); + c2_flux = kkF*(1 - cosT_p*cosT_p)*(1 - cosT_k*cosT_k); + // factor fVud2*mm_ini*kPi*m_tar/qv/FV_SM will be cancelled when dividing by R + factor = kF/TMath::Sqrt(b2_flux - c2_flux)*SmithMonizUtils::rho(P_Fermi, 0, kF)*(1 - SmithMonizUtils::rho(P_Fermi, Tf, pF))*fW[d - 1 - i]; + a1 += factor; + a2 += factor*kkF/mm_ini; + a3 += factor*kkF*cosT_p*cosT_p/mm_ini; + a4 += factor*E_p*E_p/mm_ini; + a5 += factor*2*E_p*kF*cosT_p/mm_ini; + a6 += factor*kF*cosT_p/m_ini; + a7 += factor*E_p/m_ini; + } + a1 *= 0.5*(rkF.max - rkF.min); + a2 *= 0.5*(rkF.max - rkF.min); + a3 *= 0.5*(rkF.max - rkF.min); + a4 *= 0.5*(rkF.max - rkF.min); + a5 *= 0.5*(rkF.max - rkF.min); + a6 *= 0.5*(rkF.max - rkF.min); + a7 *= 0.5*(rkF.max - rkF.min); + } + else + { + m_tar = m_ini; + a1 = a4 = a7 = 1; + } + double mm_tar = m_tar*m_tar; + double k3 = v/qv; + double k4 = (3*a3 - a2)/qqv; + double k5 = (a7 - a6*k3)*m_tar/m_ini; + + interaction->KinePtr()->SetQ2(Q2); + // Calculate the QEL form factors + fFormFactors.Calculate(interaction); + + double F_V = fFormFactors.F1V(); + double F_M = fFormFactors.xiF2V(); + double F_A = fFormFactors.FA(); + double F_P = fFormFactors.Fp(); + double FF_V = F_V*F_V; + double FF_M = F_M*F_M; + double FF_A = F_A*F_A; + + double t = Q2/(4*mm_ini); + double W1 = FF_A*(1+t)+t*(F_V+F_M)*(F_V+F_M); //Ref.[1], \tilde{T}_1 + double W2 = FF_A+FF_V+t*FF_M; //Ref.[1], \tilde{T}_2 + double W3 =-2*F_A*(F_V+F_M); //Ref.[1], \tilde{T}_8 + double W4 =-0.5*F_V*F_M-F_A*F_P+t*F_P*F_P-0.25*(1-t)*FF_M; //Ref.[1], \tilde{T}_\alpha + double W5 = W2; + + double T1 = a1*W1 + 0.5*(a2 - a3)*W2; //Ref.[1], W_1 + double T2 = ((a2 - a3)*Q2/(2*qqv) + a4 - k3*(a5 - k3*a3))*W2; //Ref.[1], W_2 + double T3 = k5*W3; //Ref.[1], W_8 + double T4 = mm_tar*(0.5*k4*W2 + a1*W4/mm_ini + a6*W5/m_ini/qv); //Ref.[1], W_\alpha + double T5 = m_tar*(a5/qv - v*k4)*W2 + k5*W5; + + double kappa = ml2/2/mm_tar; + double R = (El - Pl*cos_theta)/m_tar*(T1 + kappa*T4) + (El + Pl*cos_theta)/2/m_tar*T2 + + sign*((Enu + El)*(El - Pl*cos_theta)/2/mm_tar - kappa)*T3 - kappa*T5; //sign toghether with sign of FA ("-") will give correct total sign + + // In the frame, where lepton momentum is in z direction, x - axis is in production plane and orthogonal to z + // PL || z, PP || x, PT || y = 0 in Standard Model, because T6 = 0 + double PP = -sign*ml*sin_theta/2/m_tar/R*(T1*2 - T2 + T3*sign*Enu/m_tar - T4*ml2/mm_tar + T5*El/m_tar); + double PL = -sign*(1 - ml2/mm_tar/R*((T1*2*m_tar/(El + Pl) + T3*sign*(Enu - Pl)/(El + Pl))*cs2th + + (T2*m_tar/(El + Pl) + T4*(El + Pl)/m_tar - T5)*sn2th)); + + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + TVector3 Pz = leptonMom3.Unit(); + TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); + TVector3 Py = Pz.Cross(Px); + TVector3 pol = PP*Py + PL*Pz; + fFinalLeptonPolarization = PP*Py + PL*Pz; + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << fFinalLeptonPolarization.Mag() << "\n"; + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + return fFinalLeptonPolarization; + +} +//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h index 4817edd7c2..208e9aaac3 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h @@ -39,6 +39,8 @@ #ifndef _SMITH_MONITZ_QELCC_CROSS_SECTION_H_ #define _SMITH_MONITZ_QELCC_CROSS_SECTION_H_ +#include + #include "Framework/EventGen/XSecAlgorithmI.h" #include "Physics/QuasiElastic/XSection/QELFormFactors.h" #include "Physics/QuasiElastic/XSection/SmithMonizUtils.h" @@ -60,6 +62,7 @@ class SmithMonizQELCCPXSec : public XSecAlgorithmI { double XSec (const Interaction * i, KinePhaseSpace_t kps) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; + const TVector3 & FinalLeptonPolarization (const Interaction* i) const; // Override the Algorithm::Configure methods to load configuration // data to private data members @@ -73,12 +76,18 @@ class SmithMonizQELCCPXSec : public XSecAlgorithmI { double d3sQES_dQ2dvdkF_SM (const Interaction * interaction) const; double dsQES_dQ2_SM(const Interaction * interaction) const; double d2sQES_dQ2dv_SM(const Interaction * i) const; + void InitGaussIntArrays(void); double fXSecScale; ///< external xsec scaling factor mutable QELFormFactors fFormFactors; const QELFormFactorsModelI * fFormFactorsModel; const XSecIntegratorI * fXSecIntegrator; double fVud2; ///< |Vud|^2(square of magnitude ud-element of CKM-matrix) + + std::array fW; + std::array fR; + + }; diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx index 1d3aa04a0b..5ffcc4f392 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx @@ -32,6 +32,7 @@ using namespace genie; using namespace genie::constants; using namespace genie::utils; +using namespace std::complex_literals; //____________________________________________________________________________ PaisQELLambdaPXSec::PaisQELLambdaPXSec() : @@ -223,6 +224,9 @@ void PaisQELLambdaPXSec::LoadConfig(void) double thc ; GetParam( "CabibboAngle", thc ) ; fSin8c2 = TMath::Power(TMath::Sin(thc), 2); + + // Do precise calculation of lepton polarization + GetParamDef( "PreciseLeptonPol", fIsPreciseLeptonPolarization, false ) ; // load QEL form factors model fFormFactorsModel = dynamic_cast ( @@ -236,3 +240,210 @@ void PaisQELLambdaPXSec::LoadConfig(void) assert(fXSecIntegrator); } //____________________________________________________________________________ +const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* interaction) const +{ + if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + double ml = interaction->FSPrimLepton()->Mass(); + // First we need access to all of the particles in the interaction + // The particles were stored in the lab frame + //----- get kinematics & init state - compute auxiliary vars + const Kinematics & kinematics = interaction->Kine(); + const InitialState & init_state = interaction->InitState(); + const Target & target = init_state.Tgt(); + + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + + // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial + // struck nucleon + double Mnuc = target.HitNucMass(); + double Mnuc2 = Mnuc*Mnuc; + + // Note that GetProbeP4 defaults to returning the probe 4-momentum in the + // struck nucleon rest frame, so we have to explicitly ask for the lab frame + // here + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + TLorentzVector inNucleonMom(*init_state.TgtPtr()->HitNucP4Ptr()); + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + + // Ordinary 4-momentum transfer + TLorentzVector qP4 = neutrinoMom - leptonMom; + double Q2 = -qP4.Mag2(); + interaction->KinePtr()->SetQ2(Q2); + // Calculate the QEL form factors + fFormFactors.Calculate(interaction); + double F1V = fFormFactors.F1V(); + double xiF2V = fFormFactors.xiF2V(); + double FA = fFormFactors.FA(); + + //neutrino momentum transfer + double q2 = -Q2; + + //----- Calculate the differential cross section dxsec/dQ^2 + //resonance mass & nucleon mass + double Mi = Mnuc; + double Mf = (this)->MHyperon(interaction); + // calculate w coefficients + //start with Mass terms + double Mp = Mf + Mi; + double Mm = Mf - Mi; + double Mm2 = Mm*Mm; + double Mp2 = Mp*Mp; + double M = 0.5*Mp; + double M2 = M*M; + + //Powers of Form Factors + double FA2 = FA*FA; + + //Calculate W terms + double W1 = (Mm2 - q2)*TMath::Sq(F1V + xiF2V)/4/Mnuc2 + (Mp2 - q2)*FA2/4/Mnuc2; + double W2 = FA2 + TMath::Sq(F1V + xiF2V - Mp*xiF2V/2/Mnuc) - q2*xiF2V*xiF2V/4/Mnuc2; + double W3 = 2*FA*(F1V + xiF2V); + double W4(0), W5(0); + + + double p[4], q[4], epq[4][4], k[4], l[4], s[4], eskl[4]; + std::complex jp[4], jm[4]; + + p[0] = inNucleonMom.E(); + p[1] = inNucleonMom.Px(); + p[2] = inNucleonMom.Py(); + p[3] = inNucleonMom.Pz(); + + q[0] = qP4.E(); + q[1] = qP4.Px(); + q[2] = qP4.Py(); + q[3] = qP4.Pz(); + + k[0] = neutrinoMom.E(); + k[1] = -neutrinoMom.Px(); + k[2] = -neutrinoMom.Py(); + k[3] = -neutrinoMom.Pz(); + + l[0] = leptonMom.E(); + l[1] = -leptonMom.Px(); + l[2] = -leptonMom.Py(); + l[3] = -leptonMom.Pz(); + + s[0] = leptonMom.P()/ml; + s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; + s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; + s[3] = -leptonMom.Vect().Unit().Z()*leptonMom.E()/ml; + + // epsilon^\alpha\beta\gamma\delta p_\gamma q_\delta + for (int a = 0; a < 4; a++) + { + for (int b = 0; b < 4; b++) + { + epq[a][b] = 0; + if (b == a) continue; + for (int g = 0; g < 4; g++) + { + if (g == b || g == a) continue; + for (int d = 0; d < 4; d++) + { + if (d == g || d == b || d == a) continue; + epq[a][b] += e(a,b,g,d)*(a == 0?1:-1)*(b == 0?1:-1)*p[g]*q[d]; + } + } + } + } + + // epsilon_\alpha\beta\gamma\delta s^\beta k^\gamma l^\delta + for (int a = 0; a < 4; a++) + { + eskl[a] = 0; + for (int b = 0; b < 4; b++) + { + if (b == a) continue; + for (int g = 0; g < 4; g++) + { + if (g == b || g == a) continue; + for (int d = 0; d < 4; d++) + { + if (d == g || d == b || d == a) continue; + double sb = s[b]*(b == 0?1:-1); + double kg = k[g]*(g == 0?1:-1); + double ld = l[d]*(d == 0?1:-1); + eskl[a] += e(a,b,g,d)*sb*kg*ld; + } + } + } + } + + double kl = k[0]*l[0] - k[1]*l[1] - k[2]*l[2] - k[3]*l[3]; + double ks = k[0]*s[0] - k[1]*s[1] - k[2]*s[2] - k[3]*s[3]; + + for (int a = 0; a < 4; a++) + { + if (is_neutrino) + { + jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha + jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha + } + else + { + jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha + jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha + } + } + + //Additional constants and variables + std::complex Wmunu, Wnumu, LWpp(0, 0), LWpm(0, 0), LWmp(0, 0), LWmm(0, 0); + for(int mu = 0; mu < 4; mu++) + { + for(int nu = mu;nu < 4; nu++) + { + double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/M2 + q[mu]*q[nu]*W4/M2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/M2; + double Wimag = epq[mu][nu]*W3/2/M2; + Wmunu = Wreal - 1i*Wimag; // W^\mu\nu + LWpp += jp[mu]*std::conj(jp[nu])*Wmunu; // Lpp_\mu\nu*W^\mu\nu + LWpm += jp[mu]*std::conj(jm[nu])*Wmunu; // Lpm_\mu\nu*W^\mu\nu + LWmp += jm[mu]*std::conj(jp[nu])*Wmunu; // Lmp_\mu\nu*W^\mu\nu + LWmm += jm[mu]*std::conj(jm[nu])*Wmunu; // Lmm_\mu\nu*W^\mu\nu + if (mu != nu) + { + Wnumu = Wreal + 1i*Wimag; + LWpp += jp[nu]*std::conj(jp[mu])*Wnumu; // Lpp_\mu\nu*W^\mu\nu + LWpm += jp[nu]*std::conj(jm[mu])*Wnumu; // Lpm_\mu\nu*W^\mu\nu + LWmp += jm[nu]*std::conj(jp[mu])*Wnumu; // Lmp_\mu\nu*W^\mu\nu + LWmm += jm[nu]*std::conj(jm[mu])*Wnumu; // Lmm_\mu\nu*W^\mu\nu + } + } + } + std::complex LWppmm = LWpp + LWmm; + std::complex rhopp = LWpp/LWppmm; + std::complex rhopm = LWpm/LWppmm; + std::complex rhomp = LWmp/LWppmm; + std::complex rhomm = LWmm/LWppmm; + double PL = std::real(rhopp - rhomm); + double PP = std::real(rhopm + rhomp); + double PT = std::imag(rhomp - rhopm); + + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + TVector3 Pz = leptonMom3.Unit(); + TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); + TVector3 Py = Pz.Cross(Px); + TVector3 pol = PT*Px + PP*Py + PL*Pz; + fFinalLeptonPolarization = pol; + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << "PL = " << PL << ", PT = " << PT << ", PP = " << PP << "\n"; + std::cout << fFinalLeptonPolarization.Mag() << "\n"; + std::cout << "PL@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + return fFinalLeptonPolarization; +} +//____________________________________________________________________________ +inline int PaisQELLambdaPXSec::g(int a, int b) const +{ + return (a==b)*(2*(a==0) - 1); +} +//____________________________________________________________________________ +inline int PaisQELLambdaPXSec::e(int a, int b, int c, int d) const +{ + return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; +} +//____________________________________________________________________________ diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h index 392d11c128..5b3a5654c3 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h @@ -31,6 +31,8 @@ #include "Framework/EventGen/XSecAlgorithmI.h" #include "Physics/QuasiElastic/XSection/QELFormFactors.h" +#include + namespace genie { class QELFormFactorsModelI; @@ -48,6 +50,9 @@ class PaisQELLambdaPXSec : public XSecAlgorithmI { double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; bool ValidKinematics (const Interaction * i) const; + const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + int e(int a, int b, int c, int d) const; + int g(int a, int b) const; //-- override the Algorithm::Configure methods to load configuration // data to private data members From c5858b92727500b5330f68d8c58656bd515d6113 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 12 Dec 2024 15:45:54 +0300 Subject: [PATCH 06/78] get rid of unused factors --- .../XSection/LwlynSmithQELCCPXSec.cxx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index 8ca54a5f47..c57c58c708 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -599,12 +599,10 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio // Off shell mass of initial nucleon double Mi = inNucleonMom.M(); - double Mi2 = inNucleonMom.M2(); double M = (Mi + Mf)/2; double M2 = M*M; double r = (Mi - Mf)/2/M; double r2 = r*r; - double mr2 = Mi2/M2; double tau = Q2/4/M2; double w01 = (1 + tau)*FFAT + tau*FFVM; @@ -621,11 +619,11 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio double w25 = w22 - FP*FT; // common factor 2M^2V^2 will be cancelled in the calculation of rho - double W1 = (w01 + + w21*r2); - double W2 = (w02 + w12*r + w22*r2)*mr2; - double W3 = (w03 )*mr2; - double W4 = (w04 + w14*r + w24*r2)*mr2; - double W5 = (w05 + w15*r + w25*r2)*mr2; + double W1 = w01 + + w21*r2; + double W2 = w02 + w12*r + w22*r2; + double W3 = w03 ; + double W4 = w04 + w14*r + w24*r2; + double W5 = w05 + w15*r + w25*r2; double p[4], q[4], epq[4][4], k[4], l[4], s[4], eskl[4]; std::complex jp[4], jm[4]; @@ -720,8 +718,8 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio { for(int nu = mu;nu < 4; nu++) { - double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/Mi2 + q[mu]*q[nu]*W4/Mi2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/Mi2; - double Wimag = epq[mu][nu]*W3/2/Mi2; + double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/M2 + q[mu]*q[nu]*W4/M2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/M2; + double Wimag = epq[mu][nu]*W3/2/M2; Wmunu = Wreal - 1i*Wimag; // W^\mu\nu LWpp += jp[mu]*std::conj(jp[nu])*Wmunu; // Lpp_\mu\nu*W^\mu\nu LWpm += jp[mu]*std::conj(jm[nu])*Wmunu; // Lpm_\mu\nu*W^\mu\nu From 32ccea686dad52e81235ff6fac6084b995cdc425 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 19 Dec 2024 00:07:01 +0300 Subject: [PATCH 07/78] finish adding lepton polarization for QE --- config/SuSAv2QELPXSec.xml | 4 + .../EventGen/HybridXSecAlgorithm.cxx | 35 +- src/Framework/EventGen/HybridXSecAlgorithm.h | 3 +- .../XSection/LwlynSmithQELCCPXSec.h | 5 +- .../QuasiElastic/XSection/RosenbluthPXSec.cxx | 7 +- .../QuasiElastic/XSection/RosenbluthPXSec.h | 1 + .../QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 659 ++++++++++++++++++ .../QuasiElastic/XSection/SuSAv2QELPXSec.h | 7 +- 8 files changed, 705 insertions(+), 16 deletions(-) diff --git a/config/SuSAv2QELPXSec.xml b/config/SuSAv2QELPXSec.xml index 1e9c802183..9ac2d809ae 100644 --- a/config/SuSAv2QELPXSec.xml +++ b/config/SuSAv2QELPXSec.xml @@ -13,6 +13,8 @@ XSec-Integrator alg No QEL-CC-XSecScale double yes XSec Scaling factor for CC 1. QEL-NC-XSecScale double yes XSec Scaling factor for NC 1. QEL-EM-XSecScale double yes XSec Scaling factor for EM 1. +PreciseLeptonPol bool Yes Do precise calculation of No + lepton polarization FermiMomentumTable string No Table of Fermi momentum (kF) constants CommonParam[FermiGas] QvalueShifterAlg alg yes QValue shifter algo none ..................................................................................................... @@ -44,6 +46,8 @@ Name Type Optional Comment genie::MECXSec/Default + true + + genie::SmithMonizQELCCPXSec/Dipole + + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + + + + genie::SmithMonizQELCCPXSec/RunningMA + + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + diff --git a/src/Framework/EventGen/HybridXSecAlgorithm.cxx b/src/Framework/EventGen/HybridXSecAlgorithm.cxx index 6963465b2a..65dd30f464 100644 --- a/src/Framework/EventGen/HybridXSecAlgorithm.cxx +++ b/src/Framework/EventGen/HybridXSecAlgorithm.cxx @@ -87,10 +87,7 @@ double HybridXSecAlgorithm::XSec(const Interaction* interaction, // or kPSQELEvGen for LwlynSmithQELCCPXSec (2d phase spaces), // while RosenbluthPXSec uses kPSQ2fE (1d phase space) // and there is no way to transform 1d to 2d phase space. - if ( interaction->ProcInfo().IsEM() && - (interaction->InitState().Tgt().Pdg() == kPdgTgtFreeP || - interaction->InitState().Tgt().Pdg() == kPdgTgtFreeN) - ) + if ( alg_to_use->Id().Name() == "genie::RosenbluthPXSec") return alg_to_use->XSec( interaction, kPSQ2fE ); return alg_to_use->XSec( interaction, kps ); diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 95f9864997..1a01deb822 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -49,7 +49,6 @@ using namespace genie; using namespace genie::constants; using namespace genie::utils; -using std::ostringstream; //____________________________________________________________________________ SmithMonizQELCCPXSec::SmithMonizQELCCPXSec() : @@ -136,6 +135,8 @@ bool SmithMonizQELCCPXSec::ValidProcess(const Interaction * interaction) const const ProcessInfo & proc_info = interaction->ProcInfo(); if(!proc_info.IsQuasiElastic()) return false; + + if ( !init_state.Tgt().IsNucleus() ) return false; int nuc = init_state.Tgt().HitNucPdg(); int nu = init_state.ProbePdg(); @@ -145,7 +146,7 @@ bool SmithMonizQELCCPXSec::ValidProcess(const Interaction * interaction) const bool isnu = pdg::IsNeutrino(nu); bool isnub = pdg::IsAntiNeutrino(nu); - bool prcok = proc_info.IsWeakCC() && ((isP&&isnub) || (isN&&isnu)); + bool prcok = proc_info.IsWeakCC() && ((isP && isnub) || (isN && isnu)); if(!prcok) return false; return true; @@ -560,6 +561,7 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio double Tf(0.01); if (rkF.max > 0) { + // nuclear target for(int i = 0; i < d ;i++) { double kF = 0.5*(-fR[i]*(rkF.max - rkF.min) + rkF.min + rkF.max); @@ -618,6 +620,7 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio } else { + // nucleon target m_tar = m_ini; a1 = a4 = a7 = 1; } @@ -675,7 +678,7 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + std::cout << "SM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h index 208e9aaac3..d9403a38f9 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h @@ -73,9 +73,9 @@ class SmithMonizQELCCPXSec : public XSecAlgorithmI { mutable SmithMonizUtils * sm_utils; void LoadConfig (void); - double d3sQES_dQ2dvdkF_SM (const Interaction * interaction) const; double dsQES_dQ2_SM(const Interaction * interaction) const; - double d2sQES_dQ2dv_SM(const Interaction * i) const; + double d2sQES_dQ2dv_SM(const Interaction * interaction) const; + double d3sQES_dQ2dvdkF_SM (const Interaction * interaction) const; void InitGaussIntArrays(void); double fXSecScale; ///< external xsec scaling factor @@ -87,9 +87,6 @@ class SmithMonizQELCCPXSec : public XSecAlgorithmI { std::array fW; std::array fR; - - - }; diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index d59dcf0b8d..e9261b211a 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -680,6 +680,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int const Kinematics& kinematics = interaction -> Kine(); const InitialState& init_state = interaction -> InitState(); const Target& tgt = init_state.Tgt(); + int target_pdg = tgt.Pdg(); + int probe_pdg = interaction->InitState().ProbePdg(); bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); @@ -743,16 +745,12 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int // ****************************** // Now choose which tesor to use // ****************************** - - // Get the hadron tensor for the selected nuclide. Check the probe PDG code - // to use the tensor for CC neutrino scattering - int target_pdg = interaction->InitState().Tgt().Pdg(); - int probe_pdg = interaction->InitState().ProbePdg(); - int tensor_pdg_susa = target_pdg; int tensor_pdg_crpa = target_pdg; int A_request = pdg::IonPdgCodeToA(target_pdg); int Z_request = pdg::IonPdgCodeToZ(target_pdg); + bool need_to_scale_susa = false; + bool need_to_scale_crpa = false; // This gets a bit messy as the different models have different // targets available and currently only SuSA does EM @@ -925,11 +923,14 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int Eb_ten_susa = fEbC; Eb_ten_crpa = fEbO; } + + if (tensor_pdg_susa != target_pdg) need_to_scale_susa = true; + if (tensor_pdg_crpa != target_pdg) need_to_scale_crpa = true; - // Finally we can now get the tensors we need - const LabFrameHadronTensorI* tensor_susa; - const LabFrameHadronTensorI* tensor_crpa; - const LabFrameHadronTensorI* tensor_blen; + // Finally we can now get the tensors we need + const LabFrameHadronTensorI* tensor_susa; + const LabFrameHadronTensorI* tensor_crpa; + const LabFrameHadronTensorI* tensor_blen; if( modelConfig == kMd_SuSAv2 ) { @@ -1073,6 +1074,12 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W4_susa = tensor_susa->W4(Q0 - Delta_Q_value_susa, Q3, M); W5_susa = tensor_susa->W5(Q0 - Delta_Q_value_susa, Q3, M); // W6_susa = tensor_susa->W6(Q0 - Delta_Q_value_susa, Q3, M); + double fact_susa = XSecScaling(1.0, interaction, target_pdg, tensor_pdg_susa, need_to_scale_susa); + W1_susa *= fact_susa; + W2_susa *= fact_susa; + W3_susa *= fact_susa; + W4_susa *= fact_susa; + W5_susa *= fact_susa; } if ( modelConfig == kMd_CRPASuSAv2Hybrid || modelConfig == kMd_HFSuSAv2Hybrid || modelConfig == kMd_CRPAPWSuSAv2Hybrid || modelConfig == kMd_HFPWSuSAv2Hybrid || @@ -1084,6 +1091,20 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W4_blen = tensor_blen->W4(Q0 - Delta_Q_value_blen, Q3, M); W5_blen = tensor_blen->W5(Q0 - Delta_Q_value_blen, Q3, M); // W6_blen = tensor_blen->W6(Q0 - Delta_Q_value_blen, Q3, M); + // The blended SuSAv2 calculation already gives the xsec per atom + // For the A-scaling below to make sense we need to transform them to per active nucleon + int A_tensor = pdg::IonPdgCodeToA(tensor_pdg_crpa); + int Z_tensor = pdg::IonPdgCodeToZ(tensor_pdg_crpa); + int N_tensor = A_tensor-Z_tensor; + double fact_blen = 1.0; + if ( pdg::IsNeutrino(probe_pdg) ) fact_blen *= 1.0/N_tensor; + else if ( pdg::IsAntiNeutrino(probe_pdg) ) fact_blen *= 1.0/Z_tensor; + fact_blen = XSecScaling(fact_blen, interaction, target_pdg, tensor_pdg_crpa, need_to_scale_crpa); + W1_blen *= fact_blen; + W2_blen *= fact_blen; + W3_blen *= fact_blen; + W4_blen *= fact_blen; + W5_blen *= fact_blen; } if( modelConfig != kMd_SuSAv2 && modelConfig != kMd_SuSAv2Blend) { @@ -1093,6 +1114,20 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W4_crpa = tensor_crpa->W4(Q0 - Delta_Q_value_crpa, Q3, M); W5_crpa = tensor_crpa->W5(Q0 - Delta_Q_value_crpa, Q3, M); // W6_crpa = tensor_crpa->W6(Q0 - Delta_Q_value_crpa, Q3, M); + // The CRPA calculation already gives the xsec per atom + // For the A-scaling below to make sense we need to transform them to per active nucleon + int A_tensor = pdg::IonPdgCodeToA(tensor_pdg_crpa); + int Z_tensor = pdg::IonPdgCodeToZ(tensor_pdg_crpa); + int N_tensor = A_tensor-Z_tensor; + double fact_crpa = 1.0; + if ( pdg::IsNeutrino(probe_pdg) ) fact_crpa *= 1.0/N_tensor; + else if ( pdg::IsAntiNeutrino(probe_pdg) ) fact_crpa *= 1.0/Z_tensor; + fact_crpa = XSecScaling(fact_crpa, interaction, target_pdg, tensor_pdg_crpa, need_to_scale_crpa); + W1_crpa *= fact_crpa; + W2_crpa *= fact_crpa; + W3_crpa *= fact_crpa; + W4_crpa *= fact_crpa; + W5_crpa *= fact_crpa; } // Apply blending if needed From fffbd8047edcf0786c6caf0956efc254dc2c6e9c Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sat, 21 Dec 2024 00:59:57 +0300 Subject: [PATCH 09/78] add warning in XSecAlgorithm about EM-processes --- src/Framework/EventGen/XSecAlgorithmI.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Framework/EventGen/XSecAlgorithmI.cxx b/src/Framework/EventGen/XSecAlgorithmI.cxx index b7b540ef3f..7d168ecc60 100644 --- a/src/Framework/EventGen/XSecAlgorithmI.cxx +++ b/src/Framework/EventGen/XSecAlgorithmI.cxx @@ -63,6 +63,12 @@ bool XSecAlgorithmI::ValidKinematics(const Interaction* interaction) const //___________________________________________________________________________ const TVector3 & XSecAlgorithmI::FinalLeptonPolarization (const Interaction* i) const { + if ( i->ProcInfo().IsEM() ) + { + LOG("XSecBase", pWARN) << "For EM processes doesn't work yet. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } int pdg = i->FSPrimLeptonPdg(); if ( pdg::IsNeutrino(pdg) || pdg::IsElectron(pdg) || pdg::IsMuon(pdg) || pdg::IsTau(pdg) ) { From 1b4c5a86154b1bcbf3392f6b2ead85483450ed58 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Wed, 1 Jan 2025 16:26:03 +0300 Subject: [PATCH 10/78] refactore code --- config/NievesSimoVacasMECPXSec2016.xml | 5 + config/SuSAv2MECPXSec.xml | 3 + src/Physics/Common/PrimaryLeptonUtils.cxx | 227 +++++++++++ src/Physics/Common/PrimaryLeptonUtils.h | 103 +++++ .../Multinucleon/EventGen/MECGenerator.cxx | 8 +- .../XSection/NievesSimoVacasMECPXSec2016.cxx | 384 +++++++++++++++++- .../XSection/NievesSimoVacasMECPXSec2016.h | 1 + .../Multinucleon/XSection/SuSAv2MECPXSec.cxx | 133 +++++- .../Multinucleon/XSection/SuSAv2MECPXSec.h | 2 + .../XSection/LwlynSmithQELCCPXSec.cxx | 153 +------ .../XSection/LwlynSmithQELCCPXSec.h | 4 - .../XSection/NievesQELCCPXSec.cxx | 236 +++-------- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 2 - .../XSection/SmithMonizQELCCPXSec.cxx | 40 +- .../QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 234 ++--------- .../QuasiElastic/XSection/SuSAv2QELPXSec.h | 4 - .../Strange/XSection/PaisQELLambdaPXSec.cxx | 151 +------ .../Strange/XSection/PaisQELLambdaPXSec.h | 4 - 18 files changed, 999 insertions(+), 695 deletions(-) diff --git a/config/NievesSimoVacasMECPXSec2016.xml b/config/NievesSimoVacasMECPXSec2016.xml index 7bd6ed289e..6128336d41 100644 --- a/config/NievesSimoVacasMECPXSec2016.xml +++ b/config/NievesSimoVacasMECPXSec2016.xml @@ -14,6 +14,8 @@ MEC-CC-XSecScale double Yes XSec Scaling factor GPL v MECScaleAlg alg Yes XSecScale algorithm used The cross section is not scaled to scale the cross section QvalueShifterAlg algo yes Possible Qshift algo none +PreciseLeptonPol bool Yes Do precise calculation of No + lepton polarization --> genie::MECXSec/Default @@ -22,6 +24,9 @@ QvalueShifterAlg algo yes Possible Qshift algo none 1.000 1.000 + + true + diff --git a/config/SuSAv2MECPXSec.xml b/config/SuSAv2MECPXSec.xml index 83763ca0ae..b5a907b9d9 100644 --- a/config/SuSAv2MECPXSec.xml +++ b/config/SuSAv2MECPXSec.xml @@ -14,6 +14,8 @@ CKM-Vud double No Vud element of CKM matrix FermiMomentumTable string No Table of Fermi momentum (kF) constants CommonParam[FermiGas] MECScaleAlg alg Yes XSecScale algorithm used The cross section is unscaled to scale the cross section +PreciseLeptonPol bool Yes Do precise calculation of No + lepton polarization QvalueShifterAlg algo yes Qvalue shifter algo none --> @@ -24,6 +26,7 @@ QvalueShifterAlg algo yes Qvalue shifter algo 1.000 1.000 FermiGas + true diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index bf281a4a20..1c66ab1b44 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -28,6 +28,7 @@ using namespace genie; using namespace genie::utils; using namespace genie::constants; +using namespace std::complex_literals; //___________________________________________________________________________ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) @@ -61,3 +62,229 @@ void genie::utils::SetPrimaryLeptonPolarization( GHepRecord * ev ) } } +//___________________________________________________________________________ +void genie::utils::CalculatePolarizationVectorWithNuclearTensor( + TVector3 & polarization, + const TLorentzVector & neutrinoMom, + const TLorentzVector & leptonMom, + bool isLeftPolarized, + const HermitianMatrix & NTensor +) +{ + double k[4], l[4], s[4], eskl[4]; + std::complex jp[4], jm[4]; + + k[0] = neutrinoMom.E(); + k[1] = -neutrinoMom.Px(); + k[2] = -neutrinoMom.Py(); + k[3] = -neutrinoMom.Pz(); + + l[0] = leptonMom.E(); + l[1] = -leptonMom.Px(); + l[2] = -leptonMom.Py(); + l[3] = -leptonMom.Pz(); + + double ml = leptonMom.M(); + + s[0] = leptonMom.P()/ml; + s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; + s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; + s[3] = -leptonMom.Vect().Unit().Z()*leptonMom.E()/ml; + + + + // epsilon_\alpha\beta\gamma\delta s^\beta k^\gamma l^\delta + for (int a = 0; a < 4; a++) + { + eskl[a] = 0; + for (int b = 0; b < 4; b++) + { + if (b == a) continue; + for (int g = 0; g < 4; g++) + { + if (g == b || g == a) continue; + for (int d = 0; d < 4; d++) + { + if (d == g || d == b || d == a) continue; + double sb = s[b]*genie::utils::g(b,b); + double kg = k[g]*genie::utils::g(g,g); + double ld = l[d]*genie::utils::g(d,d); + eskl[a] += e(a,b,g,d)*sb*kg*ld; + } + } + } + } + + double kl = k[0]*l[0] - k[1]*l[1] - k[2]*l[2] - k[3]*l[3]; + double ks = k[0]*s[0] - k[1]*s[1] - k[2]*s[2] - k[3]*s[3]; + + for (int a = 0; a < 4; a++) + { + if (isLeftPolarized) + { + jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha + jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha + } + else + { + jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha + jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha + } + } + + std::complex LWpp(0, 0), LWpm(0, 0), LWmp(0, 0), LWmm(0, 0); + for(int mu = 0; mu < 4; mu++) + { + for(int nu = mu;nu < 4; nu++) + { + LWpp += jp[mu]*std::conj(jp[nu])*NTensor(mu,nu); // Lpp_\mu\nu*W^\mu\nu + LWpm += jp[mu]*std::conj(jm[nu])*NTensor(mu,nu); // Lpm_\mu\nu*W^\mu\nu + LWmp += jm[mu]*std::conj(jp[nu])*NTensor(mu,nu); // Lmp_\mu\nu*W^\mu\nu + LWmm += jm[mu]*std::conj(jm[nu])*NTensor(mu,nu); // Lmm_\mu\nu*W^\mu\nu + if (mu != nu) + { + LWpp += jp[nu]*std::conj(jp[mu])*NTensor(nu,mu); // Lpp_\mu\nu*W^\mu\nu + LWpm += jp[nu]*std::conj(jm[mu])*NTensor(nu,mu); // Lpm_\mu\nu*W^\mu\nu + LWmp += jm[nu]*std::conj(jp[mu])*NTensor(nu,mu); // Lmp_\mu\nu*W^\mu\nu + LWmm += jm[nu]*std::conj(jm[mu])*NTensor(nu,mu); // Lmm_\mu\nu*W^\mu\nu + } + } + } + + std::complex LWppmm = LWpp + LWmm; + std::complex rhopp = LWpp/LWppmm; + std::complex rhopm = LWpm/LWppmm; + std::complex rhomp = LWmp/LWppmm; + std::complex rhomm = LWmm/LWppmm; + double PL = std::real(rhopp - rhomm); + double PP = std::real(rhopm + rhomp); + double PT = std::imag(rhomp - rhopm); + + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + TVector3 Pz = leptonMom3.Unit(); + TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); + TVector3 Py = Pz.Cross(Px); + polarization = PT*Px + PP*Py + PL*Pz; + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << "\n"; + std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +} +//____________________________________________________________________________ +void genie::utils::CalculatePolarizationVectorWithStructureFunctions( + TVector3 & polarization, + const TLorentzVector & neutrinoMom, + const TLorentzVector & leptonMom, + const TLorentzVector & inNucleonMom, + const TLorentzVector & q4, + bool isLeftPolarized, + double M, + double W1, + double W2, + double W3, + double W4, + double W5, + double W6 +) +{ + double M2 = M*M; + double p[4], q[4], epq[4][4]; + p[0] = inNucleonMom.E(); + p[1] = inNucleonMom.Px(); + p[2] = inNucleonMom.Py(); + p[3] = inNucleonMom.Pz(); + + q[0] = q4.E(); + q[1] = q4.Px(); + q[2] = q4.Py(); + q[3] = q4.Pz(); + // epsilon^\alpha\beta\gamma\delta p_\gamma q_\delta + for (int a = 0; a < 4; a++) + { + for (int b = 0; b < 4; b++) + { + epq[a][b] = 0; + if (b == a) continue; + for (int g = 0; g < 4; g++) + { + if (g == b || g == a) continue; + for (int d = 0; d < 4; d++) + { + if (d == g || d == b || d == a) continue; + epq[a][b] += e(a,b,g,d)*genie::utils::g(a,a)*genie::utils::g(b,b)*p[g]*q[d]; + } + } + } + } + HermitianMatrix NucleonTensor(4); + for(int mu = 0; mu < 4; mu++) + { + for(int nu = mu;nu < 4; nu++) + { + double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/M2 + q[mu]*q[nu]*W4/M2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/M2; + double Wimag = epq[mu][nu]*W3/2/M2 + (q[mu]*p[nu] - p[mu]*q[nu])*W6/2/M2; + NucleonTensor.set(mu,nu,Wreal - 1i*Wimag); // W^\mu\nu + if (mu != nu) + { + NucleonTensor.set(nu,mu,Wreal + 1i*Wimag); + } + } + } + + CalculatePolarizationVectorWithNuclearTensor( + polarization, + neutrinoMom, + leptonMom, + isLeftPolarized, + NucleonTensor); + +} +//____________________________________________________________________________ +void genie::utils::CalculatePolarizationVectorInTargetRestFrame( + TVector3 & polarization, + const TLorentzVector & neutrinoMomTRF, + const TLorentzVector & leptonMomTRF, + bool isLeftPolarized, + double M, + double W1, + double W2, + double W3, + double W4, + double W5, + double W6 +) +{ + double ml = leptonMomTRF.M(); + double ml2 = ml*ml; + double M2 = M*M; + double Ev = neutrinoMomTRF.E(); + double El = leptonMomTRF.E(); + double Pl = leptonMomTRF.P(); + double cost = TMath::Cos( neutrinoMomTRF.Angle(leptonMomTRF.Vect()) ); + double sint = TMath::Sin( neutrinoMomTRF.Angle(leptonMomTRF.Vect()) ); + int sign = isLeftPolarized?-1:1; + double auxm = (El - Pl*cost)/2/M; + double auxp = (El + Pl*cost)/2/M; + double aux1m = (Pl - El*cost)/2/M; + double aux1p = (Pl + El*cost)/2/M; + double aux1 = ml2/2/M2; + double aux2 = (Ev + El)/M; + double R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; + double PL = sign*(2*aux1m*(W1 - aux1*W4) + aux1p*W2 - sign*(aux2*aux1m + aux1*cost)*W3 - aux1*cost*W5)/R; + double PP = sign*ml*sint*(2*W1 - W2 -sign*Ev*W3/M - ml2*W4/M2 + El*W5/M)/2/M/R; + double PT = - ml*Pl*sint*W6/2/M2/R; + + + TVector3 neutrinoMomTRF3 = neutrinoMomTRF.Vect(); + TVector3 leptonMomTRF3 = leptonMomTRF.Vect(); + TVector3 Pz = leptonMomTRF3.Unit(); + TVector3 Px = neutrinoMomTRF3.Cross(leptonMomTRF3).Unit(); + TVector3 Py = Pz.Cross(Px); + polarization = PT*Px + PP*Py + PL*Pz; + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << ", R =" << R << "\n"; + std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +} +//____________________________________________________________________________ + + diff --git a/src/Physics/Common/PrimaryLeptonUtils.h b/src/Physics/Common/PrimaryLeptonUtils.h index bd68efcfc2..c79d420d03 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.h +++ b/src/Physics/Common/PrimaryLeptonUtils.h @@ -20,13 +20,116 @@ #ifndef _PRIMARY_LEPTON_UTILS_H #define _PRIMARY_LEPTON_UTILS_H +#include +#include +#include + +#include "TVector3.h" + namespace genie { class GHepRecord; namespace utils { + class HermitianMatrix; void SetPrimaryLeptonPolarization( GHepRecord* ev ); + + void CalculatePolarizationVectorWithNuclearTensor( + TVector3 & polarization, + const TLorentzVector & neutrinoMom, + const TLorentzVector & leptonMom, + bool isLeftPolarized, + const HermitianMatrix & NTensor); + + void CalculatePolarizationVectorWithStructureFunctions( + TVector3 & polarization, + const TLorentzVector & neutrinoMom, + const TLorentzVector & leptonMom, + const TLorentzVector & inNucleonMom, + const TLorentzVector & q4, + bool isLeftPolarized, + double M, + double W1, + double W2, + double W3, + double W4, + double W5, + double W6); + + void CalculatePolarizationVectorInTargetRestFrame( + TVector3 & polarization, + const TLorentzVector & neutrinoMomTRF, + const TLorentzVector & leptonMomTRF, + bool isLeftPolarized, + double M, + double W1, + double W2, + double W3, + double W4, + double W5, + double W6); + + + inline int g(int a, int b) ///< metric g^{ab}=g_{ab}=diag(1,-1,-1,1) + { + return (a==b)*(2*(a==0) - 1); + } + inline int e(int a, int b, int c, int d) ///< Levi-Chevita symbol, where e_{0123}=+1 + { + return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; + } + + + class HermitianMatrix + { + public: + // Constructor + explicit HermitianMatrix(size_t size) : n(size), data(size * (size + 1) / 2) {} + + // Set an element + void set(size_t i, size_t j, const std::complex& value) + { + if (i >= n || j >= n) + { + throw std::out_of_range("Indices out of range."); + } + if (i == j) + { + data[index(i, j)] = std::real(value); + } + data[index(i, j)] = (i < j) ? value : std::conj(value); + } + + // Get an element + std::complex get(size_t i, size_t j) const + { + if (i >= n || j >= n) + { + throw std::out_of_range("Indices out of range."); + } + return (i <= j) ? data[index(i, j)] : std::conj(data[index(j, i)]); + } + + // Operator () for accessing elements + std::complex operator()(size_t i, size_t j) const + { + return get(i, j); + } + + private: + size_t n; // Matrix size + std::vector> data; // Vector for storing elements of the upper triangular part + + // Convert (i, j) indices to a single index in the 1D array + size_t index(size_t i, size_t j) const + { + if (i > j) std::swap(i, j); // Use only the upper triangular part + return i * n - i * (i + 1) / 2 + j; + } + }; + + } // utils namespace } // genie namespace diff --git a/src/Physics/Multinucleon/EventGen/MECGenerator.cxx b/src/Physics/Multinucleon/EventGen/MECGenerator.cxx index 9b35a121bc..2488f880a4 100644 --- a/src/Physics/Multinucleon/EventGen/MECGenerator.cxx +++ b/src/Physics/Multinucleon/EventGen/MECGenerator.cxx @@ -92,6 +92,8 @@ void MECGenerator::ProcessEventRecord(GHepRecord * event) const // copy of an earlier version of the `DecayNucleonCluster` method here - but, watch // for this... this -> DecayNucleonCluster(event); + // Set the final-state lepton polarization + utils::SetPrimaryLeptonPolarization( event ); } else if (fXSecModel->Id().Name() == "genie::SuSAv2MECPXSec") { event->Print(); this -> SelectSuSALeptonKinematics(event); @@ -110,7 +112,7 @@ void MECGenerator::ProcessEventRecord(GHepRecord * event) const "ProcessEventRecord >> Cannot calculate kinematics for " << fXSecModel->Id().Name(); } - + } //___________________________________________________________________________ @@ -849,9 +851,6 @@ void MECGenerator::SelectNSVLeptonKinematics (GHepRecord * event) const // -- Lepton event->AddParticle( pdgc, kIStStableFinalState, momidx, -1, -1, -1, p4l, v4); - // Set the final-state lepton polarization - utils::SetPrimaryLeptonPolarization( event ); - LOG("MEC",pDEBUG) << "~~~ LEPTON DONE ~~~"; } //___________________________________________________________________________ @@ -1321,6 +1320,7 @@ void MECGenerator::GenerateNSVInitialHadrons(GHepRecord * event) const event->AddParticle(p1); + interaction->InitStatePtr()->TgtPtr()->SetHitNucP4(p4initial_cluster); interaction->KinePtr()->SetHadSystP4(p4final_cluster); } //___________________________________________________________________________ diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index ffc23d93e0..937578b002 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -21,6 +21,7 @@ #include "Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h" #include "Physics/Multinucleon/XSection/MECUtils.h" #include "Physics/XSectionIntegration/XSecIntegratorI.h" +#include "Physics/Common/PrimaryLeptonUtils.h" using namespace genie; using namespace genie::constants; @@ -166,10 +167,10 @@ double NievesSimoVacasMECPXSec2016::XSec( // Check that the input kinematical point is within the range // in which hadron tensors are known (for chosen target) - double Ev = interaction->InitState().ProbeE(kRfLab); - double Tl = interaction->Kine().GetKV(kKVTl); - double costl = interaction->Kine().GetKV(kKVctl); - double ml = interaction->FSPrimLepton()->Mass(); + //double Ev = interaction->InitState().ProbeE(kRfLab); + //double Tl = interaction->Kine().GetKV(kKVTl); + //double costl = interaction->Kine().GetKV(kKVctl); + //double ml = interaction->FSPrimLepton()->Mass(); double Q0 = interaction->Kine().GetKV(kKVQ0); double Q3 = interaction->Kine().GetKV(kKVQ3); @@ -370,6 +371,9 @@ void NievesSimoVacasMECPXSec2016::LoadConfig(void) // Cross section scaling factor GetParam( "MEC-CC-XSecScale", fXSecCCScale ) ; GetParam( "MEC-NC-XSecScale", fXSecNCScale ) ; + + // Do precise calculation of lepton polarization + GetParamDef( "PreciseLeptonPol", fIsPreciseLeptonPolarization, false ) ; fHadronTensorModel = dynamic_cast ( this->SubAlg("HadronTensorAlg") ); if( !fHadronTensorModel ) { @@ -409,3 +413,375 @@ void NievesSimoVacasMECPXSec2016::LoadConfig(void) } } +//_________________________________________________________________________ +const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Interaction* interaction) const +{ + if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + + const Kinematics& kinematics = interaction -> Kine(); + const InitialState& init_state = interaction -> InitState(); + const Target& tgt = init_state.Tgt(); + // If {W,Q2} have been supplied instead, compute {Tl, ctl} + // NOTE: The expressions used here neglect Fermi motion and + // should eventually be revisited. See the "important note" + // in src/Framework/Utils/KineUtils.cxx about the + // Jacobian for transforming {W,Q2} --> {Tl, ctl}. + // - S. Gardiner, 29 July 2020 + if (kinematics.GetKV( kKVQ2 ) != -99999 && kinematics.GetKV( kKVW ) != -99999) + { + double Q2 = interaction->Kine().GetKV( kKVQ2 ); + double W = interaction->Kine().GetKV( kKVW ); + + // Probe properties (mass, energy, momentum) + double mv = init_state.Probe()->Mass(); + double Ev = init_state.ProbeE( kRfLab ); + double pv = std::sqrt( std::max(0., Ev*Ev - mv*mv) ); + + // Invariant mass of the initial hit nucleon + const TLorentzVector& hit_nuc_P4 = init_state.Tgt().HitNucP4(); + double M = hit_nuc_P4.M(); + + // Get the outgoing lepton kinetic energy + double ml = interaction->FSPrimLepton()->Mass(); + double Tl = Ev - ml - ( (W*W + Q2 - M*M) / (2.*M) ); + + // Get the outgoing lepton scattering cosine + double El = Tl + ml; + double pl = std::sqrt( std::max(0., El*El - ml*ml) ); + double ctl = ( 2.*Ev*El - Q2 - mv*mv - ml*ml ) / ( 2. * pv * pl ); + + // Set Tl, ctl in the interaction + interaction->KinePtr()->SetKV( kKVTl, Tl ); + interaction->KinePtr()->SetKV( kKVctl, ctl ); + } + const double M = 1; // the polarization doesn't depend on mass of target in target rest frame + // This function returns d2sigma/(dTmu dcos_mu) in GeV^(-3) + int target_pdg = tgt.Pdg(); + + int A_request = pdg::IonPdgCodeToA(target_pdg); + int Z_request = pdg::IonPdgCodeToZ(target_pdg); + + // To generate cross-sections for nuclei other than those with hadron + // tensors we need to pull both the full cross-section and + // the pn initial state fraction. + // Non-isoscalar nuclei are beyond the original published Valencia model + // and scale with A according to the number of pp, pn, or nn pairs + // the probe is expected to find. + // There is some by-hand optimization here, skipping the delta part when + // only the total cross-section is requested. + // Possible future models without a Delta had tensor would also use that + // flag to call this without computing the Delta part. + + // Try to look up a hadron tensor in the pool that is an exact match for + // the target nucleus. If an exact match cannot be found, decide upon a + // suitable substitute based on the mass number A and proton number Z. + + int tensor_pdg = target_pdg; + + /// \todo Replace these hard-coded replacements with an equivalent XML + /// configuration + if ( ! fHadronTensorModel->GetTensor(tensor_pdg, genie::kHT_MEC_FullAll) ) + { + + if ( A_request == 4 && Z_request == 2 ) + { + tensor_pdg = kPdgTgtC12; + // This is for helium 4, but use carbon tensor + // the use of nuclear density parameterization is suspicious + // but some users (MINERvA) need something not nothing. + // The pn will be exactly 1/3, but pp and nn will be ~1/4 + // Because the combinatorics are different. + // Could do lithium beryllium boron which you don't need + } + else if (A_request < 9) + { + // refuse to do D, T, He3, Li, and some Be, B + // actually it would work technically, maybe except D, T + MAXLOG("NievesSimoVacasMEC", pWARN, 10) + << "Asked to scale to deuterium through boron " + << target_pdg << " nope, lets not do that."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + else if (A_request >= 9 && A_request < 15) + { + tensor_pdg = kPdgTgtC12; + //} + // could explicitly put in nitrogen for air + //else if ( A_request >= 14 && A < 15) { // AND CHANGE <=14 to <14. + // tensor_pdg = kPdgTgtN14; + } + else if (A_request >= 15 && A_request < 22) + { + tensor_pdg = kPdgTgtO16; + } + else if (A_request >= 22 && A_request < 33) + { + // of special interest, this gets Al27 and Si28 + tensor_pdg = 1000140280; + } + else if (A_request >= 33 && A_request < 50) + { + // of special interest, this gets Ar40 and Ti48 + tensor_pdg = kPdgTgtCa40; + } + else if (A_request >= 50 && A_request < 90) + { + // pseudoFe56, also covers many other ferrometals and Ge + tensor_pdg = 1000280560; + } + else if (A_request >= 90 && A_request < 160) + { + // use Ba112 = PseudoCd. Row5 of Periodic table useless. Ag, Xe? + tensor_pdg = 1000561120; + } + else if (A_request >= 160) + { + // use Rf208 = pseudoPb + tensor_pdg = 1001042080; + } + else + { + MAXLOG("NievesSimoVacasMEC", pWARN, 10) << "Can't calculate final lepton polarization. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + } + + // Check that the input kinematical point is within the range + // in which hadron tensors are known (for chosen target) + double Q0 = interaction->Kine().GetKV(kKVQ0); + double Q3 = interaction->Kine().GetKV(kKVQ3); + + const LabFrameHadronTensorI* tensor + = dynamic_cast( + fHadronTensorModel->GetTensor(tensor_pdg, genie::kHT_MEC_FullAll) ); + + // If retrieving the tensor failed, complain and return zero + if ( !tensor ) + { + LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a" + " hadronic tensor for the nuclide " << tensor_pdg; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // Assume for now that the range of validity for the "FullAll" hadron + // tensor is the same as for the partial hadron tensors + /// \todo Revisit this assumption, and perhaps implement something + /// more robust + double Q0min = tensor->q0Min(); + double Q0max = tensor->q0Max(); + double Q3min = tensor->qMagMin(); + double Q3max = tensor->qMagMax(); + if (Q0 < Q0min || Q0 > Q0max || Q3 < Q3min || Q3 > Q3max) + { + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // Get the Q-value needed to calculate the cross sections using the + // hadron tensor. + /// \todo Shouldn't we get this from the nuclear model? + int nu_pdg = interaction->InitState().ProbePdg(); + double Q_value = genie::utils::mec::Qvalue(target_pdg, nu_pdg); + + // Apply Qvalue relative shift if needed: + if( fQvalueShifter ) Q_value += Q_value * fQvalueShifter -> Shift( interaction->InitState().Tgt() ) ; + + // By default, we will compute the full cross-section. If a resonance is + // set, we will calculate the part of the cross-section with an internal + // Delta line without a final state pion (usually called PPD for pioness + // Delta decay). If a {p,n} hit dinucleon was set we will calculate the + // cross-section for that component only (either full or PDD cross-section) + bool delta = interaction->ExclTag().KnownResonance(); + bool pn = (tgt.HitNucPdg() == kPdgClusterNP); + + double W1_all(0), W2_all(0), W3_all(0), W4_all(0), W5_all(0); + double W1_pn(0), W2_pn(0), W3_pn(0), W4_pn(0), W5_pn(0); + double W1(0), W2(0), W3(0), W4(0), W5(0); + + if ( delta ) + { + const LabFrameHadronTensorI* tensor_delta_all + = dynamic_cast( + fHadronTensorModel->GetTensor(tensor_pdg, genie::kHT_MEC_DeltaAll) ); + + if ( !tensor_delta_all ) + { + LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"DeltaAll\"" + << " hadronic tensor for nuclide " << tensor_pdg; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + const LabFrameHadronTensorI* tensor_delta_pn + = dynamic_cast( + fHadronTensorModel->GetTensor(tensor_pdg, genie::kHT_MEC_Deltapn) ); + + if ( !tensor_delta_pn ) + { + LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"Deltapn\"" + << " hadronic tensor for nuclide " << tensor_pdg; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + W1_all = tensor_delta_all->W1(Q0 - Q_value, Q3, M); + W2_all = tensor_delta_all->W2(Q0 - Q_value, Q3, M); + W3_all = -tensor_delta_all->W3(Q0 - Q_value, Q3, M); + W4_all = tensor_delta_all->W4(Q0 - Q_value, Q3, M); + W5_all = tensor_delta_all->W5(Q0 - Q_value, Q3, M); + W1_pn = tensor_delta_pn->W1(Q0 - Q_value, Q3, M); + W2_pn = tensor_delta_pn->W2(Q0 - Q_value, Q3, M); + W3_pn = -tensor_delta_pn->W3(Q0 - Q_value, Q3, M); + W4_pn = tensor_delta_pn->W4(Q0 - Q_value, Q3, M); + W5_pn = tensor_delta_pn->W5(Q0 - Q_value, Q3, M); + } + else + { + const LabFrameHadronTensorI* tensor_full_all + = dynamic_cast( + fHadronTensorModel->GetTensor(tensor_pdg, genie::kHT_MEC_FullAll) ); + + if ( !tensor_full_all ) + { + LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"FullAll\"" + << " hadronic tensor for nuclide " << tensor_pdg; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + const LabFrameHadronTensorI* tensor_full_pn + = dynamic_cast( + fHadronTensorModel->GetTensor(tensor_pdg, genie::kHT_MEC_Fullpn) ); + + if ( !tensor_full_pn ) + { + LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"Fullpn\"" + << " hadronic tensor for nuclide " << tensor_pdg; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + W1_all = tensor_full_all->W1(Q0 - Q_value, Q3, M); + W2_all = tensor_full_all->W2(Q0 - Q_value, Q3, M); + W3_all = -tensor_full_all->W3(Q0 - Q_value, Q3, M); + W4_all = tensor_full_all->W4(Q0 - Q_value, Q3, M); + W5_all = tensor_full_all->W5(Q0 - Q_value, Q3, M); + W1_pn = tensor_full_pn->W1(Q0 - Q_value, Q3, M); + W2_pn = tensor_full_pn->W2(Q0 - Q_value, Q3, M); + W3_pn = -tensor_full_pn->W3(Q0 - Q_value, Q3, M); + W4_pn = tensor_full_pn->W4(Q0 - Q_value, Q3, M); + W5_pn = tensor_full_pn->W5(Q0 - Q_value, Q3, M); + } + + // We need to scale the cross section appropriately if + // we are using a hadronic tensor for a nuclide that is different + // from the actual target + bool need_to_scale = (target_pdg != tensor_pdg); + + // would need to trap and treat He3, T, D special here. + if ( need_to_scale ) + { + + double PP = Z_request; + double NN = A_request - PP; + double P = pdg::IonPdgCodeToZ(tensor_pdg); + double N = pdg::IonPdgCodeToA(tensor_pdg) - P; + + double scale_pn = TMath::Sqrt( (PP*NN)/(P*N) ); + double scale_pp = TMath::Sqrt( (PP * (PP - 1.)) / (P * (P - 1.)) ); + double scale_nn = TMath::Sqrt( (NN * (NN - 1.)) / (N * (N - 1.)) ); + + LOG("NievesSimoVacasMEC", pDEBUG) + << "Scale pn pp nn for (" << target_pdg << ", " << tensor_pdg << ")" + << " : " << scale_pn << " " << scale_pp << " " << scale_nn; + + // This is an approximation in at least three senses: + // 1. We are scaling from an isoscalar nucleus using p and n counting + // 2. We are not using the right qvalue in the had tensor + // 3. We are not scaling the Delta faster than the non-Delta. + // The guess is that these are good approximations. + // A test we could document is to scale from O16 to N14 or C12 using this + // algorithm and see how many percent deviation we see from the full + // calculation. + double temp1_all = W1_all; + double temp1_pn = W1_pn * scale_pn; + double temp2_all = W2_all; + double temp2_pn = W2_pn * scale_pn; + double temp3_all = W3_all; + double temp3_pn = W3_pn * scale_pn; + double temp4_all = W4_all; + double temp4_pn = W4_pn * scale_pn; + double temp5_all = W5_all; + double temp5_pn = W5_pn * scale_pn; + if (nu_pdg > 0) + { + // matter neutrinos + temp1_all = W1_pn * scale_pn + (W1_all - W1_pn) * scale_nn; + temp2_all = W2_pn * scale_pn + (W2_all - W2_pn) * scale_nn; + temp3_all = W3_pn * scale_pn + (W3_all - W3_pn) * scale_nn; + temp4_all = W4_pn * scale_pn + (W4_all - W4_pn) * scale_nn; + temp5_all = W5_pn * scale_pn + (W5_all - W5_pn) * scale_nn; + } + else + { + // antineutrinos + temp1_all = W1_pn * scale_pn + (W1_all - W1_pn) * scale_pp; + temp2_all = W2_pn * scale_pn + (W2_all - W2_pn) * scale_pp; + temp3_all = W3_pn * scale_pn + (W3_all - W3_pn) * scale_pp; + temp4_all = W4_pn * scale_pn + (W4_all - W4_pn) * scale_pp; + temp5_all = W5_pn * scale_pn + (W5_all - W5_pn) * scale_pp; + } + + W1_all = temp1_all; + W1_pn = temp1_pn; + W2_all = temp2_all; + W2_pn = temp2_pn; + W3_all = temp3_all; + W3_pn = temp3_pn; + W4_all = temp4_all; + W4_pn = temp4_pn; + W5_all = temp5_all; + W5_pn = temp5_pn; + } + + // Choose the right kind of cross section ("all" or "pn") to return + // based on whether a {p, n} dinucleon was hit + if (pn) + { + W1 = W1_pn; + W2 = W2_pn; + W3 = W3_pn; + W4 = W4_pn; + W5 = W5_pn; + } + else + { + W1 = W1_all; + W2 = W2_all; + W3 = W3_all; + W4 = W4_all; + W5 = W5_all; + } + + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + genie::utils::CalculatePolarizationVectorInTargetRestFrame( + fFinalLeptonPolarization, + neutrinoMom, + leptonMom, + is_neutrino, + M, W1,W2,W3,W4,W5,0); + + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << fFinalLeptonPolarization.Mag() << "\n"; + std::cout << "NVMEC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + return fFinalLeptonPolarization; +} diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h index 273126f146..9228280d31 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h @@ -49,6 +49,7 @@ class NievesSimoVacasMECPXSec2016 : public XSecAlgorithmI { double XSec (const Interaction * i, KinePhaseSpace_t k) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; + const TVector3 & FinalLeptonPolarization (const Interaction* i) const; // override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index 7266bcc8d8..ccd613e4a3 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -21,6 +21,7 @@ #include "Physics/XSectionIntegration/XSecIntegratorI.h" #include "Physics/NuclearState/FermiMomentumTablePool.h" #include "Physics/NuclearState/FermiMomentumTable.h" +#include "Physics/Common/PrimaryLeptonUtils.h" using namespace genie; @@ -51,7 +52,7 @@ double SuSAv2MECPXSec::XSec(const Interaction* interaction, int target_pdg = interaction->InitState().Tgt().Pdg(); int probe_pdg = interaction->InitState().ProbePdg(); int A_request = pdg::IonPdgCodeToA(target_pdg); - int Z_request = pdg::IonPdgCodeToZ(target_pdg); +// int Z_request = pdg::IonPdgCodeToZ(target_pdg); bool need_to_scale = false; HadronTensorType_t tensor_type = kHT_Undefined; @@ -128,7 +129,7 @@ double SuSAv2MECPXSec::XSec(const Interaction* interaction, // dinucleon was set we will calculate the cross-section for that // component only - bool pn = (interaction->InitState().Tgt().HitNucPdg() == kPdgClusterNP); + //bool pn = (interaction->InitState().Tgt().HitNucPdg() == kPdgClusterNP); // Compute the cross section using the hadron tensor double xsec = tensor->dSigma_dT_dCosTheta_rosenbluth(interaction, Delta_Q_value); @@ -415,6 +416,9 @@ void SuSAv2MECPXSec::LoadConfig(void) GetParamDef("MEC-CC-XSecScale", fXSecCCScale, 1.) ; GetParamDef("MEC-NC-XSecScale", fXSecNCScale, 1.) ; GetParamDef("MEC-EM-XSecScale", fXSecEMScale, 1.) ; + + // Do precise calculation of lepton polarization + GetParamDef( "PreciseLeptonPol", fIsPreciseLeptonPolarization, false ) ; fHadronTensorModel = dynamic_cast ( this->SubAlg("HadronTensorAlg") ); if( !fHadronTensorModel ) { @@ -471,3 +475,128 @@ void SuSAv2MECPXSec::LoadConfig(void) } } +//_________________________________________________________________________ +const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* interaction) const +{ + const ProcessInfo& proc_info = interaction->ProcInfo(); + if ( proc_info.IsEM() ) + { + LOG("SuSAv2MECPXSec", pWARN) << "For EM processes doesn't work yet. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + // Get the hadron tensor for the selected nuclide. Check the probe PDG code + // to know whether to use the tensor for CC neutrino scattering or for + // electron scattering + const double M = 1; // the polarization doesn't depend on mass of target in target rest frame + const Kinematics& kinematics = interaction -> Kine(); + const InitialState& init_state = interaction -> InitState(); + int probe_pdg = interaction->InitState().ProbePdg(); + + HadronTensorType_t tensor_type = kHT_Undefined; + if ( pdg::IsNeutrino(probe_pdg) || pdg::IsAntiNeutrino(probe_pdg) ) + { + tensor_type = kHT_MEC_FullAll; + } + else + { + LOG("SuSAv2MECPXSec", pWARN) << "Doesn't work for processes other than weak ones. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + //else + //{ + //tensor_type = kHT_MEC_EM; + //} + + // Currently we only have the relative pair contributions for C12. + int tensor_pdg = kPdgTgtC12; + // The rescaling factor will be reduced. Therefore there is no need in rescaling. +// if(tensor_pdg != target_pdg) need_to_scale = true; + + // The SuSAv2-MEC hadron tensors are defined using the same conventions + // as the Valencia MEC model, so we can use the same sort of tensor + // object to describe them. + const LabFrameHadronTensorI* tensor + = dynamic_cast( fHadronTensorModel->GetTensor(tensor_pdg, + tensor_type) ); + + // If retrieving the tensor failed, complain and return zero + if ( !tensor ) + { + LOG("SuSAv2MEC", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // Check that the input kinematical point is within the range + // in which hadron tensors are known (for chosen target) + double Ev = interaction->InitState().ProbeE(kRfLab); + double Tl = interaction->Kine().GetKV(kKVTl); + double costl = interaction->Kine().GetKV(kKVctl); + double ml = interaction->FSPrimLepton()->Mass(); + double Q0 = 0.; + double Q3 = 0.; + + // The Q-Value essentially corrects q0 to account for nuclear + // binding energy in the Valencia model but this effect is already + // in Guille's tensors so its set it to 0. + // However, additional corrections may be necessary: + double Delta_Q_value = Qvalue( * interaction ) ; + + genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); + + double Q0min = tensor->q0Min(); + double Q0max = tensor->q0Max(); + double Q3min = tensor->qMagMin(); + double Q3max = tensor->qMagMax(); + if (Q0-Delta_Q_value < Q0min || Q0-Delta_Q_value > Q0max || Q3 < Q3min || Q3 > Q3max) + { + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + // *** Enforce the global Q^2 cut (important for EM scattering) *** + // Choose the appropriate minimum Q^2 value based on the interaction + // mode (this is important for EM interactions since the differential + // cross section blows up as Q^2 --> 0) + double Q2min = genie::controls::kMinQ2Limit; // CC/NC limit + //if ( interaction->ProcInfo().IsEM() ) + //Q2min = genie::utils::kinematics::electromagnetic::kMinQ2Limit; // EM limit + + // Neglect shift due to binding energy. The cut is on the actual + // value of Q^2, not the effective one to use in the tensor contraction. + double Q2 = Q3*Q3 - Q0*Q0; + if ( Q2 < Q2min ) + { + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; + } + + + double W1 = tensor->W1(Q0 - Delta_Q_value, Q3, M); + double W2 = tensor->W2(Q0 - Delta_Q_value, Q3, M); + double W3 =-tensor->W3(Q0 - Delta_Q_value, Q3, M); // note invert sign + double W4 = tensor->W4(Q0 - Delta_Q_value, Q3, M); + double W5 = tensor->W5(Q0 - Delta_Q_value, Q3, M); + + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + genie::utils::CalculatePolarizationVectorInTargetRestFrame( + fFinalLeptonPolarization, + neutrinoMom, + leptonMom, + is_neutrino, + M, W1,W2,W3,W4,W5,0); + + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << fFinalLeptonPolarization.Mag() << "\n"; + std::cout << "SU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + return fFinalLeptonPolarization; +} diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.h b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.h index 9c93967fba..b425b79969 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.h +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.h @@ -49,6 +49,8 @@ class SuSAv2MECPXSec : public XSecAlgorithmI { double XSec(const Interaction* i, KinePhaseSpace_t k) const; double Integral(const Interaction* i) const; bool ValidProcess(const Interaction* i) const; + const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + // override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index c57c58c708..9d7bacfa8e 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -32,11 +32,11 @@ #include "Framework/Utils/KineUtils.h" #include "Physics/NuclearState/NuclearUtils.h" #include "Physics/QuasiElastic/XSection/QELUtils.h" +#include "Physics/Common/PrimaryLeptonUtils.h" using namespace genie; using namespace genie::constants; using namespace genie::utils; -using namespace std::complex_literals; //____________________________________________________________________________ LwlynSmithQELCCPXSec::LwlynSmithQELCCPXSec() : @@ -488,8 +488,7 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio bool isosymmetry = true; if (qel_ff_mod_name == "genie::LwlynSmithFFCC") isosymmetry = false; if (qel_ff_mod_name == "genie::LwlynSmithIsoFFCC") isosymmetry = true; - - double ml = interaction->FSPrimLepton()->Mass(); + // First we need access to all of the particles in the interaction // The particles were stored in the lab frame const Kinematics& kinematics = interaction -> Kine(); @@ -624,149 +623,19 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio double W3 = w03 ; double W4 = w04 + w14*r + w24*r2; double W5 = w05 + w15*r + w25*r2; - - double p[4], q[4], epq[4][4], k[4], l[4], s[4], eskl[4]; - std::complex jp[4], jm[4]; - - p[0] = inNucleonMom.E(); - p[1] = inNucleonMom.Px(); - p[2] = inNucleonMom.Py(); - p[3] = inNucleonMom.Pz(); - - q[0] = qP4.E(); - q[1] = qP4.Px(); - q[2] = qP4.Py(); - q[3] = qP4.Pz(); - - k[0] = neutrinoMom.E(); - k[1] = -neutrinoMom.Px(); - k[2] = -neutrinoMom.Py(); - k[3] = -neutrinoMom.Pz(); - - l[0] = leptonMom.E(); - l[1] = -leptonMom.Px(); - l[2] = -leptonMom.Py(); - l[3] = -leptonMom.Pz(); - - s[0] = leptonMom.P()/ml; - s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; - s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; - s[3] = -leptonMom.Vect().Unit().Z()*leptonMom.E()/ml; - - // epsilon^\alpha\beta\gamma\delta p_\gamma q_\delta - for (int a = 0; a < 4; a++) - { - for (int b = 0; b < 4; b++) - { - epq[a][b] = 0; - if (b == a) continue; - for (int g = 0; g < 4; g++) - { - if (g == b || g == a) continue; - for (int d = 0; d < 4; d++) - { - if (d == g || d == b || d == a) continue; - epq[a][b] += e(a,b,g,d)*(a == 0?1:-1)*(b == 0?1:-1)*p[g]*q[d]; - } - } - } - } - - // epsilon_\alpha\beta\gamma\delta s^\beta k^\gamma l^\delta - for (int a = 0; a < 4; a++) - { - eskl[a] = 0; - for (int b = 0; b < 4; b++) - { - if (b == a) continue; - for (int g = 0; g < 4; g++) - { - if (g == b || g == a) continue; - for (int d = 0; d < 4; d++) - { - if (d == g || d == b || d == a) continue; - double sb = s[b]*(b == 0?1:-1); - double kg = k[g]*(g == 0?1:-1); - double ld = l[d]*(d == 0?1:-1); - eskl[a] += e(a,b,g,d)*sb*kg*ld; - } - } - } - } - - double kl = k[0]*l[0] - k[1]*l[1] - k[2]*l[2] - k[3]*l[3]; - double ks = k[0]*s[0] - k[1]*s[1] - k[2]*s[2] - k[3]*s[3]; - - for (int a = 0; a < 4; a++) - { - if (is_neutrino) - { - jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha - jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha - } - else - { - jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha - jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha - } - } - - //Additional constants and variables - std::complex Wmunu, Wnumu, LWpp(0, 0), LWpm(0, 0), LWmp(0, 0), LWmm(0, 0); - for(int mu = 0; mu < 4; mu++) - { - for(int nu = mu;nu < 4; nu++) - { - double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/M2 + q[mu]*q[nu]*W4/M2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/M2; - double Wimag = epq[mu][nu]*W3/2/M2; - Wmunu = Wreal - 1i*Wimag; // W^\mu\nu - LWpp += jp[mu]*std::conj(jp[nu])*Wmunu; // Lpp_\mu\nu*W^\mu\nu - LWpm += jp[mu]*std::conj(jm[nu])*Wmunu; // Lpm_\mu\nu*W^\mu\nu - LWmp += jm[mu]*std::conj(jp[nu])*Wmunu; // Lmp_\mu\nu*W^\mu\nu - LWmm += jm[mu]*std::conj(jm[nu])*Wmunu; // Lmm_\mu\nu*W^\mu\nu - if (mu != nu) - { - Wnumu = Wreal + 1i*Wimag; - LWpp += jp[nu]*std::conj(jp[mu])*Wnumu; // Lpp_\mu\nu*W^\mu\nu - LWpm += jp[nu]*std::conj(jm[mu])*Wnumu; // Lpm_\mu\nu*W^\mu\nu - LWmp += jm[nu]*std::conj(jp[mu])*Wnumu; // Lmp_\mu\nu*W^\mu\nu - LWmm += jm[nu]*std::conj(jm[mu])*Wnumu; // Lmm_\mu\nu*W^\mu\nu - } - } - } - std::complex LWppmm = LWpp + LWmm; - std::complex rhopp = LWpp/LWppmm; - std::complex rhopm = LWpm/LWppmm; - std::complex rhomp = LWmp/LWppmm; - std::complex rhomm = LWmm/LWppmm; - double PL = std::real(rhopp - rhomm); - double PP = std::real(rhopm + rhomp); - double PT = std::imag(rhomp - rhopm); - - TVector3 neutrinoMom3 = neutrinoMom.Vect(); - TVector3 leptonMom3 = leptonMom.Vect(); - TVector3 Pz = leptonMom3.Unit(); - TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); - TVector3 Py = Pz.Cross(Px); - TVector3 pol = PT*Px + PP*Py + PL*Pz; - fFinalLeptonPolarization = pol; - + CalculatePolarizationVectorWithStructureFunctions( + fFinalLeptonPolarization, + neutrinoMom, + leptonMom, + inNucleonMom, + qP4, + is_neutrino, + M, W1,W2,W3,W4,W5,0); + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << "PL = " << PL << ", PT = " << PT << ", PP = " << PP << "\n"; std::cout << fFinalLeptonPolarization.Mag() << "\n"; std::cout << "LW@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } -//____________________________________________________________________________ -inline int LwlynSmithQELCCPXSec::g(int a, int b) const -{ - return (a==b)*(2*(a==0) - 1); -} -//____________________________________________________________________________ -inline int LwlynSmithQELCCPXSec::e(int a, int b, int c, int d) const -{ - return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; -} -//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h index d6c84f8f3b..5541dffd4a 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h @@ -23,7 +23,6 @@ #ifndef _LLEWELLYN_SMITH_QELCC_CROSS_SECTION_H_ #define _LLEWELLYN_SMITH_QELCC_CROSS_SECTION_H_ -#include #include "Physics/NuclearState/NuclearModelI.h" #include "Framework/EventGen/XSecAlgorithmI.h" @@ -58,9 +57,6 @@ class LwlynSmithQELCCPXSec : public XSecAlgorithmI { double FullDifferentialXSec(const Interaction * i) const; void LoadConfig (void); - - int e(int a, int b, int c, int d) const; - int g(int a, int b) const; mutable QELFormFactors fFormFactors; ///< const QELFormFactorsModelI * fFormFactorsModel; ///< diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index b47367bba2..61ebb2db5e 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -38,6 +38,7 @@ #include "Physics/NuclearState/NuclearUtils.h" #include "Framework/Utils/PrintUtils.h" #include "Framework/Numerical/GSLUtils.h" +#include "Physics/Common/PrimaryLeptonUtils.h" #include // Used for testing code #include // Used for testing code @@ -890,9 +891,35 @@ double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const{ } } //____________________________________________________________________________ -int NievesQELCCPXSec::leviCivita(int input[]) const -{ - return e(input[0], input[1], input[2], input[3]); +int NievesQELCCPXSec::leviCivita(int input[]) const{ + int copy[4] = {input[0],input[1],input[2],input[3]}; + int permutations = 0; + int temp; + + for(int i=0;i<4;i++){ + for(int j=i+1;j<4;j++){ + //If any two elements are equal return 0 + if(input[i] == input[j]) + return 0; + //If a larger number is before a smaller one, use permutations + //(exchanges of two adjacent elements) to move the smaller element + //so it is before the larger element, eg 2341->2314->2134->1234 + if(copy[i]>copy[j]){ + temp = copy[j]; + for(int k=j;k>i;k--){ + copy[k] = copy[k-1]; + permutations++; + } + copy[i] = temp; + } + } + } + + if(permutations % 2 == 0){ + return 1; + }else{ + return -1; + } } //____________________________________________________________________________ // Calculates the constraction of the leptonic and hadronic tensors. The @@ -1460,10 +1487,9 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i } // Calculate q and qTilde - TLorentzVector qP4 = neutrinoMom - leptonMom; TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); - - double Q2 = -qP4.Mag2(); + + double Q2 = interaction->KinePtr()->Q2(true); double Q2tilde = -qTildeP4.Mag2(); // Check that Q2tilde > 0 (accounting for rounding errors) @@ -1527,84 +1553,30 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i double FA2 = FA*FA; double F1V2 = F1V*F1V; double xiF2V2 = xiF2V*xiF2V; -// const double q[4] = {qTildeP4.E(),qTildeP4.Px(),qTildeP4.Py(),qTildeP4.Pz()}; - double q[4] = {qTildeP4.E(),qTildeP4.Px(),qTildeP4.Py(),qTildeP4.Pz()}; + const double q[4] = {qTildeP4.E(),qTildeP4.Px(),qTildeP4.Py(),qTildeP4.Pz()}; double q0 = q[0]; double dq = TMath::Sqrt(q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); double q02 = q0*q0; double dq2 = dq*dq; double q2 = q02 - dq2; - double tulin[4], k[4], l[4], s[4], eskl[4]; + double tulin[4]; double rulin[4][4]; - std::complex jp[4], jm[4]; // For normal code execulation, tulin is the initial nucleon momentum tulin[0] = inNucleonMomOnShell.E(); tulin[1] = inNucleonMomOnShell.Px(); tulin[2] = inNucleonMomOnShell.Py(); tulin[3] = inNucleonMomOnShell.Pz(); - - - k[0] = neutrinoMom.E(); - k[1] = -neutrinoMom.Px(); - k[2] = -neutrinoMom.Py(); - k[3] = -neutrinoMom.Pz(); - - l[0] = leptonMom.E(); - l[1] = -leptonMom.Px(); - l[2] = -leptonMom.Py(); - l[3] = -leptonMom.Pz(); - - s[0] = leptonMom.P()/ml; - s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; - s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; - s[3] = -leptonMom.Vect().Unit().Z()*leptonMom.E()/ml; - - for (int a = 0; a < 4; a++) - { - eskl[a] = 0; - for (int b = 0; b < 4; b++) - { - if (b == a) continue; - for (int g = 0; g < 4; g++) - { - if (g == b || g == a) continue; - for (int d = 0; d < 4; d++) - { - if (d == g || d == b || d == a) continue; - double sb = s[b]*(b == 0?1:-1); - double kg = k[g]*(g == 0?1:-1); - double ld = l[d]*(d == 0?1:-1); - eskl[a] += e(a,b,g,d)*sb*kg*ld; - } - } - } - } - - double kl = neutrinoMom*leptonMom; - double ks = k[0]*s[0] - k[1]*s[1] - k[2]*s[2] - k[3]*s[3]; for(int i = 0; i < 4; i++) - for(int j = i; j < 4; j++) + for(int j = i; j < 4; j++) rulin[i][j] = rulin[j][i] = tulin[i]*tulin[j]; - - for (int a = 0; a < 4; a++) - { - if (is_neutrino) - { - jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha - jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha - } - else - { - jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha - jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha - } - } + + std::complex Amunu, Anumu; + + HermitianMatrix NuclearTensor(4); - //Additional constants and variables - std::complex Amunu, Anumu, LWpp(0, 0), LWpm(0, 0), LWmp(0, 0), LWmm(0, 0); double aux1 = 2*CL*Fp*(Fp*q2 + 4*FA*M); double aux2 = 8*(FA2 + 4*F1V2 - xiF2V2*q2/M2); for(int mu = 0; mu < 4; mu++) @@ -1616,10 +1588,7 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i Amunu = 32*F1V2*(rulin[0][0]*CN + q[0]*tulin[0] + q2/4)+ 8*q2*xiF2V2*(1 - rulin[0][0]/M2 - q[0]*tulin[0]/M2 - q02*(1/q2 + 1/4./M2)) + 8*FA2*(rulin[0][0] + q[0]*tulin[0] + q2/4 - M2)-aux1*q02-16*F1V*xiF2V*(q02 - q2)*CN; - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + NuclearTensor.set(mu, nu, Amunu); } if (mu == 1 && nu == 1) { @@ -1627,10 +1596,7 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i 8*q2*xiF2V2*(CT + rulin[1][1]/M2) + 8*FA2*(rulin[1][1] + CT*M2 - q2/4)- 16*F1V*xiF2V*CT*q2; - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + NuclearTensor.set(mu, nu, Amunu); } if (mu == 2 && nu == 2) { @@ -1638,143 +1604,75 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i 8*q2*xiF2V2*(CT + rulin[2][2]/M2) + 8*FA2*(rulin[2][2] + CT*M2 - q2/4)- 16*F1V*xiF2V*CT*q2; - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + NuclearTensor.set(mu, nu, Amunu); } if (mu == 3 && nu == 3) { Amunu = 32*F1V2*(rulin[3][3] + dq*tulin[3] - q2/4)- 8*q2*xiF2V2*(1 + rulin[3][3]/M2 + dq*tulin[3]/M2 + dq2*(1/q2 + 1/4./M2))+ 8*FA2*(rulin[3][3] + dq*tulin[3] + CL*M2 - q2/4) - aux1*dq2 - 16*F1V*xiF2V*q02; - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; + NuclearTensor.set(mu, nu, Amunu); } if (mu == 0 && nu == 1) { Amunu = aux2*(rulin[0][1] + tulin[1]*q[0]/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[2]*dq; - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; - + NuclearTensor.set(mu, nu, Amunu); + Anumu = aux2*(rulin[0][1] + tulin[1]*q[0]/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[2]*dq; - LWpp += jp[nu]*std::conj(jp[mu])*Anumu; - LWpm += jp[nu]*std::conj(jm[mu])*Anumu; - LWmp += jm[nu]*std::conj(jp[mu])*Anumu; - LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + NuclearTensor.set(nu, mu, Anumu); } if (mu == 0 && nu == 2) { Amunu = aux2*(rulin[0][2] + tulin[2]*q[0]/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[1]*dq; - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; - + NuclearTensor.set(mu, nu, Amunu); + Anumu = aux2*(rulin[0][2] + tulin[2]*q[0]/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[1]*dq; - LWpp += jp[nu]*std::conj(jp[mu])*Anumu; - LWpm += jp[nu]*std::conj(jm[mu])*Anumu; - LWmp += jm[nu]*std::conj(jp[mu])*Anumu; - LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + NuclearTensor.set(nu, mu, Anumu); } if (mu == 0 && nu == 3) { Amunu = 16*F1V2*((2*rulin[0][3] + tulin[0]*dq)*CN + tulin[3]*q[0])+ -4*q2*xiF2V2*(2*rulin[0][3]/M2 + (dq*tulin[0] + q[0]*tulin[3])/M2 + dq*q[0]*(2/q2 + 0.5/M2))+ 4*FA2*((2*rulin[0][3] + dq*tulin[0])*CL + q[0]*tulin[3]) - dq*q[0]*(aux1 + 16*F1V*xiF2V); - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; - - Anumu = Amunu; - LWpp += jp[nu]*std::conj(jp[mu])*Anumu; - LWpm += jp[nu]*std::conj(jm[mu])*Anumu; - LWmp += jm[nu]*std::conj(jp[mu])*Anumu; - LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + NuclearTensor.set(mu, nu, Amunu); + NuclearTensor.set(nu, mu, Amunu); } if (mu == 1 && nu == 2) { Amunu = -1i*16.*FA*(xiF2V+F1V)*(q[0]*tulin[3] - dq*tulin[0]*CT) + 8.*rulin[1][2]*(FA2 + 4*F1V2 - xiF2V2*q2/M2); - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; - - Anumu = 1i*16.*FA*(xiF2V+F1V)*(q[0]*tulin[3] - dq*tulin[0]*CT) + 8.*rulin[1][2]*(FA2 + 4*F1V2 - xiF2V2*q2/M2); - LWpp += jp[nu]*std::conj(jp[mu])*Anumu; - LWpm += jp[nu]*std::conj(jm[mu])*Anumu; - LWmp += jm[nu]*std::conj(jp[mu])*Anumu; - LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + NuclearTensor.set(mu, nu, Amunu); + NuclearTensor.set(nu, mu, std::conj(Amunu)); + } if (mu == 1 && nu == 3) { Amunu = aux2*(rulin[1][3] + tulin[1]*dq/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[2]*q[0]; - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; - - Anumu = aux2*(rulin[1][3] + tulin[1]*dq/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[2]*q[0]; - LWpp += jp[nu]*std::conj(jp[mu])*Anumu; - LWpm += jp[nu]*std::conj(jm[mu])*Anumu; - LWmp += jm[nu]*std::conj(jp[mu])*Anumu; - LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + NuclearTensor.set(mu, nu, Amunu); + NuclearTensor.set(nu, mu, std::conj(Amunu)); } if (mu == 2 && nu == 3) { Amunu = aux2*(rulin[2][3] + tulin[2]*dq/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[1]*q[0]; - LWpp += jp[mu]*std::conj(jp[nu])*Amunu; - LWpm += jp[mu]*std::conj(jm[nu])*Amunu; - LWmp += jm[mu]*std::conj(jp[nu])*Amunu; - LWmm += jm[mu]*std::conj(jm[nu])*Amunu; - - Anumu = aux2*(rulin[2][3] + tulin[2]*dq/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[1]*q[0]; - LWpp += jp[nu]*std::conj(jp[mu])*Anumu; - LWpm += jp[nu]*std::conj(jm[mu])*Anumu; - LWmp += jm[nu]*std::conj(jp[mu])*Anumu; - LWmm += jm[nu]*std::conj(jm[mu])*Anumu; + NuclearTensor.set(mu, nu, Amunu); + NuclearTensor.set(nu, mu, std::conj(Amunu)); } } } - std::complex LWppmm = LWpp + LWmm; - std::complex rhopp = LWpp/LWppmm; - std::complex rhopm = LWpm/LWppmm; - std::complex rhomp = LWmp/LWppmm; - std::complex rhomm = LWmm/LWppmm; - double PL = std::real(rhopp - rhomm); - double PP = std::real(rhopm + rhomp); - double PT = std::imag(rhomp - rhopm); - - neutrinoMom3 = neutrinoMom.Vect(); - leptonMom3 = leptonMom.Vect(); - TVector3 Pz = leptonMom3.Unit(); - TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); - TVector3 Py = Pz.Cross(Px); - TVector3 pol = PT*Px + PP*Py + PL*Pz; - fFinalLeptonPolarization = pol; + CalculatePolarizationVectorWithNuclearTensor( + fFinalLeptonPolarization, + neutrinoMom, + leptonMom, + is_neutrino, + NuclearTensor); + + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << "PL = " << PL << ", PT = " << PT << ", PP = " << PP << "\n"; std::cout << fFinalLeptonPolarization.Mag() << "\n"; std::cout << "NV@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } -//____________________________________________________________________________ -inline int NievesQELCCPXSec::g(int a, int b) const -{ - return (a==b)*(2*(a==0) - 1); -} -//____________________________________________________________________________ -inline int NievesQELCCPXSec::e(int a, int b, int c, int d) const -{ - return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; -} -//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index e16132df15..888594ecad 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -145,8 +145,6 @@ class NievesQELCCPXSec : public XSecAlgorithmI { //-1 if input is an odd permutation of 0123, and 0 if any two elements //are equal int leviCivita(int input[]) const; - int e(int a, int b, int c, int d) const; - int g(int a, int b) const; double LmunuAnumu(const TLorentzVector neutrinoMom, const TLorentzVector inNucleonMom, const TLorentzVector leptonMom, diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 1a01deb822..438aa80966 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -45,6 +45,7 @@ #include "Framework/Utils/KineUtils.h" #include "Framework/Utils/Range1.h" #include "Physics/QuasiElastic/XSection/SmithMonizUtils.h" +#include "Physics/Common/PrimaryLeptonUtils.h" using namespace genie; using namespace genie::constants; @@ -521,7 +522,6 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio double qv = TMath::Sqrt(qqv); bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); - int sign = (is_neutrino) ? +1 : -1; double El = Enu - v; double ml = interaction->FSPrimLepton()->Mass(); @@ -540,12 +540,7 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio fFinalLeptonPolarization = TVector3(0, 0, 0); return fFinalLeptonPolarization; } - double sin_theta = TMath::Sqrt(1 - cos_theta*cos_theta); - // cos^2(theta/2) - double cs2th = (1 + cos_theta)/2; - // sin^2(theta/2) - double sn2th = (1 - cos_theta)/2; - + double cosT_k = (v + k6)/qv; if (cosT_k < -1.0 || cosT_k > 1.0 ) { @@ -653,34 +648,23 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio double T3 = k5*W3; //Ref.[1], W_8 double T4 = mm_tar*(0.5*k4*W2 + a1*W4/mm_ini + a6*W5/m_ini/qv); //Ref.[1], W_\alpha double T5 = m_tar*(a5/qv - v*k4)*W2 + k5*W5; - - double kappa = ml2/2/mm_tar; - double R = (El - Pl*cos_theta)/m_tar*(T1 + kappa*T4) + (El + Pl*cos_theta)/2/m_tar*T2 - + sign*((Enu + El)*(El - Pl*cos_theta)/2/mm_tar - kappa)*T3 - kappa*T5; //sign toghether with sign of FA ("-") will give correct total sign - - // In the frame, where lepton momentum is in z direction, x - axis is in production plane and orthogonal to z - // PL || z, PP || x, PT || y = 0 in Standard Model, because T6 = 0 - double PP = -sign*ml*sin_theta/2/m_tar/R*(T1*2 - T2 + T3*sign*Enu/m_tar - T4*ml2/mm_tar + T5*El/m_tar); - double PL = -sign*(1 - ml2/mm_tar/R*((T1*2*m_tar/(El + Pl) + T3*sign*(Enu - Pl)/(El + Pl))*cs2th + - (T2*m_tar/(El + Pl) + T4*(El + Pl)/m_tar - T5)*sn2th)); - + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); - TLorentzVector neutrinoMom = *tempNeutrino; + TLorentzVector neutrinoMom = *tempNeutrino; delete tempNeutrino; const TLorentzVector leptonMom = kinematics.FSLeptonP4(); - TVector3 neutrinoMom3 = neutrinoMom.Vect(); - TVector3 leptonMom3 = leptonMom.Vect(); - TVector3 Pz = leptonMom3.Unit(); - TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); - TVector3 Py = Pz.Cross(Px); - TVector3 pol = PP*Py + PL*Pz; - fFinalLeptonPolarization = PP*Py + PL*Pz; + CalculatePolarizationVectorInTargetRestFrame( + fFinalLeptonPolarization, + neutrinoMom, + leptonMom, + is_neutrino, + m_tar, T1,T2,T3,T4,T5,0); + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; std::cout << fFinalLeptonPolarization.Mag() << "\n"; std::cout << "SM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - + return fFinalLeptonPolarization; - } //____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index e9261b211a..d6bdce8ca2 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -7,7 +7,6 @@ For the class documentation see the corresponding header file. */ //_________________________________________________________________________ - #include "Framework/Algorithm/AlgConfigPool.h" #include "Framework/Conventions/Units.h" #include "Framework/Messenger/Messenger.h" @@ -23,6 +22,7 @@ #include "Physics/NuclearState/FermiMomentumTablePool.h" #include "Physics/NuclearState/FermiMomentumTable.h" #include "Framework/Conventions/Constants.h" +#include "Physics/Common/PrimaryLeptonUtils.h" #include @@ -667,6 +667,7 @@ void SuSAv2QELPXSec::LoadConfig(void) } } +//_________________________________________________________________________ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* interaction) const { const ProcessInfo& proc_info = interaction->ProcInfo(); @@ -684,17 +685,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int int probe_pdg = interaction->InitState().ProbePdg(); bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); - - // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial - // struck nucleon - double Mi_onshell = tgt.HitNucMass(); - - // On-shell mass of final nucleon (from PDGLibrary) - double Mf = interaction->RecoilNucleon()->Mass(); - - // Isoscalar mass of nucleon - double M = (Mi_onshell + Mf)/2; - double M2 = M*M; + + const double M = 1; // the polarization doesn't depend on mass of target in target rest frame // Check that the input kinematical point is within the range // in which hadron tensors are known (for chosen target) @@ -709,6 +701,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int // *** Enforce the global Q^2 cut *** double Q2min = genie::controls::kMinQ2Limit; // CC limit + //if ( interaction->ProcInfo().IsEM() ) + //Q2min = genie::utils::kinematics::electromagnetic::kMinQ2Limit; // EM limit // Neglect shift due to binding energy. The cut is on the actual // value of Q^2, not the effective one to use in the tensor contraction. @@ -720,28 +714,7 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int return fFinalLeptonPolarization; } - // Note that GetProbeP4 defaults to returning the probe 4-momentum in the - // struck nucleon rest frame, so we have to explicitly ask for the lab frame - // here - TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); - TLorentzVector neutrinoMom = *tempNeutrino; - delete tempNeutrino; - TLorentzVector inNucleonMom(*init_state.TgtPtr()->HitNucP4Ptr()); - TLorentzVector inNucleonMomOnShell(inNucleonMom); - const TLorentzVector leptonMom = kinematics.FSLeptonP4(); - const TLorentzVector outNucleonMom = kinematics.HadSystP4(); - TLorentzVector outNucleonMomOnShell(outNucleonMom); - - double inNucleonOnShellEnergy = TMath::Hypot(M, inNucleonMomOnShell.P() ); - inNucleonMomOnShell.SetE(inNucleonOnShellEnergy); - double outNucleonOnShellEnergy = TMath::Hypot(M, outNucleonMomOnShell.P() ); - outNucleonMomOnShell.SetE(outNucleonOnShellEnergy); - - // Effective 4-momentum transfer (according to the deForest prescription) for - // use in computing the hadronic tensor - TLorentzVector qTildeP4 = outNucleonMomOnShell - inNucleonMomOnShell; - // ****************************** // Now choose which tesor to use // ****************************** @@ -831,9 +804,24 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int else tensor_type_crpa = kHT_QE_HFPW_anu_High; } } + //else + //{ + //if ( pdg::IsProton(hit_nuc_pdg) ) + //{ + //tensor_type_susa = kHT_QE_EM_proton; + //} + //else if( pdg::IsNeutron(hit_nuc_pdg) ) + //{ + //tensor_type_susa = kHT_QE_EM_neutron; + //} + //else + //{ + //tensor_type_susa = kHT_QE_EM; // default + //} + //} else { - LOG("SuSAv2QE", pWARN) << "For EM processes doesn't work yet. Set it to zero."; + LOG("SuSAv2QE", pWARN) << "Doesn't work for processes other than weak ones. Set it to zero."; fFinalLeptonPolarization = TVector3(0, 0, 0); return fFinalLeptonPolarization; } @@ -1062,18 +1050,18 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int } } - double W1_susa(0), W2_susa(0), W3_susa(0), W4_susa(0), W5_susa(0)/*, W6_susa(0)*/; - double W1_crpa(0), W2_crpa(0), W3_crpa(0), W4_crpa(0), W5_crpa(0)/*, W6_crpa(0)*/; - double W1_blen(0), W2_blen(0), W3_blen(0), W4_blen(0), W5_blen(0)/*, W6_blen(0)*/; + double W1_susa(0), W2_susa(0), W3_susa(0), W4_susa(0), W5_susa(0); + double W1_crpa(0), W2_crpa(0), W3_crpa(0), W4_crpa(0), W5_crpa(0); + double W1_blen(0), W2_blen(0), W3_blen(0), W4_blen(0), W5_blen(0); if ( modelConfig == kMd_SuSAv2 ) { W1_susa = tensor_susa->W1(Q0 - Delta_Q_value_susa, Q3, M); W2_susa = tensor_susa->W2(Q0 - Delta_Q_value_susa, Q3, M); - W3_susa = tensor_susa->W3(Q0 - Delta_Q_value_susa, Q3, M); + W3_susa = -tensor_susa->W3(Q0 - Delta_Q_value_susa, Q3, M); // note invert sign W4_susa = tensor_susa->W4(Q0 - Delta_Q_value_susa, Q3, M); W5_susa = tensor_susa->W5(Q0 - Delta_Q_value_susa, Q3, M); -// W6_susa = tensor_susa->W6(Q0 - Delta_Q_value_susa, Q3, M); + double fact_susa = XSecScaling(1.0, interaction, target_pdg, tensor_pdg_susa, need_to_scale_susa); W1_susa *= fact_susa; W2_susa *= fact_susa; @@ -1087,10 +1075,10 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int { W1_blen = tensor_blen->W1(Q0 - Delta_Q_value_blen, Q3, M); W2_blen = tensor_blen->W2(Q0 - Delta_Q_value_blen, Q3, M); - W3_blen = tensor_blen->W3(Q0 - Delta_Q_value_blen, Q3, M); + W3_blen = -tensor_blen->W3(Q0 - Delta_Q_value_blen, Q3, M); // note invert sign W4_blen = tensor_blen->W4(Q0 - Delta_Q_value_blen, Q3, M); W5_blen = tensor_blen->W5(Q0 - Delta_Q_value_blen, Q3, M); -// W6_blen = tensor_blen->W6(Q0 - Delta_Q_value_blen, Q3, M); + // The blended SuSAv2 calculation already gives the xsec per atom // For the A-scaling below to make sense we need to transform them to per active nucleon int A_tensor = pdg::IonPdgCodeToA(tensor_pdg_crpa); @@ -1110,10 +1098,10 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int { W1_crpa = tensor_crpa->W1(Q0 - Delta_Q_value_crpa, Q3, M); W2_crpa = tensor_crpa->W2(Q0 - Delta_Q_value_crpa, Q3, M); - W3_crpa = tensor_crpa->W3(Q0 - Delta_Q_value_crpa, Q3, M); + W3_crpa = -tensor_crpa->W3(Q0 - Delta_Q_value_crpa, Q3, M); // note invert sign W4_crpa = tensor_crpa->W4(Q0 - Delta_Q_value_crpa, Q3, M); W5_crpa = tensor_crpa->W5(Q0 - Delta_Q_value_crpa, Q3, M); -// W6_crpa = tensor_crpa->W6(Q0 - Delta_Q_value_crpa, Q3, M); + // The CRPA calculation already gives the xsec per atom // For the A-scaling below to make sense we need to transform them to per active nucleon int A_tensor = pdg::IonPdgCodeToA(tensor_pdg_crpa); @@ -1131,7 +1119,7 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int } // Apply blending if needed - double W1(0), W2(0), W3(0), W4(0), W5(0)/*, W6(0)*/; + double W1(0), W2(0), W3(0), W4(0), W5(0); if ( modelConfig == kMd_SuSAv2 ) { @@ -1140,7 +1128,6 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W3 = W3_susa; W4 = W4_susa; W5 = W5_susa; -// W6 = W6_susa; } if ( modelConfig == kMd_SuSAv2Blend ) @@ -1150,7 +1137,6 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W3 = W3_blen; W4 = W4_blen; W5 = W5_blen; -// W6 = W6_blen; } if( modelConfig == kMd_CRPA || modelConfig == kMd_HF || modelConfig == kMd_CRPAPW || modelConfig == kMd_HFPW ) @@ -1160,7 +1146,6 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W3 = W3_crpa; W4 = W4_crpa; W5 = W5_crpa; -// W6 = W6_crpa; } else if( modelConfig == kMd_CRPASuSAv2Hybrid || modelConfig == kMd_HFSuSAv2Hybrid || @@ -1176,7 +1161,6 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W3 = W3_crpa; W4 = W4_crpa; W5 = W5_crpa; -// W6 = W6_crpa; } else if (Q0 > q0BlendEnd) { @@ -1185,7 +1169,6 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W3 = W3_blen; W4 = W4_blen; W5 = W5_blen; -// W6 = W6_blen; } else { @@ -1196,7 +1179,6 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W3 = SuSAFrac*W3_blen + CRPAFrac*W3_crpa; W4 = SuSAFrac*W4_blen + CRPAFrac*W4_crpa; W5 = SuSAFrac*W5_blen + CRPAFrac*W5_crpa; -// W6 = SuSAFrac*W6_blen + CRPAFrac*W6_crpa; } else if(blendMode == 2) { // Exp blending in q (from Alexis) @@ -1208,152 +1190,24 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int W3 = sn2*W3_blen + cn2*W3_crpa; W4 = sn2*W4_blen + cn2*W4_crpa; W5 = sn2*W5_blen + cn2*W5_crpa; -// W6 = sn2*W6_blen + cn2*W6_crpa; - } - } - - double p[4], q[4], epq[4][4], k[4], l[4], s[4], eskl[4]; - std::complex jp[4], jm[4]; - - p[0] = inNucleonMomOnShell.E(); - p[1] = inNucleonMomOnShell.Px(); - p[2] = inNucleonMomOnShell.Py(); - p[3] = inNucleonMomOnShell.Pz(); - - q[0] = qTildeP4.E(); - q[1] = qTildeP4.Px(); - q[2] = qTildeP4.Py(); - q[3] = qTildeP4.Pz(); - - k[0] = neutrinoMom.E(); - k[1] = -neutrinoMom.Px(); - k[2] = -neutrinoMom.Py(); - k[3] = -neutrinoMom.Pz(); - - l[0] = leptonMom.E(); - l[1] = -leptonMom.Px(); - l[2] = -leptonMom.Py(); - l[3] = -leptonMom.Pz(); - - s[0] = leptonMom.P()/ml; - s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; - s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; - s[3] = -leptonMom.Vect().Unit().Z()*leptonMom.E()/ml; - - // epsilon^\alpha\beta\gamma\delta p_\gamma q_\delta - for (int a = 0; a < 4; a++) - { - for (int b = 0; b < 4; b++) - { - epq[a][b] = 0; - if (b == a) continue; - for (int g = 0; g < 4; g++) - { - if (g == b || g == a) continue; - for (int d = 0; d < 4; d++) - { - if (d == g || d == b || d == a) continue; - epq[a][b] += e(a,b,g,d)*(a == 0?1:-1)*(b == 0?1:-1)*p[g]*q[d]; - } - } - } - } - - // epsilon_\alpha\beta\gamma\delta s^\beta k^\gamma l^\delta - for (int a = 0; a < 4; a++) - { - eskl[a] = 0; - for (int b = 0; b < 4; b++) - { - if (b == a) continue; - for (int g = 0; g < 4; g++) - { - if (g == b || g == a) continue; - for (int d = 0; d < 4; d++) - { - if (d == g || d == b || d == a) continue; - double sb = s[b]*(b == 0?1:-1); - double kg = k[g]*(g == 0?1:-1); - double ld = l[d]*(d == 0?1:-1); - eskl[a] += e(a,b,g,d)*sb*kg*ld; - } - } - } - } - - double kl = k[0]*l[0] - k[1]*l[1] - k[2]*l[2] - k[3]*l[3]; - double ks = k[0]*s[0] - k[1]*s[1] - k[2]*s[2] - k[3]*s[3]; - - for (int a = 0; a < 4; a++) - { - if (is_neutrino) - { - jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha - jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha - } - else - { - jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha - jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha - } - } - - - //Additional constants and variables - std::complex Wmunu, Wnumu, LWpp(0, 0), LWpm(0, 0), LWmp(0, 0), LWmm(0, 0); - for(int mu = 0; mu < 4; mu++) - { - for(int nu = mu;nu < 4; nu++) - { - double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/M2 + q[mu]*q[nu]*W4/M2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/M2; - double Wimag = epq[mu][nu]*W3/2/M2; - Wmunu = Wreal - 1i*Wimag; // W^\mu\nu - LWpp += jp[mu]*std::conj(jp[nu])*Wmunu; // Lpp_\mu\nu*W^\mu\nu - LWpm += jp[mu]*std::conj(jm[nu])*Wmunu; // Lpm_\mu\nu*W^\mu\nu - LWmp += jm[mu]*std::conj(jp[nu])*Wmunu; // Lmp_\mu\nu*W^\mu\nu - LWmm += jm[mu]*std::conj(jm[nu])*Wmunu; // Lmm_\mu\nu*W^\mu\nu - if (mu != nu) - { - Wnumu = Wreal + 1i*Wimag; - LWpp += jp[nu]*std::conj(jp[mu])*Wnumu; // Lpp_\mu\nu*W^\mu\nu - LWpm += jp[nu]*std::conj(jm[mu])*Wnumu; // Lpm_\mu\nu*W^\mu\nu - LWmp += jm[nu]*std::conj(jp[mu])*Wnumu; // Lmp_\mu\nu*W^\mu\nu - LWmm += jm[nu]*std::conj(jm[mu])*Wnumu; // Lmm_\mu\nu*W^\mu\nu - } } } - std::complex LWppmm = LWpp + LWmm; - std::complex rhopp = LWpp/LWppmm; - std::complex rhopm = LWpm/LWppmm; - std::complex rhomp = LWmp/LWppmm; - std::complex rhomm = LWmm/LWppmm; - double PL = std::real(rhopp - rhomm); - double PP = std::real(rhopm + rhomp); - double PT = std::imag(rhomp - rhopm); - - TVector3 neutrinoMom3 = neutrinoMom.Vect(); - TVector3 leptonMom3 = leptonMom.Vect(); - TVector3 Pz = leptonMom3.Unit(); - TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); - TVector3 Py = Pz.Cross(Px); - TVector3 pol = PT*Px + PP*Py + PL*Pz; - fFinalLeptonPolarization = pol; + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + genie::utils::CalculatePolarizationVectorInTargetRestFrame( + fFinalLeptonPolarization, + neutrinoMom, + leptonMom, + is_neutrino, + M, W1,W2,W3,W4,W5,0); + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << "PL = " << PL << ", PT = " << PT << ", PP = " << PP << "\n"; std::cout << fFinalLeptonPolarization.Mag() << "\n"; std::cout << "SU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } -//____________________________________________________________________________ -inline int SuSAv2QELPXSec::g(int a, int b) const -{ - return (a==b)*(2*(a==0) - 1); -} -//____________________________________________________________________________ -inline int SuSAv2QELPXSec::e(int a, int b, int c, int d) const -{ - return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; -} -//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.h b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.h index e0578c37c4..a8a67ca1cf 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.h +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.h @@ -28,8 +28,6 @@ #ifndef _SUSAV2_QE_PXSEC_H_ #define _SUSAV2_QE_PXSEC_H_ -#include - #include "Framework/EventGen/XSecAlgorithmI.h" #include "Physics/HadronTensors/HadronTensorI.h" #include "Physics/HadronTensors/HadronTensorModelI.h" @@ -67,8 +65,6 @@ class SuSAv2QELPXSec : public XSecAlgorithmI { // (A-scaling with tuning based on Fermi momentum) double XSecScaling(double xsec, const Interaction* i, int target_pdg, int tensor_pdg, bool need_to_scale) const; - int e(int a, int b, int c, int d) const; - int g(int a, int b) const; /// External scaling factor for this cross section double fXSecCCScale; diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx index 5ffcc4f392..b649f62bfc 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx @@ -7,7 +7,6 @@ Tufts University */ //____________________________________________________________________________ - #include #include "Framework/Algorithm/AlgConfigPool.h" @@ -28,11 +27,11 @@ #include "Physics/QuasiElastic/XSection/QELFormFactors.h" #include "Physics/QuasiElastic/XSection/QELFormFactorsModelI.h" #include "Physics/Strange/XSection/PaisQELLambdaPXSec.h" +#include "Physics/Common/PrimaryLeptonUtils.h" using namespace genie; using namespace genie::constants; using namespace genie::utils; -using namespace std::complex_literals; //____________________________________________________________________________ PaisQELLambdaPXSec::PaisQELLambdaPXSec() : @@ -243,7 +242,6 @@ void PaisQELLambdaPXSec::LoadConfig(void) const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* interaction) const { if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - double ml = interaction->FSPrimLepton()->Mass(); // First we need access to all of the particles in the interaction // The particles were stored in the lab frame //----- get kinematics & init state - compute auxiliary vars @@ -291,7 +289,6 @@ const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* double Mm2 = Mm*Mm; double Mp2 = Mp*Mp; double M = 0.5*Mp; - double M2 = M*M; //Powers of Form Factors double FA2 = FA*FA; @@ -300,150 +297,20 @@ const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* double W1 = (Mm2 - q2)*TMath::Sq(F1V + xiF2V)/4/Mnuc2 + (Mp2 - q2)*FA2/4/Mnuc2; double W2 = FA2 + TMath::Sq(F1V + xiF2V - Mp*xiF2V/2/Mnuc) - q2*xiF2V*xiF2V/4/Mnuc2; double W3 = 2*FA*(F1V + xiF2V); - double W4(0), W5(0); - - - double p[4], q[4], epq[4][4], k[4], l[4], s[4], eskl[4]; - std::complex jp[4], jm[4]; - - p[0] = inNucleonMom.E(); - p[1] = inNucleonMom.Px(); - p[2] = inNucleonMom.Py(); - p[3] = inNucleonMom.Pz(); - - q[0] = qP4.E(); - q[1] = qP4.Px(); - q[2] = qP4.Py(); - q[3] = qP4.Pz(); - - k[0] = neutrinoMom.E(); - k[1] = -neutrinoMom.Px(); - k[2] = -neutrinoMom.Py(); - k[3] = -neutrinoMom.Pz(); - l[0] = leptonMom.E(); - l[1] = -leptonMom.Px(); - l[2] = -leptonMom.Py(); - l[3] = -leptonMom.Pz(); - - s[0] = leptonMom.P()/ml; - s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; - s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; - s[3] = -leptonMom.Vect().Unit().Z()*leptonMom.E()/ml; - - // epsilon^\alpha\beta\gamma\delta p_\gamma q_\delta - for (int a = 0; a < 4; a++) - { - for (int b = 0; b < 4; b++) - { - epq[a][b] = 0; - if (b == a) continue; - for (int g = 0; g < 4; g++) - { - if (g == b || g == a) continue; - for (int d = 0; d < 4; d++) - { - if (d == g || d == b || d == a) continue; - epq[a][b] += e(a,b,g,d)*(a == 0?1:-1)*(b == 0?1:-1)*p[g]*q[d]; - } - } - } - } - - // epsilon_\alpha\beta\gamma\delta s^\beta k^\gamma l^\delta - for (int a = 0; a < 4; a++) - { - eskl[a] = 0; - for (int b = 0; b < 4; b++) - { - if (b == a) continue; - for (int g = 0; g < 4; g++) - { - if (g == b || g == a) continue; - for (int d = 0; d < 4; d++) - { - if (d == g || d == b || d == a) continue; - double sb = s[b]*(b == 0?1:-1); - double kg = k[g]*(g == 0?1:-1); - double ld = l[d]*(d == 0?1:-1); - eskl[a] += e(a,b,g,d)*sb*kg*ld; - } - } - } - } - - double kl = k[0]*l[0] - k[1]*l[1] - k[2]*l[2] - k[3]*l[3]; - double ks = k[0]*s[0] - k[1]*s[1] - k[2]*s[2] - k[3]*s[3]; - - for (int a = 0; a < 4; a++) - { - if (is_neutrino) - { - jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha - jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha - } - else - { - jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha - jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha - } - } - - //Additional constants and variables - std::complex Wmunu, Wnumu, LWpp(0, 0), LWpm(0, 0), LWmp(0, 0), LWmm(0, 0); - for(int mu = 0; mu < 4; mu++) - { - for(int nu = mu;nu < 4; nu++) - { - double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/M2 + q[mu]*q[nu]*W4/M2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/M2; - double Wimag = epq[mu][nu]*W3/2/M2; - Wmunu = Wreal - 1i*Wimag; // W^\mu\nu - LWpp += jp[mu]*std::conj(jp[nu])*Wmunu; // Lpp_\mu\nu*W^\mu\nu - LWpm += jp[mu]*std::conj(jm[nu])*Wmunu; // Lpm_\mu\nu*W^\mu\nu - LWmp += jm[mu]*std::conj(jp[nu])*Wmunu; // Lmp_\mu\nu*W^\mu\nu - LWmm += jm[mu]*std::conj(jm[nu])*Wmunu; // Lmm_\mu\nu*W^\mu\nu - if (mu != nu) - { - Wnumu = Wreal + 1i*Wimag; - LWpp += jp[nu]*std::conj(jp[mu])*Wnumu; // Lpp_\mu\nu*W^\mu\nu - LWpm += jp[nu]*std::conj(jm[mu])*Wnumu; // Lpm_\mu\nu*W^\mu\nu - LWmp += jm[nu]*std::conj(jp[mu])*Wnumu; // Lmp_\mu\nu*W^\mu\nu - LWmm += jm[nu]*std::conj(jm[mu])*Wnumu; // Lmm_\mu\nu*W^\mu\nu - } - } - } - std::complex LWppmm = LWpp + LWmm; - std::complex rhopp = LWpp/LWppmm; - std::complex rhopm = LWpm/LWppmm; - std::complex rhomp = LWmp/LWppmm; - std::complex rhomm = LWmm/LWppmm; - double PL = std::real(rhopp - rhomm); - double PP = std::real(rhopm + rhomp); - double PT = std::imag(rhomp - rhopm); + CalculatePolarizationVectorWithStructureFunctions( + fFinalLeptonPolarization, + neutrinoMom, + leptonMom, + inNucleonMom, + qP4, + is_neutrino, + M, W1,W2,W3,0,0,0); - TVector3 neutrinoMom3 = neutrinoMom.Vect(); - TVector3 leptonMom3 = leptonMom.Vect(); - TVector3 Pz = leptonMom3.Unit(); - TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); - TVector3 Py = Pz.Cross(Px); - TVector3 pol = PT*Px + PP*Py + PL*Pz; - fFinalLeptonPolarization = pol; std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << "PL = " << PL << ", PT = " << PT << ", PP = " << PP << "\n"; std::cout << fFinalLeptonPolarization.Mag() << "\n"; std::cout << "PL@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } -//____________________________________________________________________________ -inline int PaisQELLambdaPXSec::g(int a, int b) const -{ - return (a==b)*(2*(a==0) - 1); -} -//____________________________________________________________________________ -inline int PaisQELLambdaPXSec::e(int a, int b, int c, int d) const -{ - return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; -} -//____________________________________________________________________________ diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h index 5b3a5654c3..b5aaf54f0c 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h @@ -31,8 +31,6 @@ #include "Framework/EventGen/XSecAlgorithmI.h" #include "Physics/QuasiElastic/XSection/QELFormFactors.h" -#include - namespace genie { class QELFormFactorsModelI; @@ -51,8 +49,6 @@ class PaisQELLambdaPXSec : public XSecAlgorithmI { bool ValidProcess (const Interaction * i) const; bool ValidKinematics (const Interaction * i) const; const TVector3 & FinalLeptonPolarization (const Interaction* i) const; - int e(int a, int b, int c, int d) const; - int g(int a, int b) const; //-- override the Algorithm::Configure methods to load configuration // data to private data members From f9d32e61a58ddfdb556f22a3377863cb2a4cb8ff Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 13 Jan 2025 18:58:45 +0300 Subject: [PATCH 11/78] now averaged nucleus tensor is used to calculate polarization --- src/Physics/Common/PrimaryLeptonUtils.cxx | 2 +- .../XSection/NievesQELCCPXSec.cxx | 624 ++++++++++++------ .../QuasiElastic/XSection/NievesQELCCPXSec.h | 23 + 3 files changed, 446 insertions(+), 203 deletions(-) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 1c66ab1b44..4fb7eced36 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -282,7 +282,7 @@ void genie::utils::CalculatePolarizationVectorInTargetRestFrame( TVector3 Py = Pz.Cross(Px); polarization = PT*Px + PP*Py + PL*Pz; std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << ", R =" << R << "\n"; + std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << ", R = " << R << "\n"; std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; } //____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 61ebb2db5e..2ab9df5ac4 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -31,8 +31,8 @@ #include "Physics/QuasiElastic/XSection/NievesQELCCPXSec.h" #include "Framework/Numerical/RandomGen.h" #include "Framework/ParticleData/PDGCodes.h" -#include "Framework/ParticleData/PDGLibrary.h" #include "Framework/ParticleData/PDGUtils.h" +#include "Framework/ParticleData/PDGLibrary.h" #include "Framework/Numerical/MathUtils.h" #include "Framework/Utils/KineUtils.h" #include "Physics/NuclearState/NuclearUtils.h" @@ -832,60 +832,80 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, //____________________________________________________________________________ // Gives coulomb potential in units of GeV -double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const{ - if(target->IsNucleus()){ +double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const +{ + double Rmax = MaximalRadius(target); + if (Rmax == 0) return 0; + if(Rcurr >= Rmax) + { + LOG("Nieves",pNOTICE) << "Radius greater than maximum radius for coulomb corrections." + << " Integrating to max radius."; + Rcurr = Rmax; + } + int A = target->A(); int Z = target->Z(); + ROOT::Math::IBaseFunctionOneDim * func = new + utils::gsl::wrap::NievesQELvcrIntegrand(Rcurr,A,Z); + ROOT::Math::IntegrationOneDim::Type ig_type = + utils::gsl::Integration1DimTypeFromString("adaptive"); + + double abstol = 1; // We mostly care about relative tolerance; + double reltol = 1E-4; + int nmaxeval = 100000; + ROOT::Math::Integrator ig(*func,ig_type,abstol,reltol,nmaxeval); + double result = ig.Integral(0,Rmax); + delete func; + + // Multiply by Z to normalize densities to number of protons + // Multiply by hbarc to put result in GeV instead of fm + // Multiply by an extra configurable scaling factor that defaults to unity + return -kAem*4*kPi*result*fhbarc*fCoulombScale; + +} +//____________________________________________________________________________ +double NievesQELCCPXSec::MaximalRadius(const Target * target) const +{ + if(target->IsNucleus()) + { + int A = target->A(); double Rmax = 0.; - if ( fCoulombRmaxMode == kMatchNieves ) { + if ( fCoulombRmaxMode == kMatchNieves ) + { // Rmax calculated using formula from Nieves' fortran code and default // charge and neutron matter density parameters from NuclearUtils.cxx - if (A > 20) { + if (A > 20) + { double c = TMath::Power(A,0.35), z = 0.54; Rmax = c + 9.25*z; } - else { + else + { // c = 1.75 for A <= 20 Rmax = TMath::Sqrt(20.0)*1.75; } } - else if ( fCoulombRmaxMode == kMatchVertexGeneratorRmax ) { + else if ( fCoulombRmaxMode == kMatchVertexGeneratorRmax ) + { // TODO: This solution is fragile. If the formula used by VertexGenerator // changes, then this one will need to change too. Switch to using // a common function to get Rmax for both. Rmax = 3. * fR0 * std::pow(A, 1./3.); } - else { + else + { LOG("Nieves", pFATAL) << "Unrecognized setting for fCoulombRmaxMode encountered" << " in NievesQELCCPXSec::vcr()"; gAbortingInErr = true; std::exit(1); } + + return Rmax; - if(Rcurr >= Rmax){ - LOG("Nieves",pNOTICE) << "Radius greater than maximum radius for coulomb corrections." - << " Integrating to max radius."; - Rcurr = Rmax; - } - - ROOT::Math::IBaseFunctionOneDim * func = new - utils::gsl::wrap::NievesQELvcrIntegrand(Rcurr,A,Z); - ROOT::Math::IntegrationOneDim::Type ig_type = - utils::gsl::Integration1DimTypeFromString("adaptive"); - - double abstol = 1; // We mostly care about relative tolerance; - double reltol = 1E-4; - int nmaxeval = 100000; - ROOT::Math::Integrator ig(*func,ig_type,abstol,reltol,nmaxeval); - double result = ig.Integral(0,Rmax); - delete func; - - // Multiply by Z to normalize densities to number of protons - // Multiply by hbarc to put result in GeV instead of fm - // Multiply by an extra configurable scaling factor that defaults to unity - return -kAem*4*kPi*result*fhbarc*fCoulombScale; - }else{ + } + else + { // If target is not a nucleus the potential will be 0 return 0.0; } @@ -1205,6 +1225,39 @@ ROOT::Math::IBaseFunctionOneDim * { return new utils::gsl::wrap::NievesQELvcrIntegrand(fRcurr,fA,fZ); } + +//____________________________________________________________________________ +utils::gsl::wrap::NievesQELSmithMonizIntegrand::NievesQELSmithMonizIntegrand( + const NievesQELCCPXSec* alg_, const Interaction* interaction_, int mu_, int nu_): +ROOT::Math::IBaseFunctionOneDim(), +alg(alg_), +interaction(interaction_), +mu(mu_), +nu(nu_) +{ + +} +//____________________________________________________________________________ +utils::gsl::wrap::NievesQELSmithMonizIntegrand::~NievesQELSmithMonizIntegrand() +{ + +} +//____________________________________________________________________________ +unsigned int utils::gsl::wrap::NievesQELSmithMonizIntegrand::NDim(void) const +{ + return 1; +} +//____________________________________________________________________________ +double utils::gsl::wrap::NievesQELSmithMonizIntegrand::DoEval(double rin) const +{ + return alg->IntegratedAmunuOverMomentum(interaction, rin, mu, nu); +} +//____________________________________________________________________________ +ROOT::Math::IBaseFunctionOneDim * + utils::gsl::wrap::NievesQELSmithMonizIntegrand::Clone(void) const +{ + return new utils::gsl::wrap::NievesQELSmithMonizIntegrand(alg, interaction, mu, nu); +} //____________________________________________________________________________ //____________________________________________________________________________ @@ -1327,23 +1380,115 @@ void NievesQELCCPXSec::CompareNievesTensors(const Interaction* in) //____________________________________________________________________________ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { - if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); // Get kinematics and init-state parameters const Kinematics & kinematics = interaction -> Kine(); const InitialState & init_state = interaction -> InitState(); const Target & target = init_state.Tgt(); + + const double M = 1; // polarization doesn't depend on M + // common factor will be reduced + //double factor = fCos8c2*M*Omega/pl/El/kPi/4; + double Rmax = MaximalRadius(&target); + double W00, Wxx, Wzz, ReW0z, ImWxy; + if (!target.IsNucleus() || Rmax <= 0) + { + FinalLeptonPolarizationOnFreeNucleon (interaction, W00, Wxx, Wzz, ReW0z, ImWxy); + } + else + { + ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString("adaptive"); + double reltol = 1E-4; + int nmaxeval = 100000; + + ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 0, 0); + ROOT::Math::Integrator ig(*func,ig_type,0,reltol,nmaxeval); + W00 = ig.Integral(0, Rmax); + delete func; + + func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 1, 1); + ig.SetFunction(*func); + Wxx = ig.Integral(0, Rmax); + delete func; + + func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 3, 3); + ig.SetFunction(*func); + Wzz = ig.Integral(0, Rmax); + delete func; + + func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 0, 3); + ig.SetFunction(*func); + ReW0z = ig.Integral(0, Rmax); + delete func; + + func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 1, 2); + ig.SetFunction(*func); + ImWxy= ig.Integral(0, Rmax); + delete func; + } + + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + + TLorentzVector q4 = neutrinoMom - leptonMom; + + double q0 = q4.E(); + double q = q4.Vect().Mag(); + double q02 = q0*q0; + double q2 = q*q; + + double T1 = Wxx/2/M; + double T2 = (W00 + Wxx + q02/q2*(Wzz - Wxx) - 2*q0/q*ReW0z)/2/M; + double T3 = -ImWxy/q; + double T4 = M/2/q2*(Wzz - Wxx); + double T5 = (ReW0z - q0/q*(Wzz - Wxx))/q; + + + if (T1 != 0 || T2!=0 || T3!=0 || T4!=0 || T5!=0) + { + CalculatePolarizationVectorInTargetRestFrame( + fFinalLeptonPolarization, + neutrinoMom, + leptonMom, + is_neutrino, + M, T1,T2,T3,T4,T5,0); + } + else + { + LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; + fFinalLeptonPolarization = TVector3(0, 0, 0); + } + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + std::cout << fFinalLeptonPolarization.Mag() << "\n"; + std::cout << "NV@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + + return fFinalLeptonPolarization; + +} +//___________________________________________________________________________________ +void NievesQELCCPXSec::FinalLeptonPolarizationOnFreeNucleon (const Interaction* interaction, double & A00, double & Axx, double & Azz, double & A0z, double & Axy) const +{ + + A00 = Axx = Azz = A0z = Axy = 0; + // Get kinematics and init-state parameters + const Kinematics & kinematics = interaction -> Kine(); + const InitialState & init_state = interaction -> InitState(); + const Target & target = init_state.Tgt(); // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial // struck nucleon - double Mi_onshell = target.HitNucMass(); + double Mi = target.HitNucMass(); // On-shell mass of final nucleon (from PDGLibrary) double Mf = interaction->RecoilNucleon()->Mass(); // Isoscalar mass of nucleon - double M = (Mi_onshell + Mf)/2; + double M = (Mi + Mf)/2; // Note that GetProbeP4 defaults to returning the probe 4-momentum in the // struck nucleon rest frame, so we have to explicitly ask for the lab frame @@ -1352,27 +1497,144 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i TLorentzVector neutrinoMom = *tempNeutrino; delete tempNeutrino; TLorentzVector inNucleonMom(*init_state.TgtPtr()->HitNucP4Ptr()); - TLorentzVector inNucleonMomOnShell(inNucleonMom); TLorentzVector leptonMom = kinematics.FSLeptonP4(); TLorentzVector outNucleonMom = kinematics.HadSystP4(); - // Apply Pauli blocking if enabled - if ( fDoPauliBlocking && target.IsNucleus() && !interaction->TestBit(kIAssumeFreeNucleon) ) { - int final_nucleon_pdg = interaction->RecoilNucleonPdg(); - double kF = fPauliBlocker->GetFermiMomentum(target, final_nucleon_pdg, target.HitNucPosition()); - double pNf = outNucleonMom.P(); - if ( pNf < kF ) - { - LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; - } + + double outNucleonEnergy = TMath::Hypot(M, outNucleonMom.P() ); + + double q0Tilde = outNucleonEnergy - M; + + // Note that we're working in the lab frame (i.e., the rest frame + // of the target nucleus). We can therefore use Nieves' explicit + // form of the Amunu tensor if we rotate the 3-momenta so that + // qTilde is in the +z direction + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + + // If Coulomb corrections are being used, adjust the lepton 3-momentum used + // to get q3VecTilde so that its magnitude matches the local + // Coulomb-corrected value calculated earlier. Note that, although the + // treatment of Coulomb corrections by Nieves et al. doesn't change the + // direction of the lepton 3-momentum, it *does* change the direction of the + // 3-momentum transfer, and so the correction should be applied *before* + // rotating coordinates into a frame where q3VecTilde lies along the positive + // z axis. + TVector3 q3VecTilde = neutrinoMom3 - leptonMom3; + + // Find the rotation angle needed to put q3VecTilde along z + TVector3 zvec(0, 0, 1); + TVector3 rot = ( q3VecTilde.Cross(zvec) ).Unit(); // Vector to rotate about + // Angle between the z direction and q + double angle = zvec.Angle( q3VecTilde ); + + // Handle the edge case where q3VecTilde is along -z, so the + // cross product above vanishes + if ( q3VecTilde.Perp() == 0. && q3VecTilde.Z() < 0. ) + { + rot = TVector3(0., 1., 0.); + angle = kPi; } - double outNucleonEnergy = outNucleonMom.E(); - double inNucleonOnShellEnergy = TMath::Hypot(M, inNucleonMomOnShell.P() ); - outNucleonEnergy = TMath::Hypot(M, outNucleonMom.P() ); + // Rotate if the rotation vector is not 0 + if ( rot.Mag() > 0 ) + { + neutrinoMom3.Rotate(angle,rot); + neutrinoMom.SetVect(neutrinoMom3); + leptonMom3.Rotate(angle,rot); + leptonMom.SetVect(leptonMom3); + } + + // Calculate qTilde + TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); + + double Q2 = interaction->KinePtr()->Q2(true); + double Q2tilde = -qTildeP4.Mag2(); + + // Check that Q2tilde > 0 (accounting for rounding errors) + if (Q2tilde < 0) + { + return; + } + + // Store Q2tilde in the kinematic variable representing Q2. + // This will ensure that the form factors are calculated correctly + // using the de Forest prescription (Q2tilde instead of Q2). + interaction->KinePtr()->SetQ2(Q2tilde); + // Calculate form factors + fFormFactors.Calculate( interaction ); + // Now that the form factors have been calculated, store Q2 + // in the event instead of Q2tilde + interaction->KinePtr()->SetQ2(Q2); + + + // Get the QEL form factors (were calculated before this method was called) + double F1V = 0.5*fFormFactors.F1V(); + double xiF2V = 0.5*fFormFactors.xiF2V(); + double FA = fFormFactors.FA(); + // According to Nieves' paper, Fp = 2.0*M*FA/(kPionMass2-q2), but Llewelyn- + // Smith uses Fp = 2.0*M^2*FA/(kPionMass2-q2), so I divide by M + // This gives units of GeV^-1 + double Fp = fFormFactors.Fp()/M; + + // Calculate auxiliary parameters + // Off shell mass of initial nucleon + double M2 = M*M; + double FA2 = FA*FA; + double F1V2 = F1V*F1V; + double xiF2V2 = xiF2V*xiF2V; + double q0 = qTildeP4.E(); + double dq = qTildeP4.Pz(); + double q02 = q0*q0; + double dq2 = dq*dq; + double q2 = q02 - dq2; + + double aux1 = 2*Fp*(Fp*q2 + 4*FA*M); + A00 = 32*F1V2*(M2 + q0*M + q2/4) + 8*q2*xiF2V2*(-q0/M - q02*(1/q2 + 1/M2/4)) + + 8*FA2*(q0*M + q2/4) - aux1*q02 - 16*F1V*xiF2V*dq2; + Axx = 8*(FA2*M2 - q2*( (F1V+xiF2V)*(F1V+xiF2V) + FA2/4 ) ); + Azz = -8*F1V2*q2 - 8*q2*xiF2V2*(1 + dq2*(1/q2 + 1/M2/4))+ + 8*FA2*(M2 - q2/4) - aux1*dq2 - 16*F1V*xiF2V*q02; + A0z = 16*F1V2*M*dq - 4*q2*xiF2V2*(dq/M + dq*q0*(2/q2 + 1/M2/2)) + + 4*FA2*M*dq - dq*q0*(aux1 + 16*F1V*xiF2V); + Axy = 16*FA*(xiF2V+F1V)*dq*M; + + return; +} +//___________________________________________________________________________________ +double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interaction, double r, int mu, int nu) const +{ + // Get kinematics and init-state parameters + const Kinematics & kinematics = interaction -> Kine(); + const InitialState & init_state = interaction -> InitState(); + const Target & target = init_state.Tgt(); + + // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial + // struck nucleon + double Mi_onshell = target.HitNucMass(); + + // On-shell mass of final nucleon (from PDGLibrary) + double Mf = interaction->RecoilNucleon()->Mass(); + + // Isoscalar mass of nucleon + double M = (Mi_onshell + Mf)/2; + + // Note that GetProbeP4 defaults to returning the probe 4-momentum in the + // struck nucleon rest frame, so we have to explicitly ask for the lab frame + // here + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + TLorentzVector inNucleonMom(*init_state.TgtPtr()->HitNucP4Ptr()); + + TLorentzVector leptonMom = kinematics.FSLeptonP4(); + TLorentzVector outNucleonMom = kinematics.HadSystP4(); + + double outNucleonEnergy = TMath::Hypot(M, outNucleonMom.P() ); + double inNucleonOnShellEnergy = TMath::Hypot(M, inNucleonMom.P() ); + + TLorentzVector inNucleonMomOnShell(inNucleonMom); inNucleonMomOnShell.SetE(inNucleonOnShellEnergy); // Calculate Coulomb corrections @@ -1382,21 +1644,20 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); int sign = is_neutrino ? 1 : -1; - double r = target.HitNucPosition(); + + double ElLocal = leptonMom.E(); if ( fCoulomb ) { // Coulomb potential - double Vc = vcr(& target, r); + double Vc = vcr(&target, r); // Outgoing lepton energy and momentum including Coulomb potential - double El = leptonMom.E(); - double ElLocal = El - sign*Vc; + double El = ElLocal; + ElLocal = El - sign*Vc; if ( ElLocal - ml <= 0. ) { - LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; + return 0; } // The Coulomb correction factor blows up as pl -> 0. To guard against @@ -1406,9 +1667,7 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i double KEl = El - ml; if ( KEl <= TMath::Abs(Vc) ) { - LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; + return 0; } // Local value of the lepton 3-momentum magnitude for the Coulomb correction @@ -1424,18 +1683,40 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i // // See the original Valencia model paper: // https://journals.aps.org/prc/abstract/10.1103/PhysRevC.70.055503 - double q0Tilde = outNucleonEnergy - inNucleonMomOnShell.E(); - + double q0Tilde = outNucleonEnergy - inNucleonOnShellEnergy; + + int nucl_pdg_ini = target.HitNucPdg(); + + double kFi = fPauliBlocker->GetFermiMomentum(target, nucl_pdg_ini, r); + double kFf = fPauliBlocker->GetFermiMomentum(target, interaction->RecoilNucleonPdg(), r); + double EFi = TMath::Hypot(M, kFi); + double EFf = TMath::Hypot(M, kFf); + + bool tgtIsNucleus = target.IsNucleus(); + int tgt_pdgc = target.Pdg(); + int A = target.A(); + int Z = target.Z(); + int N = target.N(); + bool hitNucIsProton = pdg::IsProton( nucl_pdg_ini ); + + // This part of the code is strictly in accordance with the original Nieves' paper + double Mi = target.Mass(); + int Zf = (hitNucIsProton) ? Z - 1 : Z + 1; + PDGLibrary * pdglib = PDGLibrary::Instance(); + TParticlePDG * nucl_f = pdglib->Find( pdg::IonPdgCode(A, Zf) ); + double Q = 0; + if(nucl_f) Q = nucl_f -> Mass() - Mi; + double Q_LFG = EFf - EFi; + q0Tilde -= (Q - Q_LFG); + // Shift the q0Tilde if required: - if( fQvalueShifter ) q0Tilde *= (1 + fQvalueShifter->Shift(*interaction) ) ; + if( fQvalueShifter ) q0Tilde += q0Tilde * fQvalueShifter->Shift(*interaction) ; // If binding energy effects pull us into an unphysical region, return // zero for the differential cross section - if ( q0Tilde <= 0 && target.IsNucleus() && !interaction->TestBit(kIAssumeFreeNucleon) ) + if ( q0Tilde <= 0 && tgtIsNucleus && !interaction->TestBit(kIAssumeFreeNucleon) ) { - LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; + return 0; } // Note that we're working in the lab frame (i.e., the rest frame @@ -1444,8 +1725,6 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i // qTilde is in the +z direction TVector3 neutrinoMom3 = neutrinoMom.Vect(); TVector3 leptonMom3 = leptonMom.Vect(); - TVector3 inNucleonMom3 = inNucleonMom.Vect(); - TVector3 outNucleonMom3 = outNucleonMom.Vect(); // If Coulomb corrections are being used, adjust the lepton 3-momentum used // to get q3VecTilde so that its magnitude matches the local @@ -1457,6 +1736,8 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i // z axis. TVector3 leptonMomCoulomb3 = !fCoulomb ? leptonMom3: plLocal*leptonMom3*(1/leptonMom3.Mag()); TVector3 q3VecTilde = neutrinoMom3 - leptonMomCoulomb3; + // Calculate qTilde + TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); // Find the rotation angle needed to put q3VecTilde along z TVector3 zvec(0, 0, 1); @@ -1479,25 +1760,15 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i neutrinoMom.SetVect(neutrinoMom3); leptonMom3.Rotate(angle,rot); leptonMom.SetVect(leptonMom3); - inNucleonMom3.Rotate(angle,rot); - inNucleonMom.SetVect(inNucleonMom3); - inNucleonMomOnShell.SetVect(inNucleonMom3); - outNucleonMom3.Rotate(angle,rot); - outNucleonMom.SetVect(outNucleonMom3); } - // Calculate q and qTilde - TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); - double Q2 = interaction->KinePtr()->Q2(true); double Q2tilde = -qTildeP4.Mag2(); // Check that Q2tilde > 0 (accounting for rounding errors) if (Q2tilde < 0) { - LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; + return 0; } // Store Q2tilde in the kinematic variable representing Q2. @@ -1510,13 +1781,6 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i // in the event instead of Q2tilde interaction->KinePtr()->SetQ2(Q2); - bool tgtIsNucleus = target.IsNucleus(); - int tgt_pdgc = target.Pdg(); - int A = target.A(); - int Z = target.Z(); - int N = target.N(); - bool hitNucIsProton = pdg::IsProton( target.HitNucPdg() ); - // Get the QEL form factors (were calculated before this method was called) double F1V = 0.5*fFormFactors.F1V(); @@ -1533,15 +1797,15 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i CNCTCLimUcalc(qTildeP4, M, r, is_neutrino, tgtIsNucleus, tgt_pdgc, A, Z, N, hitNucIsProton, CN, CT, CL, imU, t0, r00, interaction->TestBit( kIAssumeFreeNucleon )); + if ( imU > 0 ) { - LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; - } + return 0; + } - if ( !fRPA || interaction->TestBit( kIAssumeFreeNucleon ) ) { + if ( !fRPA || interaction->TestBit( kIAssumeFreeNucleon ) ) + { CN = 1.0; CT = 1.0; CL = 1.0; @@ -1553,126 +1817,82 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i double FA2 = FA*FA; double F1V2 = F1V*F1V; double xiF2V2 = xiF2V*xiF2V; - const double q[4] = {qTildeP4.E(),qTildeP4.Px(),qTildeP4.Py(),qTildeP4.Pz()}; - double q0 = q[0]; - double dq = TMath::Sqrt(q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); - double q02 = q0*q0; + double q0 = qTildeP4.E(); + double dq = qTildeP4.Pz(); double dq2 = dq*dq; + double q02 = q0*q0; double q2 = q02 - dq2; - double tulin[4]; - double rulin[4][4]; - // For normal code execulation, tulin is the initial nucleon momentum - tulin[0] = inNucleonMomOnShell.E(); - tulin[1] = inNucleonMomOnShell.Px(); - tulin[2] = inNucleonMomOnShell.Py(); - tulin[3] = inNucleonMomOnShell.Pz(); - - for(int i = 0; i < 4; i++) - for(int j = i; j < 4; j++) - rulin[i][j] = rulin[j][i] = tulin[i]*tulin[j]; + double factor = plLocal*ElLocal*r*r/dq; - std::complex Amunu, Anumu; + double c = q0/dq; + double d = q2/2/M/dq; - HermitianMatrix NuclearTensor(4); + double Elow = TMath::Max( EFf - q0, M*(c*d + TMath::Sqrt(1- c*c + d*d))/(1 - c*c) ); + double Eup = EFi; - double aux1 = 2*CL*Fp*(Fp*q2 + 4*FA*M); - double aux2 = 8*(FA2 + 4*F1V2 - xiF2V2*q2/M2); - for(int mu = 0; mu < 4; mu++) + if (Elow >= Eup) { - for(int nu = mu;nu < 4; nu++) - { - if (mu == 0 && nu == 0) - { - Amunu = 32*F1V2*(rulin[0][0]*CN + q[0]*tulin[0] + q2/4)+ - 8*q2*xiF2V2*(1 - rulin[0][0]/M2 - q[0]*tulin[0]/M2 - q02*(1/q2 + 1/4./M2)) + - 8*FA2*(rulin[0][0] + q[0]*tulin[0] + q2/4 - M2)-aux1*q02-16*F1V*xiF2V*(q02 - q2)*CN; - NuclearTensor.set(mu, nu, Amunu); - } - if (mu == 1 && nu == 1) - { - Amunu = 32*F1V2*(rulin[1][1] - q2/4)- - 8*q2*xiF2V2*(CT + rulin[1][1]/M2) + - 8*FA2*(rulin[1][1] + CT*M2 - q2/4)- - 16*F1V*xiF2V*CT*q2; - NuclearTensor.set(mu, nu, Amunu); - } - if (mu == 2 && nu == 2) - { - Amunu = 32*F1V2*(rulin[2][2] - q2/4)- - 8*q2*xiF2V2*(CT + rulin[2][2]/M2) + - 8*FA2*(rulin[2][2] + CT*M2 - q2/4)- - 16*F1V*xiF2V*CT*q2; - NuclearTensor.set(mu, nu, Amunu); - } - if (mu == 3 && nu == 3) - { - Amunu = 32*F1V2*(rulin[3][3] + dq*tulin[3] - q2/4)- - 8*q2*xiF2V2*(1 + rulin[3][3]/M2 + dq*tulin[3]/M2 + dq2*(1/q2 + 1/4./M2))+ - 8*FA2*(rulin[3][3] + dq*tulin[3] + CL*M2 - q2/4) - aux1*dq2 - 16*F1V*xiF2V*q02; - NuclearTensor.set(mu, nu, Amunu); - } - if (mu == 0 && nu == 1) - { - Amunu = aux2*(rulin[0][1] + tulin[1]*q[0]/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[2]*dq; - NuclearTensor.set(mu, nu, Amunu); - - Anumu = aux2*(rulin[0][1] + tulin[1]*q[0]/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[2]*dq; - NuclearTensor.set(nu, mu, Anumu); - } - if (mu == 0 && nu == 2) - { - Amunu = aux2*(rulin[0][2] + tulin[2]*q[0]/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[1]*dq; - NuclearTensor.set(mu, nu, Amunu); - - Anumu = aux2*(rulin[0][2] + tulin[2]*q[0]/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[1]*dq; - NuclearTensor.set(nu, mu, Anumu); - } - if (mu == 0 && nu == 3) - { - Amunu = 16*F1V2*((2*rulin[0][3] + tulin[0]*dq)*CN + tulin[3]*q[0])+ - -4*q2*xiF2V2*(2*rulin[0][3]/M2 + (dq*tulin[0] + q[0]*tulin[3])/M2 + dq*q[0]*(2/q2 + 0.5/M2))+ - 4*FA2*((2*rulin[0][3] + dq*tulin[0])*CL + q[0]*tulin[3]) - dq*q[0]*(aux1 + 16*F1V*xiF2V); - NuclearTensor.set(mu, nu, Amunu); - NuclearTensor.set(nu, mu, Amunu); - } - if (mu == 1 && nu == 2) - { - Amunu = -1i*16.*FA*(xiF2V+F1V)*(q[0]*tulin[3] - dq*tulin[0]*CT) + 8.*rulin[1][2]*(FA2 + 4*F1V2 - xiF2V2*q2/M2); - NuclearTensor.set(mu, nu, Amunu); - NuclearTensor.set(nu, mu, std::conj(Amunu)); - - } - if (mu == 1 && nu == 3) - { - Amunu = aux2*(rulin[1][3] + tulin[1]*dq/2) + 1i*16.*FA*(F1V + xiF2V)*tulin[2]*q[0]; - NuclearTensor.set(mu, nu, Amunu); - NuclearTensor.set(nu, mu, std::conj(Amunu)); - } - - if (mu == 2 && nu == 3) - { - Amunu = aux2*(rulin[2][3] + tulin[2]*dq/2) - 1i*16.*FA*(F1V + xiF2V)*tulin[1]*q[0]; - NuclearTensor.set(mu, nu, Amunu); - NuclearTensor.set(nu, mu, std::conj(Amunu)); - } - } + return 0; } - CalculatePolarizationVectorWithNuclearTensor( - fFinalLeptonPolarization, - neutrinoMom, - leptonMom, - is_neutrino, - NuclearTensor); - - - + double Elow2 = Elow*Elow; + double Elow3 = Elow*Elow2; + double Eup2 = Eup*Eup; + double Eup3 = Eup*Eup2; - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "NV@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - - return fFinalLeptonPolarization; + double b0 = factor*(Eup - Elow); + double b1 = factor/M/2*(Eup2 - Elow2); + double b2 = factor/M2/3*(Eup3 - Elow3); + + double a1 = b0; + double a2 = b2 - b0; + double a3 = c*c*b2 + 2*c*d*b1 + d*d*b0; + double a4 = b2; + double a5 = c*b2 + d*b1; + double a6 = c*b1 + d*b0; + double a7 = b1; + + + double Ep = M*a7; + double Ep2 = M2*a4; + double px2 = 0.5*M2*(a2 - a3); //py2=px2 + double pz = M*a6; + double Eppz = M2*a5; + double pz2 = M2*a3; + + double aux1 = 2*CL*Fp*(Fp*q2 + 4*FA*M); + + if (mu == 0 && nu == 0) + { + return 32*F1V2*(Ep2*CN + Ep*q0 + a1*q2/4)+ + 8*q2*xiF2V2*(a1*(1 - q02*(1/q2 + 1/M2/4)) - Ep2/M2 - Ep*q0/M2) + + 8*FA2*(Ep2 + Ep*q0 + a1*(q2/4 - M2)) - a1*(aux1*q02 + 16*F1V*xiF2V*(q02 - q2)*CN); + } + if ( (mu == 1 && nu == 1) || (mu == 2 && nu == 2) ) + { + return 32*F1V2*(px2 - a1*q2/4)- + 8*q2*xiF2V2*(a1*CT + px2/M2) + + 8*FA2*(px2 + a1*(CT*M2 - q2/4))- + 16*a1*F1V*xiF2V*CT*q2; + } + if (mu == 3 && nu == 3) + { + return 32*F1V2*(pz2 + pz*dq - a1*q2/4)- + 8*q2*xiF2V2*(a1 + pz2/M2 + pz*dq/M2 + a1*dq2*(1/q2 + 1/M2/4))+ + 8*FA2*(pz2 + pz*dq + a1*(CL*M2 - q2/4)) - a1*(aux1*dq2 + 16*F1V*xiF2V*q02); + } + if (mu == 0 && nu == 3) + { + return 16*F1V2*((2*Eppz + Ep*dq)*CN + pz*q0) + -4*q2*xiF2V2*(2*Eppz/M2 + (Ep*dq + pz*q0)/M2 + a1*dq*q0*(2/q2 + 1/M2/2))+ + 4*FA2*((2*Eppz + Ep*dq)*CL + pz*q0) - a1*dq*q0*(aux1 + 16*F1V*xiF2V); + } + if (mu == 1 && nu == 2) // should be multiplied by i + { + return -16*FA*(xiF2V+F1V)*(pz*q0 - Ep*dq*CT); + } + return 0; } +//___________________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 888594ecad..a2b6877a48 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -57,6 +57,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + double IntegratedAmunuOverMomentum (const Interaction* interaction, double r, int mu, int nu) const; // Override the Algorithm::Configure methods to load configuration // data to private data members @@ -140,6 +141,8 @@ class NievesQELCCPXSec : public XSecAlgorithmI { // Potential for coulomb correction double vcr(const Target * target, double r) const; + + double MaximalRadius(const Target * target) const; //input must be length 4. Returns 1 if input is an even permutation of 0123, //-1 if input is an odd permutation of 0123, and 0 if any two elements @@ -150,6 +153,10 @@ class NievesQELCCPXSec : public XSecAlgorithmI { const TLorentzVector inNucleonMom, const TLorentzVector leptonMom, const TLorentzVector outNucleonMom, double M, bool is_neutrino, const Target& target, bool assumeFreeNucleon) const; + + void FinalLeptonPolarizationOnFreeNucleon (const Interaction* interaction, + double & A00, double & Axx, double & Azz, + double & A0z, double & Axy) const; // NOTE: THE FOLLOWING CODE IS FOR TESTING PURPOSES ONLY // Used to print tensor elements and various inputs for comparison to Nieves' @@ -195,6 +202,22 @@ namespace genie { double fA; double fZ; }; + + class NievesQELSmithMonizIntegrand : public ROOT::Math::IBaseFunctionOneDim + { + public: + NievesQELSmithMonizIntegrand(const NievesQELCCPXSec* alg_, const Interaction* interaction_, int mu_, int nu_); + ~NievesQELSmithMonizIntegrand(); + // ROOT::Math::IBaseFunctionOneDim interface + unsigned int NDim (void) const; + double DoEval (double rin) const; + ROOT::Math::IBaseFunctionOneDim * Clone (void) const; + private: + const NievesQELCCPXSec* alg; + const Interaction* interaction; + int mu; + int nu; + }; } // wrap namespace } // gsl namespace From 398df2faa7fe4870eb6de14647d7a1d761f5ed4b Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 23 Jan 2025 01:23:39 +0300 Subject: [PATCH 12/78] remove warnings implicitly-declared genie::Range1D_t::operator= is deprecated [-Wdeprecated-copy] --- src/Framework/Utils/Range1.cxx | 21 +++++++++++++++++++++ src/Framework/Utils/Range1.h | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/src/Framework/Utils/Range1.cxx b/src/Framework/Utils/Range1.cxx index 10911c9541..b6fe7ebf03 100644 --- a/src/Framework/Utils/Range1.cxx +++ b/src/Framework/Utils/Range1.cxx @@ -45,6 +45,13 @@ void Range1F_t::Copy(const Range1F_t & r) max = r.max; } //____________________________________________________________________________ +Range1F_t & Range1F_t::operator=(const Range1F_t &r) +{ + min = r.min; + max = r.max; + return *this; +} +//____________________________________________________________________________ Range1D_t::Range1D_t(void) : min(0.), max(0.) @@ -77,6 +84,13 @@ void Range1D_t::Copy(const Range1D_t & r) max = r.max; } //____________________________________________________________________________ +Range1D_t & Range1D_t::operator=(const Range1D_t &r) +{ + min = r.min; + max = r.max; + return *this; +} +//____________________________________________________________________________ Range1I_t::Range1I_t(void) : min(0), max(0) @@ -109,3 +123,10 @@ void Range1I_t::Copy(const Range1I_t & r) max = r.max; } //____________________________________________________________________________ +Range1I_t & Range1I_t::operator=(const Range1I_t &r) +{ + min = r.min; + max = r.max; + return *this; +} +//____________________________________________________________________________ diff --git a/src/Framework/Utils/Range1.h b/src/Framework/Utils/Range1.h index 464ed1cbde..ba39369f15 100644 --- a/src/Framework/Utils/Range1.h +++ b/src/Framework/Utils/Range1.h @@ -31,6 +31,7 @@ class Range1F_t Range1F_t (void); Range1F_t (float _min, float _max); Range1F_t (const Range1F_t & r); + Range1F_t &operator=(const Range1F_t &r); ~Range1F_t (void); void Copy (const Range1F_t & r); @@ -45,6 +46,8 @@ class Range1D_t Range1D_t (void); Range1D_t (double _min, double _max); Range1D_t (const Range1D_t & r); + Range1D_t &operator=(const Range1D_t &r); + ~Range1D_t (void); void Copy (const Range1D_t & r); @@ -59,6 +62,7 @@ class Range1I_t Range1I_t (void); Range1I_t (int _min, int _max); Range1I_t (const Range1I_t & r); + Range1I_t &operator=(const Range1I_t &r); ~Range1I_t (void); void Copy (const Range1I_t & r); From ebceb1abb22e5db0cfc8a1df20f009b35fa612f7 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Fri, 24 Jan 2025 16:43:21 +0300 Subject: [PATCH 13/78] small fix to speed up integration --- src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx | 5 +++++ src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx index a332a1541e..fec9f0c31b 100644 --- a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx +++ b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx @@ -664,6 +664,9 @@ d3XSecSM_dQ2dvdkF_E::d3XSecSM_dQ2dvdkF_E( fInteraction(i), fpF(pF) { + AlgFactory * algf = AlgFactory::Instance(); + sm_utils = const_cast(dynamic_cast(algf->GetAlgorithm("genie::SmithMonizUtils","Default"))); + sm_utils->SetInteraction(fInteraction); } d3XSecSM_dQ2dvdkF_E::~d3XSecSM_dQ2dvdkF_E() { @@ -677,6 +680,8 @@ double d3XSecSM_dQ2dvdkF_E::DoEval(const double * xin) const // outputs: // differential cross section // + Range1D_t rv = sm_utils->vQES_SM_lim(xin[0]); + if (xin[1] < rv.min || xin[1] > rv.max) return 0; fInteraction->KinePtr()->SetKV(kKVQ2, xin[0]); fInteraction->KinePtr()->SetKV(kKVv, xin[1]); fInteraction->KinePtr()->SetKV(kKVPn, fpF); diff --git a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.h b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.h index 97b23e7ae6..d2a3c94f8c 100644 --- a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.h +++ b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.h @@ -104,6 +104,7 @@ class d3XSecSM_dQ2dvdkF_E: public ROOT::Math::IBaseFunctionMultiDim const XSecAlgorithmI * fModel; const Interaction * fInteraction; const double fpF; + mutable SmithMonizUtils * sm_utils; }; // // genie::utils::gsl::d1XSecSM_dQ2_E From 55ab4f79c0bf4123308939edbc94a3791094be0b Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Fri, 24 Jan 2025 17:10:22 +0300 Subject: [PATCH 14/78] refactor code to speed up max search --- src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx index fec9f0c31b..56f6294d90 100644 --- a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx +++ b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx @@ -482,10 +482,11 @@ double QELEventGeneratorSM::ComputeMaxXSec(const Interaction * interaction) cons kinematics->SetKV(kKVQ2, Q2); Range1D_t rv = sm_utils->vQES_SM_lim(Q2); const double logvmin = TMath::Log(TMath::Max(rv.min, eps)); - const double logvmax = TMath::Log(TMath::Max(rv.max, TMath::Max(rv.min, eps))); + const double logvmax = TMath::Max(TMath::Log(rv.max), logvmin); for (int v_n=0; v_n <= N_v; v_n++) { // Scan around v + // for not heavy nucleus gives nan, but it doesn't matter for latter calculations double v = TMath::Exp(v_n*(logvmax-logvmin)/N_v + logvmin); kinematics->SetKV(kKVv, v); kinematics->SetKV(kKVPn, pFmax); @@ -566,10 +567,11 @@ double QELEventGeneratorSM::ComputeMaxXSec(const Interaction * interaction, cons kinematics->SetKV(kKVQ2, Q2); Range1D_t rv = sm_utils->vQES_SM_lim(Q2); const double logvmin = TMath::Log(TMath::Max(rv.min, eps)); - const double logvmax = TMath::Log(TMath::Max(rv.max, TMath::Max(rv.min, eps))); + const double logvmax = TMath::Max(TMath::Log(rv.max), logvmin); for (int v_n=0; v_n <= N_v; v_n++) { // Scan around v + // for not heavy nucleus gives nan, but it doesn't matter for latter calculations double v = TMath::Exp(v_n*(logvmax-logvmin)/N_v + logvmin); kinematics->SetKV(kKVv, v); kinematics->SetKV(kKVPn, pFmax); From 2138e9ebd60d466d41479d94b4cfbf172672fa1f Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sat, 25 Jan 2025 23:40:37 +0300 Subject: [PATCH 15/78] reduce integration accuracy --- config/SmithMonizQELCCXSec.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/SmithMonizQELCCXSec.xml b/config/SmithMonizQELCCXSec.xml index 2d794afa3b..9b44299aed 100644 --- a/config/SmithMonizQELCCXSec.xml +++ b/config/SmithMonizQELCCXSec.xml @@ -28,7 +28,7 @@ gsl-relative-tolerance-2D double Yes GSL max evaluations for 2D inte 3 adaptive 1000000000 - 1e-7 + 1e-4 From 2674505a7c39af9aa84c35159a058b52fb95c5d5 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Wed, 29 Jan 2025 15:25:35 +0300 Subject: [PATCH 16/78] use final lepton 4-vector in polarization method --- src/Physics/Common/PrimaryLeptonUtils.cxx | 7 +- .../XSection/NievesSimoVacasMECPXSec2016.cxx | 69 +--- .../Multinucleon/XSection/SuSAv2MECPXSec.cxx | 22 +- .../XSection/NievesQELCCPXSec.cxx | 384 ++++++++---------- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 19 +- .../XSection/SmithMonizQELCCPXSec.cxx | 53 +-- .../QuasiElastic/XSection/SmithMonizUtils.cxx | 3 +- .../QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 23 +- 8 files changed, 244 insertions(+), 336 deletions(-) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 4fb7eced36..64ec7ce5b1 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -269,7 +269,12 @@ void genie::utils::CalculatePolarizationVectorInTargetRestFrame( double aux1p = (Pl + El*cost)/2/M; double aux1 = ml2/2/M2; double aux2 = (Ev + El)/M; - double R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; + double R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; + if (R == 0) + { + polarization = TVector3(0, 0, 0); + return; + } double PL = sign*(2*aux1m*(W1 - aux1*W4) + aux1p*W2 - sign*(aux2*aux1m + aux1*cost)*W3 - aux1*cost*W5)/R; double PP = sign*ml*sint*(2*W1 - W2 -sign*Ev*W3/M - ml2*W4/M2 + El*W5/M)/2/M/R; double PT = - ml*Pl*sint*W6/2/M2/R; diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index 937578b002..0d83883a6c 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -416,44 +416,28 @@ void NievesSimoVacasMECPXSec2016::LoadConfig(void) //_________________________________________________________________________ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Interaction* interaction) const { - if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - - const Kinematics& kinematics = interaction -> Kine(); - const InitialState& init_state = interaction -> InitState(); - const Target& tgt = init_state.Tgt(); - // If {W,Q2} have been supplied instead, compute {Tl, ctl} - // NOTE: The expressions used here neglect Fermi motion and - // should eventually be revisited. See the "important note" - // in src/Framework/Utils/KineUtils.cxx about the - // Jacobian for transforming {W,Q2} --> {Tl, ctl}. - // - S. Gardiner, 29 July 2020 - if (kinematics.GetKV( kKVQ2 ) != -99999 && kinematics.GetKV( kKVW ) != -99999) - { - double Q2 = interaction->Kine().GetKV( kKVQ2 ); - double W = interaction->Kine().GetKV( kKVW ); - - // Probe properties (mass, energy, momentum) - double mv = init_state.Probe()->Mass(); - double Ev = init_state.ProbeE( kRfLab ); - double pv = std::sqrt( std::max(0., Ev*Ev - mv*mv) ); - - // Invariant mass of the initial hit nucleon - const TLorentzVector& hit_nuc_P4 = init_state.Tgt().HitNucP4(); - double M = hit_nuc_P4.M(); - - // Get the outgoing lepton kinetic energy - double ml = interaction->FSPrimLepton()->Mass(); - double Tl = Ev - ml - ( (W*W + Q2 - M*M) / (2.*M) ); - - // Get the outgoing lepton scattering cosine - double El = Tl + ml; - double pl = std::sqrt( std::max(0., El*El - ml*ml) ); - double ctl = ( 2.*Ev*El - Q2 - mv*mv - ml*ml ) / ( 2. * pv * pl ); - - // Set Tl, ctl in the interaction - interaction->KinePtr()->SetKV( kKVTl, Tl ); - interaction->KinePtr()->SetKV( kKVctl, ctl ); - } + if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + + const Kinematics& kinematics = interaction -> Kine(); + const InitialState& init_state = interaction -> InitState(); + const Target& tgt = init_state.Tgt(); + + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + + double Ev = neutrinoMom.E(); + double El = leptonMom.E(); + double ml = interaction->FSPrimLepton()->Mass(); + double Tl = El - ml; + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + double costl = neutrinoMom3.Dot(leptonMom3)/neutrinoMom3.Mag()/leptonMom3.Mag(); + double Q0 = 0.; + double Q3 = 0.; + genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); + const double M = 1; // the polarization doesn't depend on mass of target in target rest frame // This function returns d2sigma/(dTmu dcos_mu) in GeV^(-3) int target_pdg = tgt.Pdg(); @@ -548,11 +532,6 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int } } - // Check that the input kinematical point is within the range - // in which hadron tensors are known (for chosen target) - double Q0 = interaction->Kine().GetKV(kKVQ0); - double Q3 = interaction->Kine().GetKV(kKVQ3); - const LabFrameHadronTensorI* tensor = dynamic_cast( fHadronTensorModel->GetTensor(tensor_pdg, genie::kHT_MEC_FullAll) ); @@ -767,10 +746,6 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int } bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); - TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); - TLorentzVector neutrinoMom = *tempNeutrino; - delete tempNeutrino; - const TLorentzVector leptonMom = kinematics.FSLeptonP4(); genie::utils::CalculatePolarizationVectorInTargetRestFrame( fFinalLeptonPolarization, neutrinoMom, diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index ccd613e4a3..01746dd252 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -530,12 +530,18 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int return fFinalLeptonPolarization; } - // Check that the input kinematical point is within the range - // in which hadron tensors are known (for chosen target) - double Ev = interaction->InitState().ProbeE(kRfLab); - double Tl = interaction->Kine().GetKV(kKVTl); - double costl = interaction->Kine().GetKV(kKVctl); - double ml = interaction->FSPrimLepton()->Mass(); + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + + double Ev = neutrinoMom.E(); + double El = leptonMom.E(); + double ml = interaction->FSPrimLepton()->Mass(); + double Tl = El - ml; + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + double costl = neutrinoMom3.Dot(leptonMom3)/neutrinoMom3.Mag()/leptonMom3.Mag(); double Q0 = 0.; double Q3 = 0.; @@ -582,10 +588,6 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int double W5 = tensor->W5(Q0 - Delta_Q_value, Q3, M); bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); - TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); - TLorentzVector neutrinoMom = *tempNeutrino; - delete tempNeutrino; - const TLorentzVector leptonMom = kinematics.FSLeptonP4(); genie::utils::CalculatePolarizationVectorInTargetRestFrame( fFinalLeptonPolarization, neutrinoMom, diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 2ab9df5ac4..a914d7b845 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -522,15 +522,16 @@ void NievesQELCCPXSec::LoadConfig(void) //___________________________________________________________________________ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double M, double r, bool is_neutrino, bool tgtIsNucleus, int tgt_pdgc, - int A, int Z, int N, bool hitNucIsProton, double & CN, double & CT, double & CL, + int A, int Z, int N, double & CN, double & CT, double & CL, double & imaginaryU, double & t0, double & r00, bool assumeFreeNucleon) const { - if ( tgtIsNucleus && !assumeFreeNucleon ) { - double dq = qTildeP4.Vect().Mag(); - double dq2 = TMath::Power(dq,2); - double q2 = 1 * qTildeP4.Mag2(); + if ( tgtIsNucleus && !assumeFreeNucleon ) + { + double dq = qTildeP4.Vect().Mag(); + double dq2 = TMath::Sq(dq); + double q2 = qTildeP4.Mag2(); //Terms for polarization coefficients CN,CT, and CL - double hbarc2 = TMath::Power(fhbarc,2); + double hbarc2 = TMath::Sq(fhbarc); double c0 = 0.380/fhbarc;//Constant for CN in natural units //Density gives the nuclear density, normalized to 1 @@ -540,41 +541,33 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double rho = rhop + rhon; double rho0 = A*nuclear::Density(0,A); - double fPrime = (0.33*rho/rho0+0.45*(1-rho/rho0))*c0; + double fPrime = (0.33*rho/rho0 + 0.45*(1 - rho/rho0))*c0; // Get Fermi momenta - double kF1, kF2; - if(fLFG){ - if(hitNucIsProton){ - kF1 = TMath::Power(3*kPi2*rhop, 1.0/3.0) *fhbarc; - kF2 = TMath::Power(3*kPi2*rhon, 1.0/3.0) *fhbarc; - }else{ - kF1 = TMath::Power(3*kPi2*rhon, 1.0/3.0) *fhbarc; - kF2 = TMath::Power(3*kPi2*rhop, 1.0/3.0) *fhbarc; - } - }else{ - if(hitNucIsProton){ - kF1 = fKFTable->FindClosestKF(tgt_pdgc, kPdgProton); - kF2 = fKFTable->FindClosestKF(tgt_pdgc, kPdgNeutron); - }else{ - kF1 = fKFTable->FindClosestKF(tgt_pdgc, kPdgNeutron); - kF2 = fKFTable->FindClosestKF(tgt_pdgc, kPdgProton); - } + double kFn, kFp; + if(fLFG) + { + kFn = TMath::Power(3*kPi2*rhon, 1.0/3.0) *fhbarc; + kFp = TMath::Power(3*kPi2*rhop, 1.0/3.0) *fhbarc; + } + else + { + kFn = fKFTable->FindClosestKF(tgt_pdgc, kPdgNeutron); + kFp = fKFTable->FindClosestKF(tgt_pdgc, kPdgProton); } - double kF = TMath::Power(1.5*kPi2*rho, 1.0/3.0) *fhbarc; - - std::complex imU(relLindhardIm(qTildeP4.E(),dq,kF1,kF2, - M,is_neutrino,t0,r00)); + double kF = TMath::Power(1.5*kPi2*rho, 1./3.)*fhbarc; - imaginaryU = imag(imU); + imaginaryU = relLindhardIm(qTildeP4.E(),dq,kFn,kFp, + M,is_neutrino,t0,r00); - std::complex relLin(0,0),udel(0,0); + std::complex relLin(0, 0), udel(0, 0); // By comparison with Nieves' fortran code - if(imaginaryU < 0.){ - relLin = relLindhard(qTildeP4.E(),dq,kF,M,is_neutrino,imU); - udel = deltaLindhard(qTildeP4.E(),dq,rho,kF); + if(imaginaryU < 0) + { + relLin = relLindhard(qTildeP4.E(), dq, kF, M, imaginaryU); + udel = deltaLindhard(qTildeP4.E(), dq, rho, kF); } std::complex relLinTot(relLin + udel); @@ -582,18 +575,17 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2 mRho = 770 MeV, (0.770 GeV)^2 = 0.5929 GeV^2 g' = 0.63 */ - double Vt = 0.08*4*kPi/kPionMass2 * - (2* TMath::Power((6.25-0.5929)/(6.25-q2),2)*dq2/(q2-0.5929) + 0.63); + double Vt = 0.08*4*kPi/kPionMass2* + (2*TMath::Sq( (6.25 - 0.5929)/(6.25 - q2) )*dq2/(q2 - 0.5929) + 0.63); /* f^2/4/Pi = 0.08 DeltaSubPi = 1200 MeV, (1.2 GeV)^2 = 1.44 GeV^2 g' = 0.63 */ - double Vl = 0.08*4*kPi/kPionMass2 * - (TMath::Power((1.44-kPionMass2)/(1.44-q2),2)*dq2/(q2-kPionMass2)+0.63); - - CN = 1.0/TMath::Power(abs(1.0-fPrime*relLin/hbarc2),2); + double Vl = 0.08*4*kPi/kPionMass2* + (TMath::Sq( (1.44 - kPionMass2)/(1.44 - q2) )*dq2/(q2 - kPionMass2) + 0.63); - CT = 1.0/TMath::Power(abs(1.0-relLinTot*Vt),2); - CL = 1.0/TMath::Power(abs(1.0-relLinTot*Vl),2); + CN = 1/TMath::Sq(abs(1. - fPrime*relLin/hbarc2)); + CT = 1/TMath::Sq(abs(1. - relLinTot*Vt)); + CL = 1/TMath::Sq(abs(1. - relLinTot*Vl)); } else { //Polarization Coefficients: all equal to 1.0 for free nucleon @@ -606,41 +598,32 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, //____________________________________________________________________________ // Gives the imaginary part of the relativistic lindhard function in GeV^2 // and sets the values of t0 and r00 -std::complex NievesQELCCPXSec::relLindhardIm(double q0, double dq, +double NievesQELCCPXSec::relLindhardIm(double q0, double dq, double kFn, double kFp, double M, bool isNeutrino, double & t0, double & r00) const { - double M2 = TMath::Power(M,2); + double M2 = TMath::Sq(M); double EF1,EF2; if(isNeutrino){ - EF1 = TMath::Sqrt(M2+TMath::Power(kFn,2)); //EFn - EF2 = TMath::Sqrt(M2+TMath::Power(kFp,2)); //EFp + EF1 = TMath::Sqrt(M2 + TMath::Sq(kFn)); //EFn + EF2 = TMath::Sqrt(M2 + TMath::Sq(kFp)); //EFp }else{ - EF1 = TMath::Sqrt(M2+TMath::Power(kFp,2)); //EFp - EF2 = TMath::Sqrt(M2+TMath::Power(kFn,2)); //EFn + EF1 = TMath::Sqrt(M2 + TMath::Sq(kFp)); //EFp + EF2 = TMath::Sqrt(M2 + TMath::Sq(kFn)); //EFn } - double q2 = TMath::Power(q0,2) - TMath::Power(dq,2); - double a = (-q0+dq*TMath::Sqrt(1-4.0*M2/q2))/2.0; - double epsRP = TMath::Max(TMath::Max(M,EF2-q0),a); - - // Other theta functions for q are handled by nuclear suppression - // That is, q0>0 and -q2>0 are always handled, and q0>EF2-EF1 is - // handled if pauli blocking is on, because otherwise the final - // nucleon would be below the fermi sea - //if(fNievesSuppression && !interaction->TestBit(kIAssumeFreeNucleon ) - //&& !EF1-epsRP<0){ - //LOG("Nieves", pINFO) << "Average value of E(p) above Fermi sea"; - //return 0; - //}else{ - t0 = 0.5*(EF1+epsRP); - r00 = (TMath::Power(EF1,2)+TMath::Power(epsRP,2)+EF1*epsRP)/3.0; - std::complex result(0.0,-M2/2.0/kPi/dq*(EF1-epsRP)); - return result; - //} + double q2 = TMath::Sq(q0) - TMath::Sq(dq); + double a = (-q0 + dq*TMath::Sqrt(1 - 4*M2/q2))/2; + double epsRP = TMath::Max(TMath::Max(M,EF2 - q0),a); + //int factor = (EF1 - EF2 + q0 >= 0)*(EF1 - epsRP >= 0); + int factor = 1; + // theta functions q0>0 and -q2>0 are always handled + t0 = factor*(EF1 + epsRP)/2; + r00 = factor*(TMath::Sq(EF1) + TMath::Sq(epsRP) + EF1*epsRP)/3; + return -factor*M2/2/kPi/dq*(EF1 - epsRP); } //____________________________________________________________________________ //Following obtained from fortran code by J Nieves, which contained the following comment: @@ -665,60 +648,49 @@ std::complex NievesQELCCPXSec::relLindhardIm(double q0, double dq, //Takes inputs in GeV (with imU in GeV^2), and gives output in GeV^2 std::complex NievesQELCCPXSec::relLindhard(double q0gev, double dqgev, double kFgev, double M, - bool isNeutrino, - std::complex /* relLindIm */) const + double relLindIm) const { double q0 = q0gev/fhbarc; double qm = dqgev/fhbarc; double kf = kFgev/fhbarc; double m = M/fhbarc; - if(q0>qm){ - LOG("Nieves", pWARN) << "relLindhard() failed"; - return 0.0; - } - - std::complex RealLinRel(ruLinRelX(q0,qm,kf,m)+ruLinRelX(-q0,qm,kf,m)); - double t0,r00; - std::complex ImLinRel(relLindhardIm(q0gev,dqgev,kFgev,kFgev,M,isNeutrino,t0,r00)); //Units of GeV^2 - return(RealLinRel*TMath::Power(fhbarc,2) + 2.0*ImLinRel); + std::complex relLind(TMath::Sq(fhbarc)*(ruLinRelX(q0,qm,kf,m) + ruLinRelX(-q0,qm,kf,m)), 2*relLindIm); + + return relLind; } //____________________________________________________________________________ //Inputs assumed to be in natural units -std::complex NievesQELCCPXSec::ruLinRelX(double q0, double qm, - double kf, double m) const +double NievesQELCCPXSec::ruLinRelX(double q0, double qm, + double kf, double m) const { - double q02 = TMath::Power(q0, 2); - double qm2 = TMath::Power(qm, 2); - double kf2 = TMath::Power(kf, 2); - double m2 = TMath::Power(m, 2); - double m4 = TMath::Power(m, 4); - - double ef = TMath::Sqrt(m2+kf2); - double q2 = q02-qm2; - double q4 = TMath::Power(q2,2); - double ds = TMath::Sqrt(1.0-4.0*m2/q2); - double L1 = log((kf+ef)/m); - std::complex uL2( - TMath::Log(TMath::Abs( - (ef + q0 - TMath::Sqrt(m2+TMath::Power(kf-qm,2)))/ - (ef + q0 - TMath::Sqrt(m2 + TMath::Power(kf + qm,2))))) + - TMath::Log(TMath::Abs( - (ef + q0 + TMath::Sqrt(m2 + TMath::Power(kf - qm,2)))/ - (ef + q0 + TMath::Sqrt(m2 + TMath::Power(kf + qm,2)))))); - - std::complex uL3( - TMath::Log(TMath::Abs((TMath::Power(2*kf + q0*ds,2)-qm2)/ - (TMath::Power(2*kf - q0*ds,2)-qm2))) + - TMath::Log(TMath::Abs((TMath::Power(kf-ef*ds,2) - (4*m4*qm2)/q4)/ - (TMath::Power(kf+ef*ds,2) - (4*m4*qm2)/q4)))); - - std::complex RlinrelX(-L1/(16.0*kPi2)+ - uL2*(2.0*ef+q0)/(32.0*kPi2*qm)- - uL3*ds/(64.0*kPi2)); - - return RlinrelX*16.0*m2; + double q02 = TMath::Sq(q0); + double qm2 = TMath::Sq(qm); + double kf2 = TMath::Sq(kf); + double m2 = TMath::Sq(m); + double m4 = TMath::Sq(m2); + + double ef = TMath::Sqrt(m2 + kf2); + double q2 = q02 - qm2; + double q4 = TMath::Sq(q2); + double ds = TMath::Sqrt(1 - 4*m2/q2); + double L1 = TMath::Log((kf + ef)/m); + + double aux1 = TMath::Sq(ef + q0); + double aux2 = TMath::Sq(kf - qm)/aux1; + double aux3 = TMath::Sq(kf + qm)/aux1; + double L2 = TMath::Log(TMath::Abs((1 - aux2)/(1 - aux3))); + + double aux5 = TMath::Sq(2*kf + q0*ds)/qm2; + double aux6 = TMath::Sq(2*kf - q0*ds)/qm2; + double aux7 = 4*m4*qm2/q4; + double aux8 = TMath::Sq(kf - ef*ds)/aux7; + double aux9 = TMath::Sq(kf + ef*ds)/aux7; + double L3 = TMath::Log(TMath::Abs((aux5 - 1)/(aux6 - 1)* + (aux8 - 1)/(aux9 - 1))); + + return m2*(-L1 + L2*(2*ef + q0)/2/qm - L3*ds/4)/kPi2; } //____________________________________________________________________________ //Following obtained from fortran code by J Nieves, which contained the following comment: @@ -746,88 +718,97 @@ std::complex NievesQELCCPXSec::ruLinRelX(double q0, double qm, Therefore this subroutine provides two different functions depending on whether q_zero is real or not!!!!!!!!!!! */ -std::complex NievesQELCCPXSec::deltaLindhard(double q0, - double dq, double rho, double kF) const +std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, + double rho, double kF) const { - double q_zero = q0/fhbarc; - double q_mod = dq/fhbarc; + double q_zero = q0/fhbarc; + double q_mod = dq/fhbarc; double k_fermi = kF/fhbarc; //Divide by hbarc in order to use natural units (rho is already in the correct units) //m = 939/197.3, md = 1232/197.3, mpi = 139/197.3 - double m = 4.7592; - double md = 6.2433; + double m = 4.7592; + double md = 6.2433; double mpi = 0.7045; - double fdel_f = 2.13; - double wr = md-m; + double fdel_f2 = 0.45; +// double fdel2 = 4*0.36*kPi; + double fdel2 = fdel_f2; + double wr = md - m; double gamma = 0; double gammap = 0; - double q_zero2 = TMath::Power(q_zero, 2); - double q_mod2 = TMath::Power(q_mod, 2); - double k_fermi2 = TMath::Power(k_fermi, 2); + double q_zero2 = TMath::Sq(q_zero); + double q_mod2 = TMath::Sq(q_mod); + double k_fermi2 = TMath::Sq(k_fermi); - double m2 = TMath::Power(m, 2); - double m4 = TMath::Power(m, 4); - double mpi2 = TMath::Power(mpi, 2); - double mpi4 = TMath::Power(mpi, 4); + double m2 = TMath::Sq(m); + double m4 = TMath::Sq(m2); + double mpi2 = TMath::Sq(mpi); + double mpi4 = TMath::Sq(mpi2); - double fdel_f2 = TMath::Power(fdel_f, 2); //For the current code q_zero is always real //If q_zero can have an imaginary part then only the real part is used //until z and zp are calculated - - double s = m2+q_zero2-q_mod2+ - 2.0*q_zero *TMath::Sqrt(m2+3.0/5.0*k_fermi2); - - if(s>TMath::Power(m+mpi,2)){ + double aux1 = m2 + q_zero2 - q_mod2; + double aux2 = 2*q_zero*TMath::Sqrt(m2 + 3*k_fermi2/5); + double aux3 = TMath::Sq(m + mpi); + double s = aux1 + aux2; + double sp = aux1 - aux2; + + if(s > aux3) + { double srot = TMath::Sqrt(s); - double qcm = TMath::Sqrt(TMath::Power(s,2)+mpi4+m4-2.0*(s*mpi2+s*m2+ - mpi2*m2)) /(2.0*srot); - gamma = 1.0/3.0 * 1.0/(4.0*kPi) * fdel_f2* - TMath::Power(qcm,3)/srot*(m+TMath::Sqrt(m2+TMath::Power(qcm,2)))/mpi2; + double qcm = TMath::Sqrt(TMath::Sq(s) + mpi4 + m4 - 2*(s*mpi2 + s*m2 + mpi2*m2))/2/srot; + gamma = fdel2*TMath::Power(qcm,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcm)))/mpi2/12/kPi/srot; } - double sp = m2+q_zero2-q_mod2- - 2.0*q_zero *TMath::Sqrt(m2+3.0/5.0*k_fermi2); - - - if(sp > TMath::Power(m+mpi,2)){ + + if(sp > aux3) + { double srotp = TMath::Sqrt(sp); - double qcmp = TMath::Sqrt(TMath::Power(sp,2)+mpi4+m4-2.0*(sp*mpi2+sp*m2+ - mpi2*m2))/(2.0*srotp); - gammap = 1.0/3.0 * 1.0/(4.0*kPi) * fdel_f2* - TMath::Power(qcmp,3)/srotp*(m+TMath::Sqrt(m2+TMath::Power(qcmp,2)))/mpi2; + double qcmp = TMath::Sqrt(TMath::Sq(sp) + mpi4 + m4 - 2*(sp*mpi2 + sp*m2 + mpi2*m2))/2/srotp; + gammap = fdel2*TMath::Power(qcmp,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcmp)))/mpi2/12/kPi/srotp; } - //}//End if statement - - std::complex z(md/(q_mod*k_fermi)*(q_zero-q_mod2/(2.0*md) - -wr +1i*gamma/2.0)); - std::complex zp(md/(q_mod*k_fermi)*(-q_zero-q_mod2/(2.0*md) - -wr +1i*gammap/2.0)); - - std::complex pzeta(0.0); - if(abs(z) > 50.0){ - pzeta = 2.0/(3.0*z)+2.0/(15.0*z*z*z); - }else if(abs(z) < TMath::Power(10.0,-2)){ - pzeta = 2.0*z-2.0/3.0*z*z*z-1i*kPi/2.0*(1.0-z*z); - }else{ - pzeta = z + (1.0-z*z) * log((z+1.0)/(z-1.0))/2.0; + + std::complex z (md/q_mod/k_fermi*( q_zero - q_mod2/2./md - wr + 1i*gamma/2.)); + std::complex zp(md/q_mod/k_fermi*(-q_zero - q_mod2/2./md - wr + 1i*gammap/2.)); + + std::complex pzeta(0, 0); + double one_sqrt10 = 1/TMath::Sq(10); + std::complex z2(z*z); + double abs_z = abs(z); + if(abs_z > 50) + { + pzeta = 2.*(1. + 1./5./z2)/3./z; + } + else if(abs_z < one_sqrt10) + { + pzeta = 2.*z*(1. - z2/3.) - 1i*kPi*(1. - z2)/2.; + } + else + { + pzeta = z + (1. - z2)*log((z + 1.)/(z - 1.))/2.; } - std::complex pzetap(0); - if(abs(zp) > 50.0){ - pzetap = 2.0/(3.0*zp)+2.0/(15.0*zp*zp*zp); - }else if(abs(zp) < TMath::Power(10.0,-2)){ - pzetap = 2.0*zp-2.0/3.0*zp*zp*zp-1i*kPi/2.0*(1.0-zp*zp); - }else{ - pzetap = zp+ (1.0-zp*zp) * log((zp+1.0)/(zp-1.0))/2.0; + std::complex pzetap(0,0); + std::complex zp2(zp*zp); + double abs_zp = abs(zp); + if(abs_zp > 50) + { + pzetap = 2.*(1. + 1./5./zp2)/3./zp; + } + else if(abs_zp < one_sqrt10) + { + pzetap = 2.*zp*(1. - zp2/3.) - 1i*kPi*(1. - zp2)/2.; + } + else + { + pzetap = zp + (1. - zp2)*log((zp + 1.)/(zp - 1.))/2.; } //Multiply by hbarc^2 to give answer in units of GeV^2 - return 2.0/3.0 * rho * md/(q_mod*k_fermi) * (pzeta +pzetap) * fdel_f2 * - TMath::Power(fhbarc,2); + return 2.*rho*md*(pzeta + pzetap)*fdel_f2*TMath::Sq(fhbarc)/q_mod/k_fermi/3.; } //____________________________________________________________________________ @@ -956,8 +937,7 @@ const Target& target, bool assumeFreeNucleon) const int A = target.A(); int Z = target.Z(); int N = target.N(); - bool hitNucIsProton = pdg::IsProton( target.HitNucPdg() ); - + const double k[4] = {neutrinoMom.E(),neutrinoMom.Px(),neutrinoMom.Py(),neutrinoMom.Pz()}; const double kPrime[4] = {leptonMom.E(),leptonMom.Px(), leptonMom.Py(),leptonMom.Pz()}; @@ -996,7 +976,7 @@ const Target& target, bool assumeFreeNucleon) const double t0,r00; double CN=1.,CT=1.,CL=1.,imU=0; CNCTCLimUcalc(qTildeP4, M, r, is_neutrino, tgtIsNucleus, - tgt_pdgc, A, Z, N, hitNucIsProton, CN, CT, CL, imU, + tgt_pdgc, A, Z, N, CN, CT, CL, imU, t0, r00, assumeFreeNucleon); if ( imU > kASmallNum ) @@ -1447,21 +1427,14 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i double T4 = M/2/q2*(Wzz - Wxx); double T5 = (ReW0z - q0/q*(Wzz - Wxx))/q; - - if (T1 != 0 || T2!=0 || T3!=0 || T4!=0 || T5!=0) - { - CalculatePolarizationVectorInTargetRestFrame( + CalculatePolarizationVectorInTargetRestFrame( fFinalLeptonPolarization, neutrinoMom, leptonMom, is_neutrino, M, T1,T2,T3,T4,T5,0); - } - else - { - LOG("Nieves", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); - } + + std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; std::cout << fFinalLeptonPolarization.Mag() << "\n"; @@ -1626,17 +1599,8 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); TLorentzVector neutrinoMom = *tempNeutrino; delete tempNeutrino; - TLorentzVector inNucleonMom(*init_state.TgtPtr()->HitNucP4Ptr()); - TLorentzVector leptonMom = kinematics.FSLeptonP4(); - TLorentzVector outNucleonMom = kinematics.HadSystP4(); - - double outNucleonEnergy = TMath::Hypot(M, outNucleonMom.P() ); - double inNucleonOnShellEnergy = TMath::Hypot(M, inNucleonMom.P() ); - - TLorentzVector inNucleonMomOnShell(inNucleonMom); - inNucleonMomOnShell.SetE(inNucleonOnShellEnergy); - + // Calculate Coulomb corrections double ml = interaction->FSPrimLepton()->Mass(); double ml2 = ml*ml; @@ -1655,35 +1619,21 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac double El = ElLocal; ElLocal = El - sign*Vc; - if ( ElLocal - ml <= 0. ) - { - return 0; - } + if ( ElLocal - ml <= 0 ) return 0; // The Coulomb correction factor blows up as pl -> 0. To guard against // unphysically huge corrections here, require that the lepton kinetic energy // (at infinity) is larger than the magnitude of the Coulomb potential // (should be around a few MeV) double KEl = El - ml; - if ( KEl <= TMath::Abs(Vc) ) - { - return 0; - } + if ( KEl <= TMath::Abs(Vc) ) return 0; // Local value of the lepton 3-momentum magnitude for the Coulomb correction plLocal = TMath::Sqrt(ElLocal*ElLocal - ml2); } - // When computing the contraction of the leptonic and hadronic tensors, - // we need to use an effective value of the 4-momentum transfer q. - // The energy transfer (q0) needs to be modified to account for the binding - // energy of the struck nucleon, while the 3-momentum transfer needs to - // be corrected for Coulomb effects. - // - // See the original Valencia model paper: - // https://journals.aps.org/prc/abstract/10.1103/PhysRevC.70.055503 - double q0Tilde = outNucleonEnergy - inNucleonOnShellEnergy; + double q0Tilde = neutrinoMom.E() - leptonMom.E(); int nucl_pdg_ini = target.HitNucPdg(); @@ -1713,11 +1663,8 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac if( fQvalueShifter ) q0Tilde += q0Tilde * fQvalueShifter->Shift(*interaction) ; // If binding energy effects pull us into an unphysical region, return - // zero for the differential cross section - if ( q0Tilde <= 0 && tgtIsNucleus && !interaction->TestBit(kIAssumeFreeNucleon) ) - { - return 0; - } + // zero + if ( q0Tilde <= 0 && tgtIsNucleus && !interaction->TestBit(kIAssumeFreeNucleon) ) return 0; // Note that we're working in the lab frame (i.e., the rest frame // of the target nucleus). We can therefore use Nieves' explicit @@ -1766,10 +1713,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac double Q2tilde = -qTildeP4.Mag2(); // Check that Q2tilde > 0 (accounting for rounding errors) - if (Q2tilde < 0) - { - return 0; - } + if (Q2tilde < 0) return 0; // Store Q2tilde in the kinematic variable representing Q2. // This will ensure that the form factors are calculated correctly @@ -1795,14 +1739,11 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac double t0,r00; double CN(1), CT(1), CL(1), imU(0); CNCTCLimUcalc(qTildeP4, M, r, is_neutrino, tgtIsNucleus, - tgt_pdgc, A, Z, N, hitNucIsProton, CN, CT, CL, imU, + tgt_pdgc, A, Z, N, CN, CT, CL, imU, t0, r00, interaction->TestBit( kIAssumeFreeNucleon )); - if ( imU > 0 ) - { - return 0; - } + if ( imU > 0 ) return 0; if ( !fRPA || interaction->TestBit( kIAssumeFreeNucleon ) ) { @@ -1832,10 +1773,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac double Elow = TMath::Max( EFf - q0, M*(c*d + TMath::Sqrt(1- c*c + d*d))/(1 - c*c) ); double Eup = EFi; - if (Elow >= Eup) - { - return 0; - } + if (Elow >= Eup) return 0; double Elow2 = Elow*Elow; double Elow3 = Elow*Elow2; diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index a2b6877a48..c00e4e1aba 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -122,20 +122,19 @@ class NievesQELCCPXSec : public XSecAlgorithmI { // r must be in units of fm. void CNCTCLimUcalc(TLorentzVector qTildeP4, double M, double r, bool is_neutrino, bool tgtIsNucleus, int tgt_pdgc, int A, int Z, int N, - bool hitNucIsProton, double & CN, double & CT, double & CL, double & imU, + double & CN, double & CT, double & CL, double & imU, double & t0, double & r00, bool assumeFreeNucleon) const; //Equations to calculate the relativistic Lindhard function for Amunu - std::complex relLindhardIm(double q0gev, double dqgev, - double kFngev, double kFpgev, - double M, bool isNeutrino, - double & t0, double & r00) const; + double relLindhardIm(double q0gev, double dqgev, + double kFngev, double kFpgev, + double M, bool isNeutrino, + double & t0, double & r00) const; std::complex relLindhard(double q0gev, double dqgev, - double kFgev, double M, - bool isNeutrino, - std::complex relLindIm) const; - std::complex ruLinRelX(double q0, double qm, - double kf, double m) const; + double kFgev, double M, + double ImU) const; + double ruLinRelX(double q0, double qm, + double kf, double m) const; std::complex deltaLindhard(double q0gev, double dqgev, double rho, double kFgev) const; diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 438aa80966..60cd57cccf 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -504,44 +504,35 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio sm_utils->SetInteraction(interaction); const InitialState & init_state = interaction -> InitState(); const Target & target = init_state.Tgt(); - double Enu = init_state.ProbeE(kRfLab); - double Q2 = kinematics.Q2(true); - double v = kinematics.GetKV(kKVv); + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + double Enu = neutrinoMom.E(); + double El = leptonMom.E(); + double ml2 = leptonMom.M2(); + double Pl = leptonMom.P(); + double v = Enu - El; + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + double cos_theta = neutrinoMom3.Dot(leptonMom3)/neutrinoMom3.Mag()/leptonMom3.Mag(); + double aux1 = El - Pl*cos_theta; + double Q2 = 2*Enu*aux1 - ml2; + Range1D_t rkF = sm_utils->kFQES_SM_lim(Q2,v); + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + //|\vec{q}| + double qqv = v*v + Q2; + double qv = TMath::Sqrt(qqv); double E_BIN = sm_utils->GetBindingEnergy(); double m_ini = target.HitNucMass(); double mm_ini = m_ini*m_ini; double m_fin = interaction->RecoilNucleon()->Mass(); // Mass of final hadron or hadron system (GeV) double mm_fin = m_fin*m_fin; double m_tar = target.Mass(); // Mass of target nucleus (GeV) - - //|\vec{q}| - double qqv = v*v + Q2; - double qv = TMath::Sqrt(qqv); - - bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); - - double El = Enu - v; - double ml = interaction->FSPrimLepton()->Mass(); - double ml2 = ml*ml; - if (El < ml) - { - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; - } - double Pl = TMath::Sqrt(El*El - ml2); - double k6 = (Q2 + ml2)/(2*Enu); - double cos_theta = (El - k6)/Pl; - if (cos_theta < -1.0 || cos_theta > 1.0 ) - { - LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; - } - - double cosT_k = (v + k6)/qv; + double cosT_k = (v + aux1)/qv; if (cosT_k < -1.0 || cosT_k > 1.0 ) { LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; @@ -649,10 +640,6 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio double T4 = mm_tar*(0.5*k4*W2 + a1*W4/mm_ini + a6*W5/m_ini/qv); //Ref.[1], W_\alpha double T5 = m_tar*(a5/qv - v*k4)*W2 + k5*W5; - TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); - TLorentzVector neutrinoMom = *tempNeutrino; - delete tempNeutrino; - const TLorentzVector leptonMom = kinematics.FSLeptonP4(); CalculatePolarizationVectorInTargetRestFrame( fFinalLeptonPolarization, neutrinoMom, diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizUtils.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizUtils.cxx index c49d46419c..1094461d87 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizUtils.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizUtils.cxx @@ -620,7 +620,8 @@ double SmithMonizUtils::rho(double P_Fermi, double T_Fermi, double p) else { //Fermi-Dirac distribution - return 1.0/(1.0 + TMath::Exp(-(P_Fermi-p)/T_Fermi)); + double aux = TMath::Exp((P_Fermi-p)/T_Fermi); + return aux/(1 + aux); } diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index d6bdce8ca2..1e4480e191 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -688,15 +688,20 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int const double M = 1; // the polarization doesn't depend on mass of target in target rest frame - // Check that the input kinematical point is within the range - // in which hadron tensors are known (for chosen target) - double Ev = init_state.ProbeE(kRfLab); - double Tl = kinematics.GetKV(kKVTl); - double costl = kinematics.GetKV(kKVctl); - double ml = interaction->FSPrimLepton()->Mass(); + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; + const TLorentzVector leptonMom = kinematics.FSLeptonP4(); + + double Ev = neutrinoMom.E(); + double El = leptonMom.E(); + double ml = leptonMom.M(); + double Tl = El - ml; + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + double costl = neutrinoMom3.Dot(leptonMom3)/neutrinoMom3.Mag()/leptonMom3.Mag(); double Q0 = 0.; double Q3 = 0.; - genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); // *** Enforce the global Q^2 cut *** @@ -1193,10 +1198,6 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int } } - TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); - TLorentzVector neutrinoMom = *tempNeutrino; - delete tempNeutrino; - const TLorentzVector leptonMom = kinematics.FSLeptonP4(); genie::utils::CalculatePolarizationVectorInTargetRestFrame( fFinalLeptonPolarization, neutrinoMom, From 2da5c0797b3e5e9252327038c3e3d5fd1143df03 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 30 Jan 2025 04:01:39 +0300 Subject: [PATCH 17/78] test variant --- .../XSection/NievesQELCCPXSec.cxx | 379 +++++++++++++++++- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 29 +- 2 files changed, 392 insertions(+), 16 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index a914d7b845..72e0e5df24 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -560,17 +560,17 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, imaginaryU = relLindhardIm(qTildeP4.E(),dq,kFn,kFp, M,is_neutrino,t0,r00); + std::complex relLin(0, 0), udel(0, 0); // By comparison with Nieves' fortran code if(imaginaryU < 0) { - relLin = relLindhard(qTildeP4.E(), dq, kF, M, imaginaryU); + relLin = relLindhard(qTildeP4.E(), dq, kF, M); udel = deltaLindhard(qTildeP4.E(), dq, rho, kF); } std::complex relLinTot(relLin + udel); - /* CRho = 2 DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2 mRho = 770 MeV, (0.770 GeV)^2 = 0.5929 GeV^2 @@ -587,7 +587,8 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, CT = 1/TMath::Sq(abs(1. - relLinTot*Vt)); CL = 1/TMath::Sq(abs(1. - relLinTot*Vl)); } - else { + else + { //Polarization Coefficients: all equal to 1.0 for free nucleon CN = 1.0; CT = 1.0; @@ -618,8 +619,7 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, double q2 = TMath::Sq(q0) - TMath::Sq(dq); double a = (-q0 + dq*TMath::Sqrt(1 - 4*M2/q2))/2; double epsRP = TMath::Max(TMath::Max(M,EF2 - q0),a); - //int factor = (EF1 - EF2 + q0 >= 0)*(EF1 - epsRP >= 0); - int factor = 1; + int factor = (EF1 - EF2 + q0 >= 0)*(EF1 - epsRP >= 0); // theta functions q0>0 and -q2>0 are always handled t0 = factor*(EF1 + epsRP)/2; r00 = factor*(TMath::Sq(EF1) + TMath::Sq(epsRP) + EF1*epsRP)/3; @@ -647,17 +647,17 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, */ //Takes inputs in GeV (with imU in GeV^2), and gives output in GeV^2 std::complex NievesQELCCPXSec::relLindhard(double q0gev, - double dqgev, double kFgev, double M, - double relLindIm) const + double dqgev, double kFgev, double M) const { double q0 = q0gev/fhbarc; double qm = dqgev/fhbarc; double kf = kFgev/fhbarc; double m = M/fhbarc; + double dummy; + double relLindIm = relLindhardIm(q0gev, dqgev, kFgev, kFgev, M, true, dummy, dummy); //Units of GeV^2 - std::complex relLind(TMath::Sq(fhbarc)*(ruLinRelX(q0,qm,kf,m) + ruLinRelX(-q0,qm,kf,m)), 2*relLindIm); - + std::complex relLind(TMath::Sq(fhbarc)*(ruLinRelX(q0,qm,kf,m) + ruLinRelX(-q0,qm,kf,m)), relLindIm); return relLind; } //____________________________________________________________________________ @@ -678,8 +678,8 @@ double NievesQELCCPXSec::ruLinRelX(double q0, double qm, double L1 = TMath::Log((kf + ef)/m); double aux1 = TMath::Sq(ef + q0); - double aux2 = TMath::Sq(kf - qm)/aux1; - double aux3 = TMath::Sq(kf + qm)/aux1; + double aux2 = (m2 + TMath::Sq(kf - qm))/aux1; + double aux3 = (m2 + TMath::Sq(kf + qm))/aux1; double L2 = TMath::Log(TMath::Abs((1 - aux2)/(1 - aux3))); double aux5 = TMath::Sq(2*kf + q0*ds)/qm2; @@ -732,8 +732,7 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, double mpi = 0.7045; double fdel_f2 = 0.45; -// double fdel2 = 4*0.36*kPi; - double fdel2 = fdel_f2; + double fdel2 = 4*0.36*kPi; double wr = md - m; double gamma = 0; double gammap = 0; @@ -770,7 +769,7 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, double qcmp = TMath::Sqrt(TMath::Sq(sp) + mpi4 + m4 - 2*(sp*mpi2 + sp*m2 + mpi2*m2))/2/srotp; gammap = fdel2*TMath::Power(qcmp,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcmp)))/mpi2/12/kPi/srotp; } - + std::complex z (md/q_mod/k_fermi*( q_zero - q_mod2/2./md - wr + 1i*gamma/2.)); std::complex zp(md/q_mod/k_fermi*(-q_zero - q_mod2/2./md - wr + 1i*gammap/2.)); @@ -1742,6 +1741,21 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac tgt_pdgc, A, Z, N, CN, CT, CL, imU, t0, r00, interaction->TestBit( kIAssumeFreeNucleon )); + double t0ttt,r00ttt; + double CNttt(1), CTttt(1), CLttt(1), imUttt(0); + CNCTCLimUcalcttt(qTildeP4, M, r, is_neutrino, tgtIsNucleus, + tgt_pdgc, A, Z, N, !is_neutrino, CNttt, CTttt, CLttt, imUttt, + t0ttt, r00ttt, interaction->TestBit( kIAssumeFreeNucleon )); + + if (TMath::Abs(1-CN/CNttt)>1E-10 || TMath::Abs(1-CT/CTttt)>1E-10 || TMath::Abs(1-CL/CLttt)>1E-10) + { + std::cout << "*******************************************************************************************************\n"; + std::cout << "*******************************************************************************************************\n"; + std::cout << "CN = " << CN << ", CT = " << CT << ", CL = " << CL << "\n"; + std::cout << "CN = " << CNttt << ", CT = " << CTttt << ", CL = " << CLttt << "\n"; + std::cout << "*******************************************************************************************************\n"; + std::cout << "*******************************************************************************************************\n"; + } if ( imU > 0 ) return 0; @@ -1834,3 +1848,340 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac return 0; } //___________________________________________________________________________________ + + + + + + + + + + + + + + + + + +//___________________________________________________________________________ +void NievesQELCCPXSec::CNCTCLimUcalcttt(TLorentzVector qTildeP4, + double M, double r, bool is_neutrino, bool tgtIsNucleus, int tgt_pdgc, + int A, int Z, int N, bool hitNucIsProton, double & CN, double & CT, double & CL, + double & imaginaryU, double & t0, double & r00, bool assumeFreeNucleon) const +{ + if ( tgtIsNucleus && !assumeFreeNucleon ) { + double dq = qTildeP4.Vect().Mag(); + double dq2 = TMath::Power(dq,2); + double q2 = 1 * qTildeP4.Mag2(); + //Terms for polarization coefficients CN,CT, and CL + double hbarc2 = TMath::Power(fhbarc,2); + double c0 = 0.380/fhbarc;//Constant for CN in natural units + + //Density gives the nuclear density, normalized to 1 + //Input radius r must be in fm + double rhop = nuclear::Density(r,A)*Z; + double rhon = nuclear::Density(r,A)*N; + double rho = rhop + rhon; + double rho0 = A*nuclear::Density(0,A); + + double fPrime = (0.33*rho/rho0+0.45*(1-rho/rho0))*c0; + + // Get Fermi momenta + double kF1, kF2; + if(fLFG) + { + //if(hitNucIsProton){ + //kF1 = TMath::Power(3*kPi2*rhop, 1.0/3.0) *fhbarc; + //kF2 = TMath::Power(3*kPi2*rhon, 1.0/3.0) *fhbarc; + //} + //else + //{ + kF1 = TMath::Power(3*kPi2*rhon, 1.0/3.0) *fhbarc; + kF2 = TMath::Power(3*kPi2*rhop, 1.0/3.0) *fhbarc; +// } + } + else{ + //if(hitNucIsProton) + //{ + //kF1 = fKFTable->FindClosestKF(tgt_pdgc, kPdgProton); + //kF2 = fKFTable->FindClosestKF(tgt_pdgc, kPdgNeutron); + //} + //else + //{ + kF1 = fKFTable->FindClosestKF(tgt_pdgc, kPdgNeutron); + kF2 = fKFTable->FindClosestKF(tgt_pdgc, kPdgProton); +// } + } + + double kF = TMath::Power(1.5*kPi2*rho, 1.0/3.0) *fhbarc; + + std::complex imU(relLindhardImttt(qTildeP4.E(),dq,kF1,kF2, + M,is_neutrino,t0,r00)); + + imaginaryU = imag(imU); + + std::complex relLin(0,0),udel(0,0); + + // By comparison with Nieves' fortran code + if(imaginaryU < 0.){ + relLin = relLindhardttt(qTildeP4.E(),dq,kF,M,is_neutrino,imU); + udel = deltaLindhardttt(qTildeP4.E(),dq,rho,kF); + } + std::complex relLinTot(relLin + udel); + /* CRho = 2 + DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2 + mRho = 770 MeV, (0.770 GeV)^2 = 0.5929 GeV^2 + g' = 0.63 */ + double Vt = 0.08*4*kPi/kPionMass2 * + (2* TMath::Power((6.25-0.5929)/(6.25-q2),2)*dq2/(q2-0.5929) + 0.63); + /* f^2/4/Pi = 0.08 + DeltaSubPi = 1200 MeV, (1.2 GeV)^2 = 1.44 GeV^2 + g' = 0.63 */ + double Vl = 0.08*4*kPi/kPionMass2 * + (TMath::Power((1.44-kPionMass2)/(1.44-q2),2)*dq2/(q2-kPionMass2)+0.63); + + CN = 1.0/TMath::Power(abs(1.0-fPrime*relLin/hbarc2),2); + + CT = 1.0/TMath::Power(abs(1.0-relLinTot*Vt),2); + CL = 1.0/TMath::Power(abs(1.0-relLinTot*Vl),2); + } + else { + //Polarization Coefficients: all equal to 1.0 for free nucleon + CN = 1.0; + CT = 1.0; + CL = 1.0; + imaginaryU = 0.0; + } +} +//____________________________________________________________________________ +// Gives the imaginary part of the relativistic lindhard function in GeV^2 +// and sets the values of t0 and r00 +std::complex NievesQELCCPXSec::relLindhardImttt(double q0, double dq, + double kFn, double kFp, + double M, + bool isNeutrino, + double & t0, + double & r00) const +{ + double M2 = TMath::Power(M,2); + double EF1,EF2; + if(isNeutrino){ + EF1 = TMath::Sqrt(M2+TMath::Power(kFn,2)); //EFn + EF2 = TMath::Sqrt(M2+TMath::Power(kFp,2)); //EFp + }else{ + EF1 = TMath::Sqrt(M2+TMath::Power(kFp,2)); //EFp + EF2 = TMath::Sqrt(M2+TMath::Power(kFn,2)); //EFn + } + + double q2 = TMath::Power(q0,2) - TMath::Power(dq,2); + double a = (-q0+dq*TMath::Sqrt(1-4.0*M2/q2))/2.0; + double epsRP = TMath::Max(TMath::Max(M,EF2-q0),a); + + // Other theta functions for q are handled by nuclear suppression + // That is, q0>0 and -q2>0 are always handled, and q0>EF2-EF1 is + // handled if pauli blocking is on, because otherwise the final + // nucleon would be below the fermi sea + //if(fNievesSuppression && !interaction->TestBit(kIAssumeFreeNucleon ) + //&& !EF1-epsRP<0){ + //LOG("Nieves", pINFO) << "Average value of E(p) above Fermi sea"; + //return 0; + //}else{ + t0 = 0.5*(EF1+epsRP); + r00 = (TMath::Power(EF1,2)+TMath::Power(epsRP,2)+EF1*epsRP)/3.0; + std::complex result(0.0,-M2/2.0/kPi/dq*(EF1-epsRP)); + return result; + //} +} +//____________________________________________________________________________ +//Following obtained from fortran code by J Nieves, which contained the following comment: +/* + NUCLEON relativistic Lindhard Function + Same normalization as ULIN + Real part + taken from Eur.Phys.J.A25:299-318,2005 (Barbaro et al) + Eq. 61 + + Im. part: Juan. + + INPUT: Real*8 + q0:Energy [fm] + qm: modulus 3mom [fm] + kf: Fermi mom [fm] + + OUTPUT: Complex*16 [fm] + + USES: ruLinRelX, relLindhardIm + */ +//Takes inputs in GeV (with imU in GeV^2), and gives output in GeV^2 +std::complex NievesQELCCPXSec::relLindhardttt(double q0gev, + double dqgev, double kFgev, double M, + bool isNeutrino, + std::complex /* relLindIm */) const +{ + double q0 = q0gev/fhbarc; + double qm = dqgev/fhbarc; + double kf = kFgev/fhbarc; + double m = M/fhbarc; + + if(q0>qm){ + LOG("Nieves", pWARN) << "relLindhard() failed"; + return 0.0; + } + + std::complex RealLinRel(ruLinRelXttt(q0,qm,kf,m)+ruLinRelXttt(-q0,qm,kf,m)); + double t0,r00; + std::complex ImLinRel(relLindhardImttt(q0gev,dqgev,kFgev,kFgev,M,isNeutrino,t0,r00)); + //Units of GeV^2 + return(RealLinRel*TMath::Power(fhbarc,2) + 2.0*ImLinRel); +} +//____________________________________________________________________________ +//Inputs assumed to be in natural units +std::complex NievesQELCCPXSec::ruLinRelXttt(double q0, double qm, + double kf, double m) const +{ + double q02 = TMath::Power(q0, 2); + double qm2 = TMath::Power(qm, 2); + double kf2 = TMath::Power(kf, 2); + double m2 = TMath::Power(m, 2); + double m4 = TMath::Power(m, 4); + + double ef = TMath::Sqrt(m2+kf2); + double q2 = q02-qm2; + double q4 = TMath::Power(q2,2); + double ds = TMath::Sqrt(1.0-4.0*m2/q2); + double L1 = log((kf+ef)/m); + std::complex uL2( + TMath::Log(TMath::Abs( + (ef + q0 - TMath::Sqrt(m2+TMath::Power(kf-qm,2)))/ + (ef + q0 - TMath::Sqrt(m2 + TMath::Power(kf + qm,2))))) + + TMath::Log(TMath::Abs( + (ef + q0 + TMath::Sqrt(m2 + TMath::Power(kf - qm,2)))/ + (ef + q0 + TMath::Sqrt(m2 + TMath::Power(kf + qm,2)))))); + + std::complex uL3( + TMath::Log(TMath::Abs((TMath::Power(2*kf + q0*ds,2)-qm2)/ + (TMath::Power(2*kf - q0*ds,2)-qm2))) + + TMath::Log(TMath::Abs((TMath::Power(kf-ef*ds,2) - (4*m4*qm2)/q4)/ + (TMath::Power(kf+ef*ds,2) - (4*m4*qm2)/q4)))); + + + std::complex RlinrelX(-L1/(16.0*kPi2)+ + uL2*(2.0*ef+q0)/(32.0*kPi2*qm)- + uL3*ds/(64.0*kPi2)); + + return RlinrelX*16.0*m2; +} +//____________________________________________________________________________ +//Following obtained from fortran code by J Nieves, which contained the following comment: +/* + complex Lindhard function for symmetric nuclear matter: + from Appendix of + E.Oset et al Phys. Rept. 188:79, 1990 + formula A.4 + + input variables: + q_zero [fm^-1] : Energy + q_mod [fm^-1] : Momentum + rho [fm^3] : Nuclear density + k_fermi[fm^-1] : Fermi momentum + + All variables are real*8 + + output variable: + delta_lind [fm^-2] + + ATTENTION!!! + Only works properly for real q_zero, + if q_zero has an imaginary part calculates the L. function + assuming Gamma= 0. + Therefore this subroutine provides two different functions + depending on whether q_zero is real or not!!!!!!!!!!! +*/ +std::complex NievesQELCCPXSec::deltaLindhardttt(double q0, + double dq, double rho, double kF) const +{ + double q_zero = q0/fhbarc; + double q_mod = dq/fhbarc; + double k_fermi = kF/fhbarc; + //Divide by hbarc in order to use natural units (rho is already in the correct units) + + //m = 939/197.3, md = 1232/197.3, mpi = 139/197.3 + double m = 4.7592; + double md = 6.2433; + double mpi = 0.7045; + + double fdel_f2 = 0.45; + double wr = md-m; + double gamma = 0; + double gammap = 0; + + double q_zero2 = TMath::Power(q_zero, 2); + double q_mod2 = TMath::Power(q_mod, 2); + double k_fermi2 = TMath::Power(k_fermi, 2); + + double m2 = TMath::Power(m, 2); + double m4 = TMath::Power(m, 4); + double mpi2 = TMath::Power(mpi, 2); + double mpi4 = TMath::Power(mpi, 4); + + //double fdel_f2 = TMath::Power(fdel_f, 2); + + //For the current code q_zero is always real + //If q_zero can have an imaginary part then only the real part is used + //until z and zp are calculated + + double s = m2+q_zero2-q_mod2+ + 2.0*q_zero *TMath::Sqrt(m2+3.0/5.0*k_fermi2); + + if(s>TMath::Power(m+mpi,2)){ + double srot = TMath::Sqrt(s); + double qcm = TMath::Sqrt(TMath::Power(s,2)+mpi4+m4-2.0*(s*mpi2+s*m2+ + mpi2*m2)) /(2.0*srot); + gamma = 1.0/3.0 * 1.0/(4.0*kPi) * fdel_f2* + TMath::Power(qcm,3)/srot*(m+TMath::Sqrt(m2+TMath::Power(qcm,2)))/mpi2; + } + double sp = m2+q_zero2-q_mod2- + 2.0*q_zero *TMath::Sqrt(m2+3.0/5.0*k_fermi2); + + + if(sp > TMath::Power(m+mpi,2)){ + double srotp = TMath::Sqrt(sp); + double qcmp = TMath::Sqrt(TMath::Power(sp,2)+mpi4+m4-2.0*(sp*mpi2+sp*m2+ + mpi2*m2))/(2.0*srotp); + gammap = 1.0/3.0 * 1.0/(4.0*kPi) * fdel_f2* + TMath::Power(qcmp,3)/srotp*(m+TMath::Sqrt(m2+TMath::Power(qcmp,2)))/mpi2; + } + //}//End if statement + const std::complex iNum(0,1.0); + + std::complex z(md/(q_mod*k_fermi)*(q_zero-q_mod2/(2.0*md) + -wr +iNum*gamma/2.0)); + std::complex zp(md/(q_mod*k_fermi)*(-q_zero-q_mod2/(2.0*md) + -wr +iNum*gammap/2.0)); + + std::complex pzeta(0.0); + if(abs(z) > 50.0){ + pzeta = 2.0/(3.0*z)+2.0/(15.0*z*z*z); + }else if(abs(z) < TMath::Power(10.0,-2)){ + pzeta = 2.0*z-2.0/3.0*z*z*z-iNum*kPi/2.0*(1.0-z*z); + }else{ + pzeta = z + (1.0-z*z) * log((z+1.0)/(z-1.0))/2.0; + } + + std::complex pzetap(0); + if(abs(zp) > 50.0){ + pzetap = 2.0/(3.0*zp)+2.0/(15.0*zp*zp*zp); + }else if(abs(zp) < TMath::Power(10.0,-2)){ + pzetap = 2.0*zp-2.0/3.0*zp*zp*zp-iNum*kPi/2.0*(1.0-zp*zp); + }else{ + pzetap = zp+ (1.0-zp*zp) * log((zp+1.0)/(zp-1.0))/2.0; + } + + //Multiply by hbarc^2 to give answer in units of GeV^2 + return 2.0/3.0 * rho * md/(q_mod*k_fermi) * (pzeta +pzetap) * fdel_f2 * + TMath::Power(fhbarc,2); +} + +//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index c00e4e1aba..3e3c25336a 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -131,12 +131,37 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double M, bool isNeutrino, double & t0, double & r00) const; std::complex relLindhard(double q0gev, double dqgev, - double kFgev, double M, - double ImU) const; + double kFgev, double M) const; double ruLinRelX(double q0, double qm, double kf, double m) const; std::complex deltaLindhard(double q0gev, double dqgev, + double rho, double kFgev) const; + +/////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// + // Calculates values of CN, CT, CL, and imU, and stores them in the provided + // variables. If target is not a nucleus, then CN, CN, and CL are all 1.0. + // r must be in units of fm. + void CNCTCLimUcalcttt(TLorentzVector qTildeP4, double M, double r, + bool is_neutrino, bool tgtIsNucleus, int tgt_pdgc, int A, int Z, int N, + bool hitNucIsProton, double & CN, double & CT, double & CL, double & imU, + double & t0, double & r00, bool assumeFreeNucleon) const; + + //Equations to calculate the relativistic Lindhard function for Amunu + std::complex relLindhardImttt(double q0gev, double dqgev, + double kFngev, double kFpgev, + double M, bool isNeutrino, + double & t0, double & r00) const; + std::complex relLindhardttt(double q0gev, double dqgev, + double kFgev, double M, + bool isNeutrino, + std::complex relLindIm) const; + std::complex ruLinRelXttt(double q0, double qm, + double kf, double m) const; + std::complex deltaLindhardttt(double q0gev, double dqgev, double rho, double kFgev) const; +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// // Potential for coulomb correction double vcr(const Target * target, double r) const; From bfc12ec455a529617a63cf27da8cd432b07e025f Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 30 Jan 2025 04:07:16 +0300 Subject: [PATCH 18/78] remove test methods --- .../XSection/NievesQELCCPXSec.cxx | 353 ------------------ .../QuasiElastic/XSection/NievesQELCCPXSec.h | 26 -- 2 files changed, 379 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 72e0e5df24..eb2c757458 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1741,22 +1741,6 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac tgt_pdgc, A, Z, N, CN, CT, CL, imU, t0, r00, interaction->TestBit( kIAssumeFreeNucleon )); - double t0ttt,r00ttt; - double CNttt(1), CTttt(1), CLttt(1), imUttt(0); - CNCTCLimUcalcttt(qTildeP4, M, r, is_neutrino, tgtIsNucleus, - tgt_pdgc, A, Z, N, !is_neutrino, CNttt, CTttt, CLttt, imUttt, - t0ttt, r00ttt, interaction->TestBit( kIAssumeFreeNucleon )); - - if (TMath::Abs(1-CN/CNttt)>1E-10 || TMath::Abs(1-CT/CTttt)>1E-10 || TMath::Abs(1-CL/CLttt)>1E-10) - { - std::cout << "*******************************************************************************************************\n"; - std::cout << "*******************************************************************************************************\n"; - std::cout << "CN = " << CN << ", CT = " << CT << ", CL = " << CL << "\n"; - std::cout << "CN = " << CNttt << ", CT = " << CTttt << ", CL = " << CLttt << "\n"; - std::cout << "*******************************************************************************************************\n"; - std::cout << "*******************************************************************************************************\n"; - } - if ( imU > 0 ) return 0; if ( !fRPA || interaction->TestBit( kIAssumeFreeNucleon ) ) @@ -1848,340 +1832,3 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac return 0; } //___________________________________________________________________________________ - - - - - - - - - - - - - - - - - -//___________________________________________________________________________ -void NievesQELCCPXSec::CNCTCLimUcalcttt(TLorentzVector qTildeP4, - double M, double r, bool is_neutrino, bool tgtIsNucleus, int tgt_pdgc, - int A, int Z, int N, bool hitNucIsProton, double & CN, double & CT, double & CL, - double & imaginaryU, double & t0, double & r00, bool assumeFreeNucleon) const -{ - if ( tgtIsNucleus && !assumeFreeNucleon ) { - double dq = qTildeP4.Vect().Mag(); - double dq2 = TMath::Power(dq,2); - double q2 = 1 * qTildeP4.Mag2(); - //Terms for polarization coefficients CN,CT, and CL - double hbarc2 = TMath::Power(fhbarc,2); - double c0 = 0.380/fhbarc;//Constant for CN in natural units - - //Density gives the nuclear density, normalized to 1 - //Input radius r must be in fm - double rhop = nuclear::Density(r,A)*Z; - double rhon = nuclear::Density(r,A)*N; - double rho = rhop + rhon; - double rho0 = A*nuclear::Density(0,A); - - double fPrime = (0.33*rho/rho0+0.45*(1-rho/rho0))*c0; - - // Get Fermi momenta - double kF1, kF2; - if(fLFG) - { - //if(hitNucIsProton){ - //kF1 = TMath::Power(3*kPi2*rhop, 1.0/3.0) *fhbarc; - //kF2 = TMath::Power(3*kPi2*rhon, 1.0/3.0) *fhbarc; - //} - //else - //{ - kF1 = TMath::Power(3*kPi2*rhon, 1.0/3.0) *fhbarc; - kF2 = TMath::Power(3*kPi2*rhop, 1.0/3.0) *fhbarc; -// } - } - else{ - //if(hitNucIsProton) - //{ - //kF1 = fKFTable->FindClosestKF(tgt_pdgc, kPdgProton); - //kF2 = fKFTable->FindClosestKF(tgt_pdgc, kPdgNeutron); - //} - //else - //{ - kF1 = fKFTable->FindClosestKF(tgt_pdgc, kPdgNeutron); - kF2 = fKFTable->FindClosestKF(tgt_pdgc, kPdgProton); -// } - } - - double kF = TMath::Power(1.5*kPi2*rho, 1.0/3.0) *fhbarc; - - std::complex imU(relLindhardImttt(qTildeP4.E(),dq,kF1,kF2, - M,is_neutrino,t0,r00)); - - imaginaryU = imag(imU); - - std::complex relLin(0,0),udel(0,0); - - // By comparison with Nieves' fortran code - if(imaginaryU < 0.){ - relLin = relLindhardttt(qTildeP4.E(),dq,kF,M,is_neutrino,imU); - udel = deltaLindhardttt(qTildeP4.E(),dq,rho,kF); - } - std::complex relLinTot(relLin + udel); - /* CRho = 2 - DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2 - mRho = 770 MeV, (0.770 GeV)^2 = 0.5929 GeV^2 - g' = 0.63 */ - double Vt = 0.08*4*kPi/kPionMass2 * - (2* TMath::Power((6.25-0.5929)/(6.25-q2),2)*dq2/(q2-0.5929) + 0.63); - /* f^2/4/Pi = 0.08 - DeltaSubPi = 1200 MeV, (1.2 GeV)^2 = 1.44 GeV^2 - g' = 0.63 */ - double Vl = 0.08*4*kPi/kPionMass2 * - (TMath::Power((1.44-kPionMass2)/(1.44-q2),2)*dq2/(q2-kPionMass2)+0.63); - - CN = 1.0/TMath::Power(abs(1.0-fPrime*relLin/hbarc2),2); - - CT = 1.0/TMath::Power(abs(1.0-relLinTot*Vt),2); - CL = 1.0/TMath::Power(abs(1.0-relLinTot*Vl),2); - } - else { - //Polarization Coefficients: all equal to 1.0 for free nucleon - CN = 1.0; - CT = 1.0; - CL = 1.0; - imaginaryU = 0.0; - } -} -//____________________________________________________________________________ -// Gives the imaginary part of the relativistic lindhard function in GeV^2 -// and sets the values of t0 and r00 -std::complex NievesQELCCPXSec::relLindhardImttt(double q0, double dq, - double kFn, double kFp, - double M, - bool isNeutrino, - double & t0, - double & r00) const -{ - double M2 = TMath::Power(M,2); - double EF1,EF2; - if(isNeutrino){ - EF1 = TMath::Sqrt(M2+TMath::Power(kFn,2)); //EFn - EF2 = TMath::Sqrt(M2+TMath::Power(kFp,2)); //EFp - }else{ - EF1 = TMath::Sqrt(M2+TMath::Power(kFp,2)); //EFp - EF2 = TMath::Sqrt(M2+TMath::Power(kFn,2)); //EFn - } - - double q2 = TMath::Power(q0,2) - TMath::Power(dq,2); - double a = (-q0+dq*TMath::Sqrt(1-4.0*M2/q2))/2.0; - double epsRP = TMath::Max(TMath::Max(M,EF2-q0),a); - - // Other theta functions for q are handled by nuclear suppression - // That is, q0>0 and -q2>0 are always handled, and q0>EF2-EF1 is - // handled if pauli blocking is on, because otherwise the final - // nucleon would be below the fermi sea - //if(fNievesSuppression && !interaction->TestBit(kIAssumeFreeNucleon ) - //&& !EF1-epsRP<0){ - //LOG("Nieves", pINFO) << "Average value of E(p) above Fermi sea"; - //return 0; - //}else{ - t0 = 0.5*(EF1+epsRP); - r00 = (TMath::Power(EF1,2)+TMath::Power(epsRP,2)+EF1*epsRP)/3.0; - std::complex result(0.0,-M2/2.0/kPi/dq*(EF1-epsRP)); - return result; - //} -} -//____________________________________________________________________________ -//Following obtained from fortran code by J Nieves, which contained the following comment: -/* - NUCLEON relativistic Lindhard Function - Same normalization as ULIN - Real part - taken from Eur.Phys.J.A25:299-318,2005 (Barbaro et al) - Eq. 61 - - Im. part: Juan. - - INPUT: Real*8 - q0:Energy [fm] - qm: modulus 3mom [fm] - kf: Fermi mom [fm] - - OUTPUT: Complex*16 [fm] - - USES: ruLinRelX, relLindhardIm - */ -//Takes inputs in GeV (with imU in GeV^2), and gives output in GeV^2 -std::complex NievesQELCCPXSec::relLindhardttt(double q0gev, - double dqgev, double kFgev, double M, - bool isNeutrino, - std::complex /* relLindIm */) const -{ - double q0 = q0gev/fhbarc; - double qm = dqgev/fhbarc; - double kf = kFgev/fhbarc; - double m = M/fhbarc; - - if(q0>qm){ - LOG("Nieves", pWARN) << "relLindhard() failed"; - return 0.0; - } - - std::complex RealLinRel(ruLinRelXttt(q0,qm,kf,m)+ruLinRelXttt(-q0,qm,kf,m)); - double t0,r00; - std::complex ImLinRel(relLindhardImttt(q0gev,dqgev,kFgev,kFgev,M,isNeutrino,t0,r00)); - //Units of GeV^2 - return(RealLinRel*TMath::Power(fhbarc,2) + 2.0*ImLinRel); -} -//____________________________________________________________________________ -//Inputs assumed to be in natural units -std::complex NievesQELCCPXSec::ruLinRelXttt(double q0, double qm, - double kf, double m) const -{ - double q02 = TMath::Power(q0, 2); - double qm2 = TMath::Power(qm, 2); - double kf2 = TMath::Power(kf, 2); - double m2 = TMath::Power(m, 2); - double m4 = TMath::Power(m, 4); - - double ef = TMath::Sqrt(m2+kf2); - double q2 = q02-qm2; - double q4 = TMath::Power(q2,2); - double ds = TMath::Sqrt(1.0-4.0*m2/q2); - double L1 = log((kf+ef)/m); - std::complex uL2( - TMath::Log(TMath::Abs( - (ef + q0 - TMath::Sqrt(m2+TMath::Power(kf-qm,2)))/ - (ef + q0 - TMath::Sqrt(m2 + TMath::Power(kf + qm,2))))) + - TMath::Log(TMath::Abs( - (ef + q0 + TMath::Sqrt(m2 + TMath::Power(kf - qm,2)))/ - (ef + q0 + TMath::Sqrt(m2 + TMath::Power(kf + qm,2)))))); - - std::complex uL3( - TMath::Log(TMath::Abs((TMath::Power(2*kf + q0*ds,2)-qm2)/ - (TMath::Power(2*kf - q0*ds,2)-qm2))) + - TMath::Log(TMath::Abs((TMath::Power(kf-ef*ds,2) - (4*m4*qm2)/q4)/ - (TMath::Power(kf+ef*ds,2) - (4*m4*qm2)/q4)))); - - - std::complex RlinrelX(-L1/(16.0*kPi2)+ - uL2*(2.0*ef+q0)/(32.0*kPi2*qm)- - uL3*ds/(64.0*kPi2)); - - return RlinrelX*16.0*m2; -} -//____________________________________________________________________________ -//Following obtained from fortran code by J Nieves, which contained the following comment: -/* - complex Lindhard function for symmetric nuclear matter: - from Appendix of - E.Oset et al Phys. Rept. 188:79, 1990 - formula A.4 - - input variables: - q_zero [fm^-1] : Energy - q_mod [fm^-1] : Momentum - rho [fm^3] : Nuclear density - k_fermi[fm^-1] : Fermi momentum - - All variables are real*8 - - output variable: - delta_lind [fm^-2] - - ATTENTION!!! - Only works properly for real q_zero, - if q_zero has an imaginary part calculates the L. function - assuming Gamma= 0. - Therefore this subroutine provides two different functions - depending on whether q_zero is real or not!!!!!!!!!!! -*/ -std::complex NievesQELCCPXSec::deltaLindhardttt(double q0, - double dq, double rho, double kF) const -{ - double q_zero = q0/fhbarc; - double q_mod = dq/fhbarc; - double k_fermi = kF/fhbarc; - //Divide by hbarc in order to use natural units (rho is already in the correct units) - - //m = 939/197.3, md = 1232/197.3, mpi = 139/197.3 - double m = 4.7592; - double md = 6.2433; - double mpi = 0.7045; - - double fdel_f2 = 0.45; - double wr = md-m; - double gamma = 0; - double gammap = 0; - - double q_zero2 = TMath::Power(q_zero, 2); - double q_mod2 = TMath::Power(q_mod, 2); - double k_fermi2 = TMath::Power(k_fermi, 2); - - double m2 = TMath::Power(m, 2); - double m4 = TMath::Power(m, 4); - double mpi2 = TMath::Power(mpi, 2); - double mpi4 = TMath::Power(mpi, 4); - - //double fdel_f2 = TMath::Power(fdel_f, 2); - - //For the current code q_zero is always real - //If q_zero can have an imaginary part then only the real part is used - //until z and zp are calculated - - double s = m2+q_zero2-q_mod2+ - 2.0*q_zero *TMath::Sqrt(m2+3.0/5.0*k_fermi2); - - if(s>TMath::Power(m+mpi,2)){ - double srot = TMath::Sqrt(s); - double qcm = TMath::Sqrt(TMath::Power(s,2)+mpi4+m4-2.0*(s*mpi2+s*m2+ - mpi2*m2)) /(2.0*srot); - gamma = 1.0/3.0 * 1.0/(4.0*kPi) * fdel_f2* - TMath::Power(qcm,3)/srot*(m+TMath::Sqrt(m2+TMath::Power(qcm,2)))/mpi2; - } - double sp = m2+q_zero2-q_mod2- - 2.0*q_zero *TMath::Sqrt(m2+3.0/5.0*k_fermi2); - - - if(sp > TMath::Power(m+mpi,2)){ - double srotp = TMath::Sqrt(sp); - double qcmp = TMath::Sqrt(TMath::Power(sp,2)+mpi4+m4-2.0*(sp*mpi2+sp*m2+ - mpi2*m2))/(2.0*srotp); - gammap = 1.0/3.0 * 1.0/(4.0*kPi) * fdel_f2* - TMath::Power(qcmp,3)/srotp*(m+TMath::Sqrt(m2+TMath::Power(qcmp,2)))/mpi2; - } - //}//End if statement - const std::complex iNum(0,1.0); - - std::complex z(md/(q_mod*k_fermi)*(q_zero-q_mod2/(2.0*md) - -wr +iNum*gamma/2.0)); - std::complex zp(md/(q_mod*k_fermi)*(-q_zero-q_mod2/(2.0*md) - -wr +iNum*gammap/2.0)); - - std::complex pzeta(0.0); - if(abs(z) > 50.0){ - pzeta = 2.0/(3.0*z)+2.0/(15.0*z*z*z); - }else if(abs(z) < TMath::Power(10.0,-2)){ - pzeta = 2.0*z-2.0/3.0*z*z*z-iNum*kPi/2.0*(1.0-z*z); - }else{ - pzeta = z + (1.0-z*z) * log((z+1.0)/(z-1.0))/2.0; - } - - std::complex pzetap(0); - if(abs(zp) > 50.0){ - pzetap = 2.0/(3.0*zp)+2.0/(15.0*zp*zp*zp); - }else if(abs(zp) < TMath::Power(10.0,-2)){ - pzetap = 2.0*zp-2.0/3.0*zp*zp*zp-iNum*kPi/2.0*(1.0-zp*zp); - }else{ - pzetap = zp+ (1.0-zp*zp) * log((zp+1.0)/(zp-1.0))/2.0; - } - - //Multiply by hbarc^2 to give answer in units of GeV^2 - return 2.0/3.0 * rho * md/(q_mod*k_fermi) * (pzeta +pzetap) * fdel_f2 * - TMath::Power(fhbarc,2); -} - -//____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 3e3c25336a..0a2e3a9983 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -137,32 +137,6 @@ class NievesQELCCPXSec : public XSecAlgorithmI { std::complex deltaLindhard(double q0gev, double dqgev, double rho, double kFgev) const; -/////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////// - // Calculates values of CN, CT, CL, and imU, and stores them in the provided - // variables. If target is not a nucleus, then CN, CN, and CL are all 1.0. - // r must be in units of fm. - void CNCTCLimUcalcttt(TLorentzVector qTildeP4, double M, double r, - bool is_neutrino, bool tgtIsNucleus, int tgt_pdgc, int A, int Z, int N, - bool hitNucIsProton, double & CN, double & CT, double & CL, double & imU, - double & t0, double & r00, bool assumeFreeNucleon) const; - - //Equations to calculate the relativistic Lindhard function for Amunu - std::complex relLindhardImttt(double q0gev, double dqgev, - double kFngev, double kFpgev, - double M, bool isNeutrino, - double & t0, double & r00) const; - std::complex relLindhardttt(double q0gev, double dqgev, - double kFgev, double M, - bool isNeutrino, - std::complex relLindIm) const; - std::complex ruLinRelXttt(double q0, double qm, - double kf, double m) const; - std::complex deltaLindhardttt(double q0gev, double dqgev, - double rho, double kFgev) const; -//////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////// - // Potential for coulomb correction double vcr(const Target * target, double r) const; From a889a2db289f1ea713aae5853f471a4f5614ad95 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 30 Jan 2025 04:12:39 +0300 Subject: [PATCH 19/78] comment out test logs --- src/Physics/Common/PrimaryLeptonUtils.cxx | 12 ++++++------ .../QuasiElastic/XSection/NievesQELCCPXSec.cxx | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 64ec7ce5b1..37e22c064f 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -166,9 +166,9 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); TVector3 Py = Pz.Cross(Px); polarization = PT*Px + PP*Py + PL*Pz; - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << "\n"; - std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << "\n"; +// std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; } //____________________________________________________________________________ void genie::utils::CalculatePolarizationVectorWithStructureFunctions( @@ -286,9 +286,9 @@ void genie::utils::CalculatePolarizationVectorInTargetRestFrame( TVector3 Px = neutrinoMomTRF3.Cross(leptonMomTRF3).Unit(); TVector3 Py = Pz.Cross(Px); polarization = PT*Px + PP*Py + PL*Pz; - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << ", R = " << R << "\n"; - std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << ", R = " << R << "\n"; +// std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; } //____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index eb2c757458..459f85c1b7 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1435,9 +1435,9 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "NV@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << fFinalLeptonPolarization.Mag() << "\n"; +// std::cout << "NV@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; From e675e544506eb912a2db215672daba300172651e Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 30 Jan 2025 13:45:41 +0300 Subject: [PATCH 20/78] small optimization --- .../QuasiElastic/XSection/NievesQELCCPXSec.cxx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 459f85c1b7..61919cbf30 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -619,11 +619,15 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, double q2 = TMath::Sq(q0) - TMath::Sq(dq); double a = (-q0 + dq*TMath::Sqrt(1 - 4*M2/q2))/2; double epsRP = TMath::Max(TMath::Max(M,EF2 - q0),a); - int factor = (EF1 - EF2 + q0 >= 0)*(EF1 - epsRP >= 0); // theta functions q0>0 and -q2>0 are always handled - t0 = factor*(EF1 + epsRP)/2; - r00 = factor*(TMath::Sq(EF1) + TMath::Sq(epsRP) + EF1*epsRP)/3; - return -factor*M2/2/kPi/dq*(EF1 - epsRP); + int theta = (EF1 - EF2 + q0 >= 0)*(EF1 - epsRP >= 0); + + if(fCompareNievesTensors) + { + t0 = theta*(EF1 + epsRP)/2; + r00 = theta*(TMath::Sq(EF1) + TMath::Sq(epsRP) + EF1*epsRP)/3; + } + return -theta*M2/2/kPi/dq*(EF1 - epsRP); } //____________________________________________________________________________ //Following obtained from fortran code by J Nieves, which contained the following comment: @@ -657,7 +661,7 @@ std::complex NievesQELCCPXSec::relLindhard(double q0gev, double dummy; double relLindIm = relLindhardIm(q0gev, dqgev, kFgev, kFgev, M, true, dummy, dummy); //Units of GeV^2 - std::complex relLind(TMath::Sq(fhbarc)*(ruLinRelX(q0,qm,kf,m) + ruLinRelX(-q0,qm,kf,m)), relLindIm); + std::complex relLind(TMath::Sq(fhbarc)*(ruLinRelX(q0,qm,kf,m) + ruLinRelX(-q0,qm,kf,m)), 2*relLindIm); return relLind; } //____________________________________________________________________________ @@ -1735,11 +1739,11 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac double Fp = fFormFactors.Fp()/M; - double t0,r00; + double dummy; double CN(1), CT(1), CL(1), imU(0); CNCTCLimUcalc(qTildeP4, M, r, is_neutrino, tgtIsNucleus, tgt_pdgc, A, Z, N, CN, CT, CL, imU, - t0, r00, interaction->TestBit( kIAssumeFreeNucleon )); + dummy, dummy, interaction->TestBit( kIAssumeFreeNucleon )); if ( imU > 0 ) return 0; From 20c0bbbd99d0d6e43fa66b4bc193291d9452d142 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 2 Feb 2025 00:14:02 +0300 Subject: [PATCH 21/78] fix singularity --- .../XSection/NievesSimoVacasMECPXSec2016.cxx | 8 +++++--- src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx | 10 ++++++---- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 7 +------ .../QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx | 6 +++--- src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 8 +++++--- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index 0d83883a6c..5b0f5a1024 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -433,9 +433,11 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int double Tl = El - ml; TVector3 neutrinoMom3 = neutrinoMom.Vect(); TVector3 leptonMom3 = leptonMom.Vect(); - double costl = neutrinoMom3.Dot(leptonMom3)/neutrinoMom3.Mag()/leptonMom3.Mag(); - double Q0 = 0.; - double Q3 = 0.; + double pv = neutrinoMom3.Mag(); + double pl = leptonMom3.Mag(); + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; + double Q0 = 0.; + double Q3 = 0.; genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); const double M = 1; // the polarization doesn't depend on mass of target in target rest frame diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index 01746dd252..9561c13424 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -493,7 +493,7 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int const Kinematics& kinematics = interaction -> Kine(); const InitialState& init_state = interaction -> InitState(); int probe_pdg = interaction->InitState().ProbePdg(); - + HadronTensorType_t tensor_type = kHT_Undefined; if ( pdg::IsNeutrino(probe_pdg) || pdg::IsAntiNeutrino(probe_pdg) ) { @@ -541,9 +541,11 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int double Tl = El - ml; TVector3 neutrinoMom3 = neutrinoMom.Vect(); TVector3 leptonMom3 = leptonMom.Vect(); - double costl = neutrinoMom3.Dot(leptonMom3)/neutrinoMom3.Mag()/leptonMom3.Mag(); - double Q0 = 0.; - double Q3 = 0.; + double pv = neutrinoMom3.Mag(); + double pl = leptonMom3.Mag(); + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; + double Q0 = 0; + double Q3 = 0; // The Q-Value essentially corrects q0 to account for nuclear // binding energy in the Valencia model but this effect is already diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 61919cbf30..544ac0bd13 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1472,15 +1472,10 @@ void NievesQELCCPXSec::FinalLeptonPolarizationOnFreeNucleon (const Interaction* TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); TLorentzVector neutrinoMom = *tempNeutrino; delete tempNeutrino; - TLorentzVector inNucleonMom(*init_state.TgtPtr()->HitNucP4Ptr()); TLorentzVector leptonMom = kinematics.FSLeptonP4(); - TLorentzVector outNucleonMom = kinematics.HadSystP4(); - - - double outNucleonEnergy = TMath::Hypot(M, outNucleonMom.P() ); - double q0Tilde = outNucleonEnergy - M; + double q0Tilde = neutrinoMom.E() - leptonMom.E(); // Note that we're working in the lab frame (i.e., the rest frame // of the target nucleus). We can therefore use Nieves' explicit diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 60cd57cccf..6a0d76d83e 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -497,8 +497,6 @@ double SmithMonizQELCCPXSec::dsQES_dQ2_SM(const Interaction * interaction) const const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - // Assuming that variables Enu, Q2, \nu and kF are within allowable kinematic region - // which are specified in methods: genie::utils::gsl::d2Xsec_dQ2dv::DoEval and QELEventGeneratorSM::ProcessEventRecord // Get kinematics & init-state parameters const Kinematics & kinematics = interaction -> Kine(); sm_utils->SetInteraction(interaction); @@ -515,7 +513,9 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio double v = Enu - El; TVector3 neutrinoMom3 = neutrinoMom.Vect(); TVector3 leptonMom3 = leptonMom.Vect(); - double cos_theta = neutrinoMom3.Dot(leptonMom3)/neutrinoMom3.Mag()/leptonMom3.Mag(); + double pv = neutrinoMom3.Mag(); + double pl = leptonMom3.Mag(); + double cos_theta = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; double aux1 = El - Pl*cos_theta; double Q2 = 2*Enu*aux1 - ml2; diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 1e4480e191..633f7123c5 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -699,9 +699,11 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int double Tl = El - ml; TVector3 neutrinoMom3 = neutrinoMom.Vect(); TVector3 leptonMom3 = leptonMom.Vect(); - double costl = neutrinoMom3.Dot(leptonMom3)/neutrinoMom3.Mag()/leptonMom3.Mag(); - double Q0 = 0.; - double Q3 = 0.; + double pv = neutrinoMom3.Mag(); + double pl = leptonMom3.Mag(); + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; + double Q0 = 0; + double Q3 = 0; genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); // *** Enforce the global Q^2 cut *** From 6e4a122926b430b097a70aa90453b68a18b72189 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 3 Feb 2025 18:13:29 +0300 Subject: [PATCH 22/78] fix a small bug --- .../XSection/SmithMonizQELCCPXSec.cxx | 59 ++++++++----------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 6a0d76d83e..4acfc9f86a 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -554,47 +554,40 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio double kkF = kF*kF; double E_p = TMath::Sqrt(mm_ini + kkF) - E_BIN; double cosT_p = ((v - E_BIN)*(2*E_p + v + E_BIN) - qqv + mm_ini - mm_fin)/(2*kF*qv); //\cos\theta_p - if (cosT_p < -1.0 || cosT_p > 1.0 ) + if (cosT_p >= -1.0 && cosT_p <= 1.0 ) { - LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; + double pF = TMath::Sqrt(kkF + 2*kF*qv*cosT_p + qqv); + double b2_flux = TMath::Sq(E_p - kF*cosT_k*cosT_p); + double c2_flux = kkF*(1 - cosT_p*cosT_p)*(1 - cosT_k*cosT_k); + // factor fVud2*mm_ini*kPi*m_tar/qv/FV_SM will be cancelled when dividing by R + double factor = kF/TMath::Sqrt(b2_flux - c2_flux)*SmithMonizUtils::rho(P_Fermi, 0, kF)*(1 - SmithMonizUtils::rho(P_Fermi, Tf, pF))*fW[d - 1 - i]; + a1 += factor; + a2 += factor*kkF/mm_ini; + a3 += factor*kkF*cosT_p*cosT_p/mm_ini; + a4 += factor*E_p*E_p/mm_ini; + a5 += factor*2*E_p*kF*cosT_p/mm_ini; + a6 += factor*kF*cosT_p/m_ini; + a7 += factor*E_p/m_ini; } - double pF = TMath::Sqrt(kkF + 2*kF*qv*cosT_p + qqv); - double b2_flux = TMath::Sq(E_p - kF*cosT_k*cosT_p); - double c2_flux = kkF*(1 - cosT_p*cosT_p)*(1 - cosT_k*cosT_k); - // factor fVud2*mm_ini*kPi*m_tar/qv/FV_SM will be cancelled when dividing by R - double factor = kF/TMath::Sqrt(b2_flux - c2_flux)*SmithMonizUtils::rho(P_Fermi, 0, kF)*(1 - SmithMonizUtils::rho(P_Fermi, Tf, pF))*fW[d - 1 - i]; - a1 += factor; - a2 += factor*kkF/mm_ini; - a3 += factor*kkF*cosT_p*cosT_p/mm_ini; - a4 += factor*E_p*E_p/mm_ini; - a5 += factor*2*E_p*kF*cosT_p/mm_ini; - a6 += factor*kF*cosT_p/m_ini; - a7 += factor*E_p/m_ini; kF = 0.5*(fR[i]*(rkF.max - rkF.min) + rkF.min + rkF.max); kkF = kF*kF; E_p = TMath::Sqrt(mm_ini + kkF)-E_BIN; - cosT_p = ((v - E_BIN)*(2*E_p + v + E_BIN) - qqv + mm_ini - mm_fin)/(2*kF*qv); //\cos\theta_p - if (cosT_p < -1.0 || cosT_p > 1.0 ) + cosT_p = ((v - E_BIN)*(2*E_p + v + E_BIN) - qqv + mm_ini - mm_fin)/(2*kF*qv); + if (cosT_p >= -1.0 && cosT_p <= 1.0 ) { - LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); - return fFinalLeptonPolarization; + double pF = TMath::Sqrt(kkF + 2*kF*qv*cosT_p + qqv); + double b2_flux = TMath::Sq(E_p - kF*cosT_k*cosT_p); + double c2_flux = kkF*(1 - cosT_p*cosT_p)*(1 - cosT_k*cosT_k); + double factor = kF/TMath::Sqrt(b2_flux - c2_flux)*SmithMonizUtils::rho(P_Fermi, 0, kF)*(1 - SmithMonizUtils::rho(P_Fermi, Tf, pF))*fW[d - 1 - i]; + a1 += factor; + a2 += factor*kkF/mm_ini; + a3 += factor*kkF*cosT_p*cosT_p/mm_ini; + a4 += factor*E_p*E_p/mm_ini; + a5 += factor*2*E_p*kF*cosT_p/mm_ini; + a6 += factor*kF*cosT_p/m_ini; + a7 += factor*E_p/m_ini; } - pF = TMath::Sqrt(kkF + 2*kF*qv*cosT_p + qqv); - b2_flux = TMath::Sq(E_p - kF*cosT_k*cosT_p); - c2_flux = kkF*(1 - cosT_p*cosT_p)*(1 - cosT_k*cosT_k); - // factor fVud2*mm_ini*kPi*m_tar/qv/FV_SM will be cancelled when dividing by R - factor = kF/TMath::Sqrt(b2_flux - c2_flux)*SmithMonizUtils::rho(P_Fermi, 0, kF)*(1 - SmithMonizUtils::rho(P_Fermi, Tf, pF))*fW[d - 1 - i]; - a1 += factor; - a2 += factor*kkF/mm_ini; - a3 += factor*kkF*cosT_p*cosT_p/mm_ini; - a4 += factor*E_p*E_p/mm_ini; - a5 += factor*2*E_p*kF*cosT_p/mm_ini; - a6 += factor*kF*cosT_p/m_ini; - a7 += factor*E_p/m_ini; } a1 *= 0.5*(rkF.max - rkF.min); a2 *= 0.5*(rkF.max - rkF.min); From d733774ccc79a8b4afaf0e8f61ad7e28211b6eec Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 3 Feb 2025 19:57:23 +0300 Subject: [PATCH 23/78] fix few bugs --- .../Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx | 2 +- src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx | 2 +- src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx | 2 +- src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index 5b0f5a1024..5e4b5a4046 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -435,7 +435,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int TVector3 leptonMom3 = leptonMom.Vect(); double pv = neutrinoMom3.Mag(); double pl = leptonMom3.Mag(); - double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 1; double Q0 = 0.; double Q3 = 0.; genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index 9561c13424..9ef8a4e26e 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -543,7 +543,7 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int TVector3 leptonMom3 = leptonMom.Vect(); double pv = neutrinoMom3.Mag(); double pl = leptonMom3.Mag(); - double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 1; double Q0 = 0; double Q3 = 0; diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 4acfc9f86a..af180229bd 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -515,7 +515,7 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio TVector3 leptonMom3 = leptonMom.Vect(); double pv = neutrinoMom3.Mag(); double pl = leptonMom3.Mag(); - double cos_theta = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; + double cos_theta = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 1; double aux1 = El - Pl*cos_theta; double Q2 = 2*Enu*aux1 - ml2; diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 633f7123c5..3c2554310c 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -701,7 +701,7 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int TVector3 leptonMom3 = leptonMom.Vect(); double pv = neutrinoMom3.Mag(); double pl = leptonMom3.Mag(); - double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 1; double Q0 = 0; double Q3 = 0; genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); From 813250575cba9755f930c1c3cd7fa6482f390620 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 3 Feb 2025 22:37:24 +0300 Subject: [PATCH 24/78] fix singularities --- src/Physics/Common/PrimaryLeptonUtils.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 37e22c064f..87197f7ea7 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -120,15 +120,17 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( for (int a = 0; a < 4; a++) { + double aux_plus = kl + ml*ks; + double aux_minus = kl - ml*ks; if (isLeftPolarized) { - jp[a] = (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jp_\alpha - jm[a] = (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl - ml*ks); //jm_\alpha + jp[a] = aux_plus !=0 ? (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(aux_plus) : 0; //jp_\alpha + jm[a] = aux_minus !=0 ? (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(aux_minus) : 0; //jm_\alpha } else { - jp[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(kl - ml*ks); //jp_\alpha - jm[a] = (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(kl + ml*ks); //jm_\alpha + jp[a] = aux_minus !=0 ? (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(aux_minus) : 0; //jp_\alpha + jm[a] = aux_plus !=0 ? (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(aux_plus) : 0; //jm_\alpha } } From 2592878dd59b0123d19e8ccc0d2b520ae1d5e5b1 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 4 Feb 2025 03:06:23 +0300 Subject: [PATCH 25/78] fix singularities --- src/Physics/Common/PrimaryLeptonUtils.cxx | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 87197f7ea7..c61abdb59e 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -124,13 +124,13 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( double aux_minus = kl - ml*ks; if (isLeftPolarized) { - jp[a] = aux_plus !=0 ? (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(aux_plus) : 0; //jp_\alpha - jm[a] = aux_minus !=0 ? (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(aux_minus) : 0; //jm_\alpha + jp[a] = aux_plus > 0 ? (l[a]*ks - s[a]*kl - 1i*eskl[a] + ml*k[a])/sqrt(aux_plus) : 0; //jp_\alpha + jm[a] = aux_minus > 0 ? (-l[a]*ks + s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(aux_minus) : 0; //jm_\alpha } else { - jp[a] = aux_minus !=0 ? (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(aux_minus) : 0; //jp_\alpha - jm[a] = aux_plus !=0 ? (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(aux_plus) : 0; //jm_\alpha + jp[a] = aux_minus > 0 ? (l[a]*ks - s[a]*kl + 1i*eskl[a] - ml*k[a])/sqrt(aux_minus) : 0; //jp_\alpha + jm[a] = aux_plus > 0 ? (l[a]*ks - s[a]*kl + 1i*eskl[a] + ml*k[a])/sqrt(aux_plus) : 0; //jm_\alpha } } @@ -221,15 +221,12 @@ void genie::utils::CalculatePolarizationVectorWithStructureFunctions( HermitianMatrix NucleonTensor(4); for(int mu = 0; mu < 4; mu++) { - for(int nu = mu;nu < 4; nu++) + for(int nu = mu; nu < 4; nu++) { double Wreal = -g(mu,nu)*W1 + p[mu]*p[nu]*W2/M2 + q[mu]*q[nu]*W4/M2 + (p[mu]*q[nu] + q[mu]*p[nu])*W5/2/M2; double Wimag = epq[mu][nu]*W3/2/M2 + (q[mu]*p[nu] - p[mu]*q[nu])*W6/2/M2; - NucleonTensor.set(mu,nu,Wreal - 1i*Wimag); // W^\mu\nu - if (mu != nu) - { - NucleonTensor.set(nu,mu,Wreal + 1i*Wimag); - } + NucleonTensor.set(mu, nu, Wreal - 1i*Wimag); // W^\mu\nu + if (mu != nu) NucleonTensor.set(nu, mu, Wreal + 1i*Wimag); } } From 99519e2e1e0f7c1780a077b103b987545ab39d9e Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 4 Feb 2025 03:25:54 +0300 Subject: [PATCH 26/78] switch off print out --- src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index 9d7bacfa8e..5851fceadf 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -633,9 +633,9 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio is_neutrino, M, W1,W2,W3,W4,W5,0); - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "LW@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << fFinalLeptonPolarization.Mag() << "\n"; +// std::cout << "LW@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } From 27517a1a6e1a4896778cc92cdf558a4bb10e2842 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 4 Feb 2025 03:32:17 +0300 Subject: [PATCH 27/78] switch off print out --- src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index af180229bd..f9d1c179f9 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -641,9 +641,9 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio m_tar, T1,T2,T3,T4,T5,0); - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "SM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << fFinalLeptonPolarization.Mag() << "\n"; +// std::cout << "SM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } From 5b806d3d04770f8b105e437226b7f5525ac314cd Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 4 Feb 2025 03:48:53 +0300 Subject: [PATCH 28/78] switch off print out --- src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx index b649f62bfc..454ccab27d 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx @@ -308,9 +308,9 @@ const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* M, W1,W2,W3,0,0,0); - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "PL@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << fFinalLeptonPolarization.Mag() << "\n"; +// std::cout << "PL@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } From 3b3ec23cf5ff80625bd21cb74a277edbd0f01c3c Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 4 Feb 2025 03:58:40 +0300 Subject: [PATCH 29/78] fix singularities --- src/Physics/Common/PrimaryLeptonUtils.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index c61abdb59e..f34febe2b8 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -154,6 +154,11 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( } std::complex LWppmm = LWpp + LWmm; + if (abs(LWppmm) == 0) + { + polarization = TVector3(0, 0, 0); + return; + } std::complex rhopp = LWpp/LWppmm; std::complex rhopm = LWpm/LWppmm; std::complex rhomp = LWmp/LWppmm; From e002fc5f096bb301ace4625fed5fbfe0400d3a03 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 4 Feb 2025 12:52:00 +0300 Subject: [PATCH 30/78] zero is orthogonal --- .../Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx | 2 +- src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx | 2 +- src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx | 2 +- src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index 5e4b5a4046..5b0f5a1024 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -435,7 +435,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int TVector3 leptonMom3 = leptonMom.Vect(); double pv = neutrinoMom3.Mag(); double pl = leptonMom3.Mag(); - double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 1; + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; double Q0 = 0.; double Q3 = 0.; genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index 9ef8a4e26e..9561c13424 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -543,7 +543,7 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int TVector3 leptonMom3 = leptonMom.Vect(); double pv = neutrinoMom3.Mag(); double pl = leptonMom3.Mag(); - double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 1; + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; double Q0 = 0; double Q3 = 0; diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index f9d1c179f9..e26843596d 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -515,7 +515,7 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio TVector3 leptonMom3 = leptonMom.Vect(); double pv = neutrinoMom3.Mag(); double pl = leptonMom3.Mag(); - double cos_theta = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 1; + double cos_theta = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; double aux1 = El - Pl*cos_theta; double Q2 = 2*Enu*aux1 - ml2; diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 3c2554310c..633f7123c5 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -701,7 +701,7 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int TVector3 leptonMom3 = leptonMom.Vect(); double pv = neutrinoMom3.Mag(); double pl = leptonMom3.Mag(); - double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 1; + double costl = pl*pv != 0 ? neutrinoMom3.Dot(leptonMom3)/pl/pv : 0; double Q0 = 0; double Q3 = 0; genie::utils::mec::Getq0q3FromTlCostl(Tl, costl, Ev, ml, Q0, Q3); From 1835942b8b8a38802b71b4df63fd3a48b8b414d8 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 4 Feb 2025 14:28:59 +0300 Subject: [PATCH 31/78] add optimizations --- src/Physics/Common/PrimaryLeptonUtils.cxx | 2 +- .../QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx | 4 ---- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 10 ++-------- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index f34febe2b8..e8bb0b63ef 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -154,7 +154,7 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( } std::complex LWppmm = LWpp + LWmm; - if (abs(LWppmm) == 0) + if (LWppmm.real() == 0 && LWppmm.imag() == 0) { polarization = TVector3(0, 0, 0); return; diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index 5851fceadf..c8bbcd1468 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -591,10 +591,6 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio double FFAT = (FA + FT)*(FA + FT); double FFMS = (FM - FS)*(FM - FS); double FFTP = (FT - FP)*(FT - FP); - - // Restore Q2 in the interaction's kinematic variables - // now that the form factors have been computed - interaction->KinePtr()->SetQ2(Q2); // Off shell mass of initial nucleon double Mi = inNucleonMom.M(); diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 544ac0bd13..4d1b12836f 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1520,7 +1520,6 @@ void NievesQELCCPXSec::FinalLeptonPolarizationOnFreeNucleon (const Interaction* // Calculate qTilde TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); - double Q2 = interaction->KinePtr()->Q2(true); double Q2tilde = -qTildeP4.Mag2(); // Check that Q2tilde > 0 (accounting for rounding errors) @@ -1535,9 +1534,7 @@ void NievesQELCCPXSec::FinalLeptonPolarizationOnFreeNucleon (const Interaction* interaction->KinePtr()->SetQ2(Q2tilde); // Calculate form factors fFormFactors.Calculate( interaction ); - // Now that the form factors have been calculated, store Q2 - // in the event instead of Q2tilde - interaction->KinePtr()->SetQ2(Q2); + // Get the QEL form factors (were calculated before this method was called) @@ -1707,7 +1704,6 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac leptonMom.SetVect(leptonMom3); } - double Q2 = interaction->KinePtr()->Q2(true); double Q2tilde = -qTildeP4.Mag2(); // Check that Q2tilde > 0 (accounting for rounding errors) @@ -1719,9 +1715,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac interaction->KinePtr()->SetQ2(Q2tilde); // Calculate form factors fFormFactors.Calculate( interaction ); - // Now that the form factors have been calculated, store Q2 - // in the event instead of Q2tilde - interaction->KinePtr()->SetQ2(Q2); + // Get the QEL form factors (were calculated before this method was called) From a2f4e61ff502d0db7f4987ac7b1ed33eb3ac78b5 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 9 Feb 2025 02:17:27 +0300 Subject: [PATCH 32/78] save before comparison with intacted code --- .../XSection/NievesQELCCPXSec.cxx | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 4d1b12836f..18f15f5f89 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -532,7 +532,7 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double q2 = qTildeP4.Mag2(); //Terms for polarization coefficients CN,CT, and CL double hbarc2 = TMath::Sq(fhbarc); - double c0 = 0.380/fhbarc;//Constant for CN in natural units + double c0 = 0.380/fhbarc/hbarc2; //Constant for CN in natural units //Density gives the nuclear density, normalized to 1 //Input radius r must be in fm @@ -565,7 +565,8 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, std::complex relLin(0, 0), udel(0, 0); // By comparison with Nieves' fortran code - if(imaginaryU < 0) + if (imaginaryU > 0) std::cerr << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " << imaginaryU << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; + if (TMath::Abs(imaginaryU) > kASmallNum)//if(imaginaryU < 0) { relLin = relLindhard(qTildeP4.E(), dq, kF, M); udel = deltaLindhard(qTildeP4.E(), dq, rho, kF); @@ -583,9 +584,9 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double Vl = 0.08*4*kPi/kPionMass2* (TMath::Sq( (1.44 - kPionMass2)/(1.44 - q2) )*dq2/(q2 - kPionMass2) + 0.63); - CN = 1/TMath::Sq(abs(1. - fPrime*relLin/hbarc2)); - CT = 1/TMath::Sq(abs(1. - relLinTot*Vt)); - CL = 1/TMath::Sq(abs(1. - relLinTot*Vl)); + CN = 1/std::norm(1. - fPrime*relLin); + CT = 1/std::norm(1. - relLinTot*Vt); + CL = 1/std::norm(1. - relLinTot*Vl); } else { @@ -618,16 +619,20 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, double q2 = TMath::Sq(q0) - TMath::Sq(dq); double a = (-q0 + dq*TMath::Sqrt(1 - 4*M2/q2))/2; - double epsRP = TMath::Max(TMath::Max(M,EF2 - q0),a); + double epsRP = TMath::Max(TMath::Max(a,EF2 - q0),M); // theta functions q0>0 and -q2>0 are always handled - int theta = (EF1 - EF2 + q0 >= 0)*(EF1 - epsRP >= 0); + if ( (EF2 - q0 > EF1) || (a > EF1) ) + { + t0 = r00 = 0; + return 0; + } if(fCompareNievesTensors) { - t0 = theta*(EF1 + epsRP)/2; - r00 = theta*(TMath::Sq(EF1) + TMath::Sq(epsRP) + EF1*epsRP)/3; + t0 = (EF1 + epsRP)/2; + r00 = (TMath::Sq(EF1) + TMath::Sq(epsRP) + EF1*epsRP)/3; } - return -theta*M2/2/kPi/dq*(EF1 - epsRP); + return -M2/2/kPi/dq*(EF1 - epsRP); } //____________________________________________________________________________ //Following obtained from fortran code by J Nieves, which contained the following comment: @@ -735,8 +740,7 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, double md = 6.2433; double mpi = 0.7045; - double fdel_f2 = 0.45; - double fdel2 = 4*0.36*kPi; + double fdel_f2 = 4.5; double wr = md - m; double gamma = 0; double gammap = 0; @@ -764,28 +768,27 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, { double srot = TMath::Sqrt(s); double qcm = TMath::Sqrt(TMath::Sq(s) + mpi4 + m4 - 2*(s*mpi2 + s*m2 + mpi2*m2))/2/srot; - gamma = fdel2*TMath::Power(qcm,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcm)))/mpi2/12/kPi/srot; + gamma = fdel_f2*TMath::Power(qcm,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcm)))/mpi2/12/kPi/srot; } if(sp > aux3) { double srotp = TMath::Sqrt(sp); double qcmp = TMath::Sqrt(TMath::Sq(sp) + mpi4 + m4 - 2*(sp*mpi2 + sp*m2 + mpi2*m2))/2/srotp; - gammap = fdel2*TMath::Power(qcmp,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcmp)))/mpi2/12/kPi/srotp; + gammap = fdel_f2*TMath::Power(qcmp,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcmp)))/mpi2/12/kPi/srotp; } std::complex z (md/q_mod/k_fermi*( q_zero - q_mod2/2./md - wr + 1i*gamma/2.)); std::complex zp(md/q_mod/k_fermi*(-q_zero - q_mod2/2./md - wr + 1i*gammap/2.)); std::complex pzeta(0, 0); - double one_sqrt10 = 1/TMath::Sq(10); std::complex z2(z*z); double abs_z = abs(z); if(abs_z > 50) { pzeta = 2.*(1. + 1./5./z2)/3./z; } - else if(abs_z < one_sqrt10) + else if(abs_z < 1e-2) { pzeta = 2.*z*(1. - z2/3.) - 1i*kPi*(1. - z2)/2.; } @@ -801,7 +804,7 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, { pzetap = 2.*(1. + 1./5./zp2)/3./zp; } - else if(abs_zp < one_sqrt10) + else if(abs_zp < 1e-2) { pzetap = 2.*zp*(1. - zp2/3.) - 1i*kPi*(1. - zp2)/2.; } @@ -1734,7 +1737,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac tgt_pdgc, A, Z, N, CN, CT, CL, imU, dummy, dummy, interaction->TestBit( kIAssumeFreeNucleon )); - if ( imU > 0 ) return 0; + if (TMath::Abs(imU) < kASmallNum) return 0;//if ( imU > 0 ) return 0; if ( !fRPA || interaction->TestBit( kIAssumeFreeNucleon ) ) { From a8b320397ebeddab736fdd54b331f5266078f341 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 9 Feb 2025 03:00:56 +0300 Subject: [PATCH 33/78] use imU is always negative --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 18f15f5f89..8855a59cec 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -565,8 +565,7 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, std::complex relLin(0, 0), udel(0, 0); // By comparison with Nieves' fortran code - if (imaginaryU > 0) std::cerr << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " << imaginaryU << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; - if (TMath::Abs(imaginaryU) > kASmallNum)//if(imaginaryU < 0) + if(imaginaryU < 0) { relLin = relLindhard(qTildeP4.E(), dq, kF, M); udel = deltaLindhard(qTildeP4.E(), dq, rho, kF); @@ -621,7 +620,7 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, double a = (-q0 + dq*TMath::Sqrt(1 - 4*M2/q2))/2; double epsRP = TMath::Max(TMath::Max(a,EF2 - q0),M); // theta functions q0>0 and -q2>0 are always handled - if ( (EF2 - q0 > EF1) || (a > EF1) ) + if ( (EF2 - q0 >= EF1) || (a >= EF1) ) { t0 = r00 = 0; return 0; @@ -1737,7 +1736,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac tgt_pdgc, A, Z, N, CN, CT, CL, imU, dummy, dummy, interaction->TestBit( kIAssumeFreeNucleon )); - if (TMath::Abs(imU) < kASmallNum) return 0;//if ( imU > 0 ) return 0; + if ( imU >= 0 ) return 0; if ( !fRPA || interaction->TestBit( kIAssumeFreeNucleon ) ) { From b11988302f579072df6f985fd64968cc66050e92 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 9 Feb 2025 16:40:55 +0300 Subject: [PATCH 34/78] opimize NievesQELCCXSec, get rid of tests --- .../XSection/NievesQELCCPXSec.cxx | 363 ++---------------- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 18 +- 2 files changed, 40 insertions(+), 341 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 8855a59cec..a7136bc552 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -40,8 +40,6 @@ #include "Framework/Numerical/GSLUtils.h" #include "Physics/Common/PrimaryLeptonUtils.h" -#include // Used for testing code -#include // Used for testing code #include "Physics/NuclearState/NuclearModelI.h" using namespace genie; @@ -71,20 +69,6 @@ NievesQELCCPXSec::~NievesQELCCPXSec() double NievesQELCCPXSec::XSec(const Interaction * interaction, KinePhaseSpace_t kps) const { - /*// TESTING CODE: - // The first time this method is called, output tensor elements and other - // kinmeatics variables for various kinematics. This can the be compared - // to Nieves' fortran code for validation purposes - if(fCompareNievesTensors){ - LOG("Nieves",pNOTICE) << "Printing tensor elements for specific " - << "kinematics for testing purposes"; - CompareNievesTensors(interaction); - fCompareNievesTensors = false; - exit(0); - } - // END TESTING CODE*/ - - if ( !this->ValidProcess (interaction) ) return 0.; if ( !this->ValidKinematics(interaction) ) return 0.; @@ -317,7 +301,7 @@ double NievesQELCCPXSec::XSec(const Interaction * interaction, xsec *= xsec_scale ; - LOG("Nieves",pDEBUG) << "TESTING: RPA=" << fRPA + LOG("Nieves",pDEBUG) << "RPA=" << fRPA << ", Coulomb=" << fCoulomb << ", q2 = " << q2 << ", xsec = " << xsec; @@ -456,10 +440,6 @@ void NievesQELCCPXSec::LoadConfig(void) assert( fKFTable ); } - // TESTING CODE - GetParamDef( "PrintDebugData", fCompareNievesTensors, false ) ; - // END TESTING CODE - // Nuclear radius parameter (R = R0*A^(1/3)) to use when computing // the maximum radius to use to integrate the Coulomb potential GetParam("NUCL-R0", fR0) ; // fm @@ -521,9 +501,8 @@ void NievesQELCCPXSec::LoadConfig(void) } //___________________________________________________________________________ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, - double M, double r, bool is_neutrino, bool tgtIsNucleus, int tgt_pdgc, - int A, int Z, int N, double & CN, double & CT, double & CL, - double & imaginaryU, double & t0, double & r00, bool assumeFreeNucleon) const + double M, double r, bool tgtIsNucleus, int A, int Z, int N, + double & CN, double & CT, double & CL, bool assumeFreeNucleon) const { if ( tgtIsNucleus && !assumeFreeNucleon ) { @@ -543,33 +522,9 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double fPrime = (0.33*rho/rho0 + 0.45*(1 - rho/rho0))*c0; - // Get Fermi momenta - double kFn, kFp; - if(fLFG) - { - kFn = TMath::Power(3*kPi2*rhon, 1.0/3.0) *fhbarc; - kFp = TMath::Power(3*kPi2*rhop, 1.0/3.0) *fhbarc; - } - else - { - kFn = fKFTable->FindClosestKF(tgt_pdgc, kPdgNeutron); - kFp = fKFTable->FindClosestKF(tgt_pdgc, kPdgProton); - } - double kF = TMath::Power(1.5*kPi2*rho, 1./3.)*fhbarc; - imaginaryU = relLindhardIm(qTildeP4.E(),dq,kFn,kFp, - M,is_neutrino,t0,r00); - - - std::complex relLin(0, 0), udel(0, 0); - - // By comparison with Nieves' fortran code - if(imaginaryU < 0) - { - relLin = relLindhard(qTildeP4.E(), dq, kF, M); - udel = deltaLindhard(qTildeP4.E(), dq, rho, kF); - } + std::complex relLin(relLindhard(qTildeP4.E(), dq, kF, M)), udel(deltaLindhard(qTildeP4.E(), dq, rho, kF)); std::complex relLinTot(relLin + udel); /* CRho = 2 DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2 @@ -593,7 +548,6 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, CN = 1.0; CT = 1.0; CL = 1.0; - imaginaryU = 0.0; } } //____________________________________________________________________________ @@ -602,9 +556,7 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double NievesQELCCPXSec::relLindhardIm(double q0, double dq, double kFn, double kFp, double M, - bool isNeutrino, - double & t0, - double & r00) const + bool isNeutrino) const { double M2 = TMath::Sq(M); double EF1,EF2; @@ -620,17 +572,8 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, double a = (-q0 + dq*TMath::Sqrt(1 - 4*M2/q2))/2; double epsRP = TMath::Max(TMath::Max(a,EF2 - q0),M); // theta functions q0>0 and -q2>0 are always handled - if ( (EF2 - q0 >= EF1) || (a >= EF1) ) - { - t0 = r00 = 0; - return 0; - } + if ( (EF2 - q0 >= EF1) || (a >= EF1) ) return 0; - if(fCompareNievesTensors) - { - t0 = (EF1 + epsRP)/2; - r00 = (TMath::Sq(EF1) + TMath::Sq(epsRP) + EF1*epsRP)/3; - } return -M2/2/kPi/dq*(EF1 - epsRP); } //____________________________________________________________________________ @@ -662,8 +605,7 @@ std::complex NievesQELCCPXSec::relLindhard(double q0gev, double kf = kFgev/fhbarc; double m = M/fhbarc; - double dummy; - double relLindIm = relLindhardIm(q0gev, dqgev, kFgev, kFgev, M, true, dummy, dummy); + double relLindIm = relLindhardIm(q0gev, dqgev, kFgev, kFgev, M, true); //Units of GeV^2 std::complex relLind(TMath::Sq(fhbarc)*(ruLinRelX(q0,qm,kf,m) + ruLinRelX(-q0,qm,kf,m)), 2*relLindIm); return relLind; @@ -897,35 +839,9 @@ double NievesQELCCPXSec::MaximalRadius(const Target * target) const } } //____________________________________________________________________________ -int NievesQELCCPXSec::leviCivita(int input[]) const{ - int copy[4] = {input[0],input[1],input[2],input[3]}; - int permutations = 0; - int temp; - - for(int i=0;i<4;i++){ - for(int j=i+1;j<4;j++){ - //If any two elements are equal return 0 - if(input[i] == input[j]) - return 0; - //If a larger number is before a smaller one, use permutations - //(exchanges of two adjacent elements) to move the smaller element - //so it is before the larger element, eg 2341->2314->2134->1234 - if(copy[i]>copy[j]){ - temp = copy[j]; - for(int k=j;k>i;k--){ - copy[k] = copy[k-1]; - permutations++; - } - copy[i] = temp; - } - } - } - - if(permutations % 2 == 0){ - return 1; - }else{ - return -1; - } +int NievesQELCCPXSec::leviCivita(int input[]) const +{ + return (input[1] - input[0])*(input[2] - input[0])*(input[3] - input[0])*(input[2] - input[1])*(input[3] - input[1])*(input[3] - input[2])/12; } //____________________________________________________________________________ // Calculates the constraction of the leptonic and hadronic tensors. The @@ -938,7 +854,7 @@ const Target& target, bool assumeFreeNucleon) const { double r = target.HitNucPosition(); bool tgtIsNucleus = target.IsNucleus(); - int tgt_pdgc = target.Pdg(); + int A = target.A(); int Z = target.Z(); int N = target.N(); @@ -950,7 +866,7 @@ const Target& target, bool assumeFreeNucleon) const double q2 = qTildeP4.Mag2(); const double q[4] = {qTildeP4.E(),qTildeP4.Px(),qTildeP4.Py(),qTildeP4.Pz()}; - double q0 = q[0]; + double dq = TMath::Sqrt(TMath::Power(q[1],2)+ TMath::Power(q[2],2)+TMath::Power(q[3],2)); @@ -970,28 +886,18 @@ const Target& target, bool assumeFreeNucleon) const #endif // Calculate auxiliary parameters - double M2 = TMath::Power(M, 2); - double FA2 = TMath::Power(FA, 2); - double F1V2 = TMath::Power(F1V, 2); - double xiF2V2 = TMath::Power(xiF2V, 2); - double q02 = TMath::Power(q[0], 2); - double dq2 = TMath::Power(dq, 2); - double q4 = TMath::Power(q2, 2); - - double t0,r00; - double CN=1.,CT=1.,CL=1.,imU=0; - CNCTCLimUcalc(qTildeP4, M, r, is_neutrino, tgtIsNucleus, - tgt_pdgc, A, Z, N, CN, CT, CL, imU, - t0, r00, assumeFreeNucleon); - - if ( imU > kASmallNum ) - return 0.; - - - if ( !fRPA || assumeFreeNucleon ) { - CN = 1.0; - CT = 1.0; - CL = 1.0; + double M2 = M*M; + double FA2 = FA*FA; + double F1V2 = F1V*F1V; + double xiF2V2 = xiF2V*xiF2V; + double q02 = q[0]*q[0]; + double dq2 = dq*dq; + + double CN(1),CT(1),CL(1); + if (fRPA) + { + CNCTCLimUcalc(qTildeP4, M, r, tgtIsNucleus, + A, Z, N, CN, CT, CL, assumeFreeNucleon); } double tulin[4] = {0.,0.,0.,0.}; @@ -1000,46 +906,17 @@ const Target& target, bool assumeFreeNucleon) const {0.,0.,0.,0.}, {0.,0.,0.,0.} }; - // TESTING CODE: - if(fCompareNievesTensors){ - // Use average values for initial momentum to calculate A, as given - // in Appendix B of Nieves' paper. T gives average values of components - // of p, and R gives the average value of two components multiplied - // together - double t3 = (0.5*q2 + q0*t0)/dq; // Average pz - - // Vector of p - - tulin[0] = t0; - tulin[3] = t3; - - // R is a 4x4 matrix, with R[mu][nu] is the average - // value of p[mu]*p[nu] - double aR = r00-M2; - double bR = (q4+4.0*r00*q02+4.0*q2*q0*t0)/(4.0*dq2); - double gamma = (aR-bR)/2.0; - double delta = (-aR+3.0*bR)/2.0/dq2; - - double r03 = (0.5*q2*t0 + q0*r00)/dq; // Average E(p)*pz - - rulin[0][0] = r00; - rulin[0][3] = r03; - rulin[1][1] = gamma; - rulin[2][2] = gamma; - rulin[3][0] = r03; - rulin[3][3] = gamma+delta*dq2; // END TESTING CODE - } - else { - // For normal code execulation, tulin is the initial nucleon momentum - tulin[0] = inNucleonMomOnShell.E(); - tulin[1] = inNucleonMomOnShell.Px(); - tulin[2] = inNucleonMomOnShell.Py(); - tulin[3] = inNucleonMomOnShell.Pz(); - for(int i=0; i<4; i++) + // Tulin is the initial nucleon momentum + tulin[0] = inNucleonMomOnShell.E(); + tulin[1] = inNucleonMomOnShell.Px(); + tulin[2] = inNucleonMomOnShell.Py(); + tulin[3] = inNucleonMomOnShell.Pz(); + + for(int i=0; i<4; i++) for(int j=0; j<4; j++) rulin[i][j] = tulin[i]*tulin[j]; - } + //Additional constants and variables const int g[4][4] = {{1,0,0,0},{0,-1,0,0},{0,0,-1,0},{0,0,0,-1}}; @@ -1056,7 +933,6 @@ const Target& target, bool assumeFreeNucleon) const // Calculate LmunuAnumu by iterating over mu and nu // In each iteration, add LmunuAnumu to sum if mu=nu, and add // LmunuAnumu + LnumuAmunu if mu != nu, since we start nu at mu - double axx=0.,azz=0.,a0z=0.,a00=0.,axy=0.; for(int mu=0;mu<4;mu++){ for(int nu=mu;nu<4;nu++){ imaginaryPart = 0; @@ -1077,7 +953,6 @@ const Target& target, bool assumeFreeNucleon) const } } //real(Lmunu) is symmetric, and imag(Lmunu) is antisymmetric - //std::complex num(g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu]+g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu],imaginaryPart); Lmunu = g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu]+g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu] + 1i*imaginaryPart; Lnumu = g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu]+g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu ]- 1i*imaginaryPart; } // End Lmunu calculation @@ -1088,13 +963,11 @@ const Target& target, bool assumeFreeNucleon) const (4.0-4.0*rulin[0][0]/M2-4.0*q[0]*tulin[0]/M2-q02*(4.0/q2+1.0/M2)) + 4.0*FA2*(2.0*rulin[0][0]+2.0*q[0]*tulin[0]+(q2/2.0-2.0*M2))- aux1*q02-16.0*F1V*xiF2V*(-q2+q02)*CN; - a00 = real(Amunu); // TESTING CODE sum += Lmunu*Amunu; }else if(mu == 0 && nu == 3){ Amunu = 16.0*F1V2*((2.0*rulin[0][3]+tulin[0]*dq)*CN+tulin[3]*q[0])+ -4.0*q2*xiF2V2*(2.0*rulin[0][3]/M2+(dq*tulin[0]+q[0]*tulin[3])/M2+dq*q[0]*(2.0/q2+0.5/M2))+ 4.0*FA2*((2.0*rulin[0][3]+dq*tulin[0])*CL+q[0]*tulin[3])-dq*q[0]*(aux1+16.0*F1V*xiF2V); - a0z= real(Amunu); // TESTING CODE Anumu = Amunu; sum += Lmunu*Anumu + Lnumu*Amunu; }else if(mu == 3 && nu == 3){ @@ -1102,14 +975,12 @@ const Target& target, bool assumeFreeNucleon) const 2.0*q2*xiF2V2*(-4.0-4.0*rulin[3][3]/M2-4.0*dq*tulin[3]/M2-dq2*(4.0/q2+1.0/M2))+ 4.0*FA2*(2.0*rulin[3][3]+2.0*dq*tulin[3]-(q2/2.0-2.0*CL*M2))- aux1*dq2-16.0*F1V*xiF2V*q02; - azz = real(Amunu); // TESTING CODE sum += Lmunu*Amunu; }else if(mu ==1 && nu == 1){ Amunu = 16.0*F1V2*(2.0*rulin[1][1]-q2/2.0)+ 2.0*q2*xiF2V2*(-4.0*CT-4.0*rulin[1][1]/M2) + 4.0*FA2*(2.0*rulin[1][1]-(q2/2.0-2.0*CT*M2))- 16.0*F1V*xiF2V*CT*q2; - axx = real(Amunu); // TESTING CODE sum += Lmunu*Amunu; }else if(mu == 2 && nu == 2){ // Ayy not explicitly listed in paper. This is included so rotating the @@ -1122,7 +993,6 @@ const Target& target, bool assumeFreeNucleon) const }else if(mu ==1 && nu == 2){ Amunu = sign*16.0*1i*FA*(xiF2V+F1V)*(-dq*tulin[0]*CT + q[0]*tulin[3]); Anumu = -Amunu; // Im(A) is antisymmetric - axy = imag(Amunu); // TESTING CODE sum += Lmunu*Anumu+Lnumu*Amunu; } // All other terms will be 0 because the initial nucleus is at rest and @@ -1131,38 +1001,6 @@ const Target& target, bool assumeFreeNucleon) const } // End loop over nu } // End loop over mu - // TESTING CODE - if(fCompareNievesTensors){ - // get tmu - double tmugev = leptonMom.E() - leptonMom.Mag(); - // Print Q2, form factors, and tensor elts - std::ofstream ffstream; - ffstream.open(fTensorsOutFile, std::ios_base::app); - if(q0 > 0){ - ffstream << -q2 << "\t" << q[0] << "\t" << dq - << "\t" << axx << "\t" << azz << "\t" << a0z - << "\t" << a00 << "\t" << axy << "\t" - << CT << "\t" << CL << "\t" << CN << "\t" - << tmugev << "\t" << imU << "\t" - << F1V << "\t" << xiF2V << "\t" - << FA << "\t" << Fp << "\t" - << tulin[0] << "\t"<< tulin[1] << "\t" - << tulin[2] << "\t"<< tulin[3] << "\t" - << rulin[0][0]<< "\t"<< rulin[0][1]<< "\t" - << rulin[0][2]<< "\t"<< rulin[0][3]<< "\t" - << rulin[1][0]<< "\t"<< rulin[1][1]<< "\t" - << rulin[1][2]<< "\t"<< rulin[1][3]<< "\t" - << rulin[2][0]<< "\t"<< rulin[2][1]<< "\t" - << rulin[2][2]<< "\t"<< rulin[2][3]<< "\t" - << rulin[3][0]<< "\t"<< rulin[3][1]<< "\t" - << rulin[3][2]<< "\t"<< rulin[3][3]<< "\t" - << fVc << "\t" << fCoulombFactor << "\t"; - ffstream << "\n"; - } - ffstream.close(); - } - // END TESTING CODE - // Since the real parts of A and L are both symmetric and the imaginary // parts are antisymmetric, the contraction should be real if ( imag(sum) > kASmallNum ) @@ -1244,125 +1082,6 @@ ROOT::Math::IBaseFunctionOneDim * return new utils::gsl::wrap::NievesQELSmithMonizIntegrand(alg, interaction, mu, nu); } //____________________________________________________________________________ - -//____________________________________________________________________________ -// -// NOTE: THE REMAINING IS TESTING CODE -// -// This method prints the tensor elements (as well as various inputs) for -// different kinematics. The tensor elements can then be compared to the -// output of Nieves' fortran code. -// -// The results of this code will only agree exactlly with Nieves' fortran -// if Dipole form factors are set (in UserPhysicsOptions). -// -void NievesQELCCPXSec::CompareNievesTensors(const Interaction* in) - const { - Interaction * interaction = new Interaction(*in); // copy in - - // Set input values here - double ein = 0.2; - double ctl = 0.5; - double rmaxfrac = 0.25; - - bool carbon = false; // true -> C12, false -> Pb208 - - if(fRPA) - fTensorsOutFile = "gen.RPA"; - else - fTensorsOutFile = "gen.noRPA"; - - // Calculate radius - bool klave; - double rp,ap,rn,an; - if(carbon){ - klave = true; - rp = 1.692; - ap = 1.082; - rn = 1.692; - an = 1.082; - }else{ - // Pb208 - klave = false; - rp = 6.624; - ap = 0.549; - rn = 6.890; - an = 0.549; - } - double rmax; - if(!klave) - rmax = TMath::Max(rp,rn) + 9.25*TMath::Max(ap,an); - else - rmax = TMath::Sqrt(20.0)*TMath::Max(rp,rn); - double r = rmax * rmaxfrac; - - // Relevant objects and parameters - //const Kinematics & kinematics = interaction -> Kine(); - const InitialState & init_state = interaction -> InitState(); - const Target & target = init_state.Tgt(); - - // Parameters required for LmunuAnumu - double M = target.HitNucMass(); - double ml = interaction->FSPrimLepton()->Mass(); - bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); - - // Iterate over lepton energy (which then affects q, which is passed to - // LmunuAnumu using in and out NucleonMom - double delta = (ein-0.025)/100.0; - for(int it=0;it<100;it++){ - double tmu = it*delta; - double eout = ml + tmu; - double pout = TMath::Sqrt(eout*eout-ml*ml); - - double pin = TMath::Sqrt(ein*ein); // Assume massless neutrinos - - double q0 = ein-eout; - double dq = TMath::Sqrt(pin*pin+pout*pout-2.0*ctl*pin*pout); - double q2 = q0*q0-dq*dq; - interaction->KinePtr()->SetQ2(-q2); - - // When this method is called, inNucleonMomOnShell is unused. - // I can thus provide the calculated values using a null vector for - // inNucleonMomOnShell. I also need to put qTildeP4 in the z direction, as - // Nieves does in his paper. - TLorentzVector qTildeP4(0, 0, dq, q0); - TLorentzVector inNucleonMomOnShell(0,0,0,0); - - // neutrinoMom and leptonMom only directly affect the leptonic tensor, which - // we are not calculating now. Use them to transfer q. - TLorentzVector neutrinoMom(0,0,pout+dq,eout+q0); - TLorentzVector leptonMom(0,0,pout,eout); - - if(fCoulomb){ // Use same steps as in XSec() - // Coulomb potential - double Vc = vcr(& target, r); - fVc = Vc; - - // Outgoing lepton energy and momentum including coulomb potential - int sign = is_neutrino ? 1 : -1; - double El = leptonMom.E(); - double ElLocal = El - sign*Vc; - if(ElLocal - ml <= 0.0){ - LOG("Nieves",pINFO) << "Event should be rejected. Coulomb effects " - << "push kinematics below threshold"; - return; - } - double plLocal = TMath::Sqrt(ElLocal*ElLocal-ml*ml); - - // Correction factor - double coulombFactor= plLocal*ElLocal/leptonMom.Vect().Mag()/El; - fCoulombFactor = coulombFactor; // Store and print - } - - // TODO: apply Coulomb correction to 3-momentum transfer dq - - fFormFactors.Calculate(interaction); - LmunuAnumu(neutrinoMom, inNucleonMomOnShell, leptonMom, qTildeP4, - M, is_neutrino, target, false); - } - return; -} // END TESTING CODE -//____________________________________________________________________________ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); @@ -1640,7 +1359,6 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac double EFf = TMath::Hypot(M, kFf); bool tgtIsNucleus = target.IsNucleus(); - int tgt_pdgc = target.Pdg(); int A = target.A(); int Z = target.Z(); int N = target.N(); @@ -1729,20 +1447,11 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac // This gives units of GeV^-1 double Fp = fFormFactors.Fp()/M; - - double dummy; - double CN(1), CT(1), CL(1), imU(0); - CNCTCLimUcalc(qTildeP4, M, r, is_neutrino, tgtIsNucleus, - tgt_pdgc, A, Z, N, CN, CT, CL, imU, - dummy, dummy, interaction->TestBit( kIAssumeFreeNucleon )); - - if ( imU >= 0 ) return 0; - - if ( !fRPA || interaction->TestBit( kIAssumeFreeNucleon ) ) + double CN(1), CT(1), CL(1); + if (fRPA) { - CN = 1.0; - CT = 1.0; - CL = 1.0; + CNCTCLimUcalc(qTildeP4, M, r, tgtIsNucleus, A, Z, N, + CN, CT, CL, interaction->TestBit(kIAssumeFreeNucleon) ); } // Calculate auxiliary parameters diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 0a2e3a9983..ac1c126bce 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -120,16 +120,14 @@ class NievesQELCCPXSec : public XSecAlgorithmI { // Calculates values of CN, CT, CL, and imU, and stores them in the provided // variables. If target is not a nucleus, then CN, CN, and CL are all 1.0. // r must be in units of fm. - void CNCTCLimUcalc(TLorentzVector qTildeP4, double M, double r, - bool is_neutrino, bool tgtIsNucleus, int tgt_pdgc, int A, int Z, int N, - double & CN, double & CT, double & CL, double & imU, - double & t0, double & r00, bool assumeFreeNucleon) const; + void CNCTCLimUcalc(TLorentzVector qTildeP4, double M, double r, + bool tgtIsNucleus, int A, int Z, int N, double & CN, double & CT, + double & CL, bool assumeFreeNucleon) const; //Equations to calculate the relativistic Lindhard function for Amunu double relLindhardIm(double q0gev, double dqgev, double kFngev, double kFpgev, - double M, bool isNeutrino, - double & t0, double & r00) const; + double M, bool isNeutrino) const; std::complex relLindhard(double q0gev, double dqgev, double kFgev, double M) const; double ruLinRelX(double q0, double qm, @@ -156,14 +154,6 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double & A00, double & Axx, double & Azz, double & A0z, double & Axy) const; - // NOTE: THE FOLLOWING CODE IS FOR TESTING PURPOSES ONLY - // Used to print tensor elements and various inputs for comparison to Nieves' - // fortran code - mutable bool fCompareNievesTensors; ///< print tensors - mutable TString fTensorsOutFile; ///< file to print tensors to - mutable double fVc,fCoulombFactor; - void CompareNievesTensors(const Interaction* i) const; - // END TESTING CODE }; } // genie namespace From c9c20d0614415375a89e954709f44a3c9ab6ae54 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 10 Feb 2025 01:58:56 +0300 Subject: [PATCH 35/78] samll change --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index a7136bc552..f5c8f48ab7 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -560,10 +560,13 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, { double M2 = TMath::Sq(M); double EF1,EF2; - if(isNeutrino){ + if(isNeutrino) + { EF1 = TMath::Sqrt(M2 + TMath::Sq(kFn)); //EFn EF2 = TMath::Sqrt(M2 + TMath::Sq(kFp)); //EFp - }else{ + } + else + { EF1 = TMath::Sqrt(M2 + TMath::Sq(kFp)); //EFp EF2 = TMath::Sqrt(M2 + TMath::Sq(kFn)); //EFn } From 18fb24f234c9327d6ec1e3f2f5dfb57f597bd687 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 10 Feb 2025 21:52:17 +0300 Subject: [PATCH 36/78] small optimization --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index f5c8f48ab7..1849a0c68f 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -506,6 +506,7 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, { if ( tgtIsNucleus && !assumeFreeNucleon ) { + double q0 = qTildeP4.E(); double dq = qTildeP4.Vect().Mag(); double dq2 = TMath::Sq(dq); double q2 = qTildeP4.Mag2(); @@ -524,19 +525,18 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double kF = TMath::Power(1.5*kPi2*rho, 1./3.)*fhbarc; - std::complex relLin(relLindhard(qTildeP4.E(), dq, kF, M)), udel(deltaLindhard(qTildeP4.E(), dq, rho, kF)); + std::complex relLin(relLindhard(q0, dq, kF, M)), udel(deltaLindhard(q0, dq, rho, kF)); std::complex relLinTot(relLin + udel); /* CRho = 2 DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2 mRho = 770 MeV, (0.770 GeV)^2 = 0.5929 GeV^2 g' = 0.63 */ - double Vt = 0.08*4*kPi/kPionMass2* - (2*TMath::Sq( (6.25 - 0.5929)/(6.25 - q2) )*dq2/(q2 - 0.5929) + 0.63); + double aux = 0.08*4*kPi/kPionMass2; + double Vt = aux*(2*TMath::Sq( (6.25 - 0.5929)/(6.25 - q2) )*dq2/(q2 - 0.5929) + 0.63); /* f^2/4/Pi = 0.08 DeltaSubPi = 1200 MeV, (1.2 GeV)^2 = 1.44 GeV^2 g' = 0.63 */ - double Vl = 0.08*4*kPi/kPionMass2* - (TMath::Sq( (1.44 - kPionMass2)/(1.44 - q2) )*dq2/(q2 - kPionMass2) + 0.63); + double Vl = aux*(TMath::Sq( (1.44 - kPionMass2)/(1.44 - q2) )*dq2/(q2 - kPionMass2) + 0.63); CN = 1/std::norm(1. - fPrime*relLin); CT = 1/std::norm(1. - relLinTot*Vt); From e26efad3d1fb4697bd44a3a2d78cae87ccb33847 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 11 Feb 2025 19:32:04 +0300 Subject: [PATCH 37/78] optimize delta Linhard --- .../XSection/NievesQELCCPXSec.cxx | 85 ++++++++----------- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 2 +- 2 files changed, 37 insertions(+), 50 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 1849a0c68f..b4a6d8ac0d 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -525,7 +525,7 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double kF = TMath::Power(1.5*kPi2*rho, 1./3.)*fhbarc; - std::complex relLin(relLindhard(q0, dq, kF, M)), udel(deltaLindhard(q0, dq, rho, kF)); + std::complex relLin(relLindhard(q0, dq, kF, M)), udel(deltaLindhard(q0, dq, rho*hbarc2*fhbarc, kF, M)); std::complex relLinTot(relLin + udel); /* CRho = 2 DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2 @@ -653,77 +653,64 @@ double NievesQELCCPXSec::ruLinRelX(double q0, double qm, E.Oset et al Phys. Rept. 188:79, 1990 formula A.4 - input variables: - q_zero [fm^-1] : Energy - q_mod [fm^-1] : Momentum - rho [fm^3] : Nuclear density - k_fermi[fm^-1] : Fermi momentum - - All variables are real*8 - - output variable: - delta_lind [fm^-2] - ATTENTION!!! - Only works properly for real q_zero, - if q_zero has an imaginary part calculates the L. function + Only works properly for real q0, + if q0 has an imaginary part calculates the L. function assuming Gamma= 0. Therefore this subroutine provides two different functions - depending on whether q_zero is real or not!!!!!!!!!!! + depending on whether q0 is real or not!!!!!!!!!!! */ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, - double rho, double kF) const + double rho, double kF, double M) const { - double q_zero = q0/fhbarc; - double q_mod = dq/fhbarc; - double k_fermi = kF/fhbarc; - //Divide by hbarc in order to use natural units (rho is already in the correct units) - - //m = 939/197.3, md = 1232/197.3, mpi = 139/197.3 - double m = 4.7592; - double md = 6.2433; - double mpi = 0.7045; - - double fdel_f2 = 4.5; - double wr = md - m; - double gamma = 0; + + double MD = 1.232; + double mpi = kPionMass; + + double fs2_f2 = 4.5; + double wr = MD - M; + double gamma = 0; double gammap = 0; - double q_zero2 = TMath::Sq(q_zero); - double q_mod2 = TMath::Sq(q_mod); - double k_fermi2 = TMath::Sq(k_fermi); + double q02 = q0*q0; + double dq2 = dq*dq; + double kF2 = kF*kF; - double m2 = TMath::Sq(m); - double m4 = TMath::Sq(m2); - double mpi2 = TMath::Sq(mpi); - double mpi4 = TMath::Sq(mpi2); + double M2 = M*M; + double M4 = M2*M2; + double mpi2 = mpi*mpi; + double mpi4 = mpi2*mpi2; - //For the current code q_zero is always real - //If q_zero can have an imaginary part then only the real part is used + //For the current code q0 is always real + //If q0 can have an imaginary part then only the real part is used //until z and zp are calculated - double aux1 = m2 + q_zero2 - q_mod2; - double aux2 = 2*q_zero*TMath::Sqrt(m2 + 3*k_fermi2/5); - double aux3 = TMath::Sq(m + mpi); + double aux1 = M2 + q02 - dq2; + double aux2 = 2*q0*TMath::Sqrt(M2 + 3*kF2/5); + double aux3 = TMath::Sq(M + mpi); double s = aux1 + aux2; double sp = aux1 - aux2; if(s > aux3) { double srot = TMath::Sqrt(s); - double qcm = TMath::Sqrt(TMath::Sq(s) + mpi4 + m4 - 2*(s*mpi2 + s*m2 + mpi2*m2))/2/srot; - gamma = fdel_f2*TMath::Power(qcm,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcm)))/mpi2/12/kPi/srot; + double qcm = TMath::Sqrt(s*s + mpi4 + M4 - 2*(s*mpi2 + s*M2 + mpi2*M2))/2/srot; + double qcm2 = qcm*qcm; + gamma = fs2_f2*qcm*qcm2*(M + TMath::Sqrt(M2 + qcm2))/mpi2/12/kPi/srot; } if(sp > aux3) { double srotp = TMath::Sqrt(sp); - double qcmp = TMath::Sqrt(TMath::Sq(sp) + mpi4 + m4 - 2*(sp*mpi2 + sp*m2 + mpi2*m2))/2/srotp; - gammap = fdel_f2*TMath::Power(qcmp,3)*(m + TMath::Sqrt(m2 + TMath::Sq(qcmp)))/mpi2/12/kPi/srotp; + double qcmp = TMath::Sqrt(sp*sp + mpi4 + M4 - 2*(sp*mpi2 + sp*M2 + mpi2*M2))/2/srotp; + double qcmp2 = qcmp*qcmp; + gammap = fs2_f2*qcmp*qcmp2*(M + TMath::Sqrt(M2 + qcmp2))/mpi2/12/kPi/srotp; } - std::complex z (md/q_mod/k_fermi*( q_zero - q_mod2/2./md - wr + 1i*gamma/2.)); - std::complex zp(md/q_mod/k_fermi*(-q_zero - q_mod2/2./md - wr + 1i*gammap/2.)); + std::complex z ( q0 - dq2/2./MD - wr, gamma/2. ); + std::complex zp(-q0 - dq2/2./MD - wr, gammap/2.); + z *= MD/dq/kF; + zp *= MD/dq/kF; std::complex pzeta(0, 0); std::complex z2(z*z); @@ -758,7 +745,7 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, } //Multiply by hbarc^2 to give answer in units of GeV^2 - return 2.*rho*md*(pzeta + pzetap)*fdel_f2*TMath::Sq(fhbarc)/q_mod/k_fermi/3.; + return 2.*rho*MD*(pzeta + pzetap)*fs2_f2/dq/kF/3.; } //____________________________________________________________________________ @@ -822,7 +809,7 @@ double NievesQELCCPXSec::MaximalRadius(const Target * target) const // TODO: This solution is fragile. If the formula used by VertexGenerator // changes, then this one will need to change too. Switch to using // a common function to get Rmax for both. - Rmax = 3. * fR0 * std::pow(A, 1./3.); + Rmax = fR0 * std::pow(A, 1./3.); } else { diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index ac1c126bce..24d841f6f4 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -133,7 +133,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double ruLinRelX(double q0, double qm, double kf, double m) const; std::complex deltaLindhard(double q0gev, double dqgev, - double rho, double kFgev) const; + double rho, double kFgev, double Mgev) const; // Potential for coulomb correction double vcr(const Target * target, double r) const; From 20a381cdcc6c24e4f07bb0e8da861187cb39f86f Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 11 Feb 2025 19:49:18 +0300 Subject: [PATCH 38/78] small changes --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index b4a6d8ac0d..183ebeafb1 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -668,7 +668,7 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, double mpi = kPionMass; double fs2_f2 = 4.5; - double wr = MD - M; + double wR = MD - M; double gamma = 0; double gammap = 0; @@ -707,8 +707,8 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, gammap = fs2_f2*qcmp*qcmp2*(M + TMath::Sqrt(M2 + qcmp2))/mpi2/12/kPi/srotp; } - std::complex z ( q0 - dq2/2./MD - wr, gamma/2. ); - std::complex zp(-q0 - dq2/2./MD - wr, gammap/2.); + std::complex z ( q0 - dq2/2./MD - wR, gamma/2. ); + std::complex zp(-q0 - dq2/2./MD - wR, gammap/2.); z *= MD/dq/kF; zp *= MD/dq/kF; From 024def987d80b43878819c699e87fb4bf2ad1dba Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Wed, 12 Feb 2025 04:43:06 +0300 Subject: [PATCH 39/78] add more optimizations --- .../XSection/NievesQELCCPXSec.cxx | 70 +++++++------------ .../QuasiElastic/XSection/NievesQELCCPXSec.h | 12 ++-- 2 files changed, 33 insertions(+), 49 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 183ebeafb1..5128c43c08 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -589,61 +589,46 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, Eq. 61 Im. part: Juan. - - INPUT: Real*8 - q0:Energy [fm] - qm: modulus 3mom [fm] - kf: Fermi mom [fm] - - OUTPUT: Complex*16 [fm] - - USES: ruLinRelX, relLindhardIm */ -//Takes inputs in GeV (with imU in GeV^2), and gives output in GeV^2 -std::complex NievesQELCCPXSec::relLindhard(double q0gev, - double dqgev, double kFgev, double M) const +//Takes inputs in GeV and gives output in GeV^2 +std::complex NievesQELCCPXSec::relLindhard(double q0, + double dq, double kF, double M) const { - double q0 = q0gev/fhbarc; - double qm = dqgev/fhbarc; - double kf = kFgev/fhbarc; - double m = M/fhbarc; - - double relLindIm = relLindhardIm(q0gev, dqgev, kFgev, kFgev, M, true); - //Units of GeV^2 - std::complex relLind(TMath::Sq(fhbarc)*(ruLinRelX(q0,qm,kf,m) + ruLinRelX(-q0,qm,kf,m)), 2*relLindIm); + double relLindIm = relLindhardIm(q0, dq, kF, kF, M, true); + std::complex relLind(ruLinRelX(q0,dq,kF,M) + ruLinRelX(-q0,dq,kF,M), 2*relLindIm); return relLind; } //____________________________________________________________________________ //Inputs assumed to be in natural units -double NievesQELCCPXSec::ruLinRelX(double q0, double qm, - double kf, double m) const +double NievesQELCCPXSec::ruLinRelX(double q0, double dq, + double kF, double M) const { - double q02 = TMath::Sq(q0); - double qm2 = TMath::Sq(qm); - double kf2 = TMath::Sq(kf); - double m2 = TMath::Sq(m); - double m4 = TMath::Sq(m2); - - double ef = TMath::Sqrt(m2 + kf2); - double q2 = q02 - qm2; - double q4 = TMath::Sq(q2); - double ds = TMath::Sqrt(1 - 4*m2/q2); - double L1 = TMath::Log((kf + ef)/m); + double q02 = q0*q0; + double dq2 = dq*dq; + double kF2 = kF*kF; + double M2 = M*M; + double M4 = M2*M2; + + double EF = TMath::Sqrt(M2 + kF2); + double q2 = q02 - dq2; + double q4 = q2*q2; + double ds = TMath::Sqrt(1 - 4*M2/q2); + double L1 = TMath::Log((kF + EF)/M); - double aux1 = TMath::Sq(ef + q0); - double aux2 = (m2 + TMath::Sq(kf - qm))/aux1; - double aux3 = (m2 + TMath::Sq(kf + qm))/aux1; + double aux1 = TMath::Sq(EF + q0); + double aux2 = (M2 + TMath::Sq(kF - dq))/aux1; + double aux3 = (M2 + TMath::Sq(kF + dq))/aux1; double L2 = TMath::Log(TMath::Abs((1 - aux2)/(1 - aux3))); - double aux5 = TMath::Sq(2*kf + q0*ds)/qm2; - double aux6 = TMath::Sq(2*kf - q0*ds)/qm2; - double aux7 = 4*m4*qm2/q4; - double aux8 = TMath::Sq(kf - ef*ds)/aux7; - double aux9 = TMath::Sq(kf + ef*ds)/aux7; + double aux5 = TMath::Sq(2*kF + q0*ds)/dq2; + double aux6 = TMath::Sq(2*kF - q0*ds)/dq2; + double aux7 = 4*M4*dq2/q4; + double aux8 = TMath::Sq(kF - EF*ds)/aux7; + double aux9 = TMath::Sq(kF + EF*ds)/aux7; double L3 = TMath::Log(TMath::Abs((aux5 - 1)/(aux6 - 1)* (aux8 - 1)/(aux9 - 1))); - return m2*(-L1 + L2*(2*ef + q0)/2/qm - L3*ds/4)/kPi2; + return M2*(-L1 + L2*(2*EF + q0)/2/dq - L3*ds/4)/kPi2; } //____________________________________________________________________________ //Following obtained from fortran code by J Nieves, which contained the following comment: @@ -744,7 +729,6 @@ std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, pzetap = zp + (1. - zp2)*log((zp + 1.)/(zp - 1.))/2.; } - //Multiply by hbarc^2 to give answer in units of GeV^2 return 2.*rho*MD*(pzeta + pzetap)*fs2_f2/dq/kF/3.; } diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 24d841f6f4..876f8cda6d 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -125,15 +125,15 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double & CL, bool assumeFreeNucleon) const; //Equations to calculate the relativistic Lindhard function for Amunu - double relLindhardIm(double q0gev, double dqgev, - double kFngev, double kFpgev, + double relLindhardIm(double q0, double dq, + double kFn, double kFp, double M, bool isNeutrino) const; - std::complex relLindhard(double q0gev, double dqgev, - double kFgev, double M) const; + std::complex relLindhard(double q0, double dq, + double kF, double M) const; double ruLinRelX(double q0, double qm, double kf, double m) const; - std::complex deltaLindhard(double q0gev, double dqgev, - double rho, double kFgev, double Mgev) const; + std::complex deltaLindhard(double q0, double dq, + double rho, double kF, double M) const; // Potential for coulomb correction double vcr(const Target * target, double r) const; From 0882da8823aa02c1c1e9188b2f1f078818eba105 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 13 Feb 2025 00:20:23 +0300 Subject: [PATCH 40/78] small optimizations --- src/Physics/NuclearState/NuclearUtils.cxx | 12 +++++++----- .../QuasiElastic/XSection/NievesQELCCPXSec.cxx | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Physics/NuclearState/NuclearUtils.cxx b/src/Physics/NuclearState/NuclearUtils.cxx index 7f6c985ccd..37ddff5be6 100644 --- a/src/Physics/NuclearState/NuclearUtils.cxx +++ b/src/Physics/NuclearState/NuclearUtils.cxx @@ -453,9 +453,10 @@ double genie::utils::nuclear::DensityGaus( ring = TMath::Min(ring, 0.3*a); double aeval = a + ring; - double norm = 1./((5.568 + alf*8.353)*TMath::Power(a,3.)); //0.0132; - double b = TMath::Power(r/aeval, 2.); - double dens = norm * (1. + alf*b) * TMath::Exp(-b); + double a3 = a*a*a; + double norm = 1/(5.568 + alf*8.353)/a3; //0.0132; + double b = TMath::Sq(r/aeval); + double dens = norm*(1 + alf*b)*TMath::Exp(-b); LOG("Nuclear", pINFO) << "r = " << r << ", norm = " << norm << ", dens = " << dens @@ -480,8 +481,9 @@ double genie::utils::nuclear::DensityWoodsSaxon( ring = TMath::Min(ring, 0.75*c); double ceval = c + ring; - double norm = (3./(4.*kPi*TMath::Power(c,3)))*1./(1.+TMath::Power((kPi*z/c),2)); - double dens = norm / (1 + TMath::Exp((r-ceval)/z)); + double c3 = c*c*c; + double norm = 3/4./kPi/c3/(1 + TMath::Sq(kPi*z/c)); + double dens = norm/(1 + TMath::Exp((r - ceval)/z)); LOG("Nuclear", pINFO) << "r = " << r << ", norm = " << norm diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 5128c43c08..4644eb44cd 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -793,7 +793,7 @@ double NievesQELCCPXSec::MaximalRadius(const Target * target) const // TODO: This solution is fragile. If the formula used by VertexGenerator // changes, then this one will need to change too. Switch to using // a common function to get Rmax for both. - Rmax = fR0 * std::pow(A, 1./3.); + Rmax = 3*fR0*std::pow(A, 1./3); } else { From c48b7c01e3680cf94f9320d5fb6f0f349452f8c9 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 20 Feb 2025 18:38:28 +0300 Subject: [PATCH 41/78] fix config --- config/NievesQELCCPXSec.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/config/NievesQELCCPXSec.xml b/config/NievesQELCCPXSec.xml index 955e3fc0ba..9ce4990cea 100644 --- a/config/NievesQELCCPXSec.xml +++ b/config/NievesQELCCPXSec.xml @@ -46,7 +46,6 @@ RmaxMode string Yes Method to use to comput true true - false genie::PauliBlocker/Default true From 4361ded41d07995b9e3c9241e90411fd87772072 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sat, 15 Mar 2025 17:21:38 +0300 Subject: [PATCH 42/78] fix addressed to Roberts comments --- src/Framework/GHEP/GHepParticle.h | 2 +- src/Framework/GHEP/GHepRecord.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Framework/GHEP/GHepParticle.h b/src/Framework/GHEP/GHepParticle.h index f6576bdccc..1c0686db37 100644 --- a/src/Framework/GHEP/GHepParticle.h +++ b/src/Framework/GHEP/GHepParticle.h @@ -119,7 +119,7 @@ public : double PolzPolarAngle (void) const { return fPolarization.Mag()>0?fPolarization.Theta():0; } double PolzAzimuthAngle (void) const { return fPolarization.Mag()>0?fPolarization.Phi():0; } bool PolzIsSet (void) const { return fPolarization.Mag()>0;} - const TVector3 & GetPolarization (void) const {return fPolarization;} + void GetPolarization (TVector3 & polz) const {polz = fPolarization;} // Set pdg code and status codes void SetPdgCode (int c); diff --git a/src/Framework/GHEP/GHepRecord.cxx b/src/Framework/GHEP/GHepRecord.cxx index 5b9e3cfdbe..cef32032df 100644 --- a/src/Framework/GHEP/GHepRecord.cxx +++ b/src/Framework/GHEP/GHepRecord.cxx @@ -1048,7 +1048,7 @@ void GHepRecord::Print(ostream & stream) const << p->P4()->M() << " "; if (p->PolzIsSet()) { - polarization = p->GetPolarization(); + p->GetPolarization(polarization); stream << "P = (" << polarization.x() << "," << polarization.y() << "," << polarization.z() << ")"; } From a2b3308a0797c60ac20217d28586d8b33305ac9b Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Wed, 19 Mar 2025 15:40:00 +0300 Subject: [PATCH 43/78] add new Lindhardt functions as an option; ansatz for RPA with lepton polarization with magnitude greater than 1 --- config/NievesQELCCPXSec.xml | 26 +- .../XSection/NievesQELCCPXSec.cxx | 341 ++++++++++-------- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 27 +- 3 files changed, 229 insertions(+), 165 deletions(-) diff --git a/config/NievesQELCCPXSec.xml b/config/NievesQELCCPXSec.xml index 9ce4990cea..3a465a0e15 100644 --- a/config/NievesQELCCPXSec.xml +++ b/config/NievesQELCCPXSec.xml @@ -6,18 +6,18 @@ Configuration for the Nieves QEL CCP xsec algorithm. Configurable Parameters: -..................................................................................................... -Name Type Optional Comment Default -..................................................................................................... -FormFactorsAlg alg No QEL form factors algorithm -XSec-Integrator alg No -CabibboAngle double No Cabibbo angle CommonParam[CKM] -RPA bool Yes Turn RPA effects on or off true -Coulomb bool Yes Turn coulomb effects on or off true -QEL-CC-XSecScale double Yes Scaling factor for CC GPL value -QEL-NC-XSecScale double Yes Scaling factor for NC GPL value -PreciseLeptonPol bool Yes Do precise calculation of No - lepton polarization +................................................................................................................... +Name Type Optional Comment Default +................................................................................................................... +FormFactorsAlg alg No QEL form factors algorithm +XSec-Integrator alg No +CabibboAngle double No Cabibbo angle CommonParam[CKM] +RPA bool Yes Turn RPA effects on or off true +Coulomb bool Yes Turn coulomb effects on or off true +QEL-CC-XSecScale double Yes Scaling factor for CC GPL value +QEL-NC-XSecScale double Yes Scaling factor for NC GPL value +PreciseLeptonPol bool Yes Do precise calculation of lepton polarization No +LindhardFunction string Yes Which Lindhard functions to use? OriginalByNieves ..................................................................................................... Parameters needed when Integrating with this model to generate splines: @@ -44,7 +44,7 @@ RmaxMode string Yes Method to use to comput UseNuclearModel 10.0 - true + true true genie::PauliBlocker/Default diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 4644eb44cd..a6daf142da 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -446,6 +446,8 @@ void NievesQELCCPXSec::LoadConfig(void) std::string temp_mode; GetParamDef( "RmaxMode", temp_mode, std::string("VertexGenerator") ) ; + + GetParamDef( "LindhardFunction", fLindhardFunction, std::string("OriginalByNieves") ) ; // Translate the string setting the Rmax mode to the appropriate // enum value, or complain if one couldn't be found @@ -525,22 +527,19 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double kF = TMath::Power(1.5*kPi2*rho, 1./3.)*fhbarc; - std::complex relLin(relLindhard(q0, dq, kF, M)), udel(deltaLindhard(q0, dq, rho*hbarc2*fhbarc, kF, M)); - std::complex relLinTot(relLin + udel); - /* CRho = 2 - DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2 - mRho = 770 MeV, (0.770 GeV)^2 = 0.5929 GeV^2 - g' = 0.63 */ + std::complex Unuc( LindhardNuclear(q0, dq, kF, M) ); + std::complex Udel( LindhardDelta(q0, dq, kF, M, rho) ); + std::complex Utot = Unuc + Udel; + +// CRho = 2, DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2, mRho = 770 MeV, (0.770 GeV)^2 = 0.5929 GeV^2, g' = 0.63 double aux = 0.08*4*kPi/kPionMass2; double Vt = aux*(2*TMath::Sq( (6.25 - 0.5929)/(6.25 - q2) )*dq2/(q2 - 0.5929) + 0.63); - /* f^2/4/Pi = 0.08 - DeltaSubPi = 1200 MeV, (1.2 GeV)^2 = 1.44 GeV^2 - g' = 0.63 */ +// f^2/4/Pi = 0.08, DeltaSubPi = 1200 MeV, (1.2 GeV)^2 = 1.44 GeV^2, g' = 0.63 double Vl = aux*(TMath::Sq( (1.44 - kPionMass2)/(1.44 - q2) )*dq2/(q2 - kPionMass2) + 0.63); - CN = 1/std::norm(1. - fPrime*relLin); - CT = 1/std::norm(1. - relLinTot*Vt); - CL = 1/std::norm(1. - relLinTot*Vl); + CN = 1/std::norm(1. - c0*fPrime*Unuc); + CT = 1/std::norm(1. - Vt*Utot); + CL = 1/std::norm(1. - Vl*Utot); } else { @@ -551,12 +550,10 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, } } //____________________________________________________________________________ -// Gives the imaginary part of the relativistic lindhard function in GeV^2 -// and sets the values of t0 and r00 +// Gives the imaginary part of the relativistic lindhard function in GeV^2, Ref.1, Eq.B2 double NievesQELCCPXSec::relLindhardIm(double q0, double dq, - double kFn, double kFp, - double M, - bool isNeutrino) const + double kFn, double kFp, + double M, bool isNeutrino) const { double M2 = TMath::Sq(M); double EF1,EF2; @@ -580,26 +577,7 @@ double NievesQELCCPXSec::relLindhardIm(double q0, double dq, return -M2/2/kPi/dq*(EF1 - epsRP); } //____________________________________________________________________________ -//Following obtained from fortran code by J Nieves, which contained the following comment: -/* - NUCLEON relativistic Lindhard Function - Same normalization as ULIN - Real part - taken from Eur.Phys.J.A25:299-318,2005 (Barbaro et al) - Eq. 61 - - Im. part: Juan. - */ -//Takes inputs in GeV and gives output in GeV^2 -std::complex NievesQELCCPXSec::relLindhard(double q0, - double dq, double kF, double M) const -{ - double relLindIm = relLindhardIm(q0, dq, kF, kF, M, true); - std::complex relLind(ruLinRelX(q0,dq,kF,M) + ruLinRelX(-q0,dq,kF,M), 2*relLindIm); - return relLind; -} -//____________________________________________________________________________ -//Inputs assumed to be in natural units +//Inputs assumed to be in natural units, Ref.2, Eq.61 double NievesQELCCPXSec::ruLinRelX(double q0, double dq, double kF, double M) const { @@ -630,108 +608,193 @@ double NievesQELCCPXSec::ruLinRelX(double q0, double dq, return M2*(-L1 + L2*(2*EF + q0)/2/dq - L3*ds/4)/kPi2; } +//____________________________________________________________________________ +//Takes inputs in GeV and gives output in GeV^2 +std::complex NievesQELCCPXSec::LindhardNuclear(double q0, double dq, double kF, double M) const +{ + if (fLindhardFunction == "CJP46") + { + // Ref.4, Eqs.27-29 + double v = q0*M/kF/kF; + double q = dq/kF; + double q2 = q*q; + double auxm = v/q - q/2; + double auxp = v/q + q/2; + double auxm2 = auxm*auxm; + double auxp2 = auxp*auxp; + double ReUnuc = M*kF/kPi2*(-1 + ( (1 - auxm2)*TMath::Log( TMath::Abs( (auxm + 1)/(auxm - 1) ) ) - + (1 - auxp2)*TMath::Log( TMath::Abs( (auxp + 1)/(auxp - 1) ) ) )/2/q); + + double uplim = q + q2/2; + double lowlim = q - q2/2; + double ImUnuc = 0; + if ((q > 2 && uplim >= v && v >= -lowlim ) || (q < 2 && uplim >= v && v >= lowlim) ) + ImUnuc = -M*kF*(1 - auxm2 )/2/kPi/q; + else if (q < 2 && 0 <= v && v <= lowlim) + ImUnuc = -M*kF*v/kPi/q; + + return std::complex(ReUnuc, ImUnuc); + } + + //Following obtained from fortran code by J Nieves, which contained the following comment: + // NUCLEON relativistic Lindhard Function + // Same normalization as ULIN + // Real part + // taken from Eur.Phys.J.A25:299-318,2005 (Barbaro et al) + // Eq. 61 + // Im. part: Juan. + double relLindIm = relLindhardIm(q0, dq, kF, kF, M, true); + std::complex relLind(ruLinRelX(q0,dq,kF,M) + ruLinRelX(-q0,dq,kF,M), 2*relLindIm); + return relLind; +} //____________________________________________________________________________ -//Following obtained from fortran code by J Nieves, which contained the following comment: -/* - complex Lindhard function for symmetric nuclear matter: - from Appendix of - E.Oset et al Phys. Rept. 188:79, 1990 - formula A.4 - - ATTENTION!!! - Only works properly for real q0, - if q0 has an imaginary part calculates the L. function - assuming Gamma= 0. - Therefore this subroutine provides two different functions - depending on whether q0 is real or not!!!!!!!!!!! -*/ -std::complex NievesQELCCPXSec::deltaLindhard(double q0, double dq, - double rho, double kF, double M) const +std::complex NievesQELCCPXSec::LindhardDelta(double q0, double dq, double kF, double M, double rho) const { - - double MD = 1.232; - double mpi = kPionMass; - - double fs2_f2 = 4.5; - double wR = MD - M; - double gamma = 0; - double gammap = 0; - - double q02 = q0*q0; - double dq2 = dq*dq; - double kF2 = kF*kF; - - double M2 = M*M; - double M4 = M2*M2; - double mpi2 = mpi*mpi; - double mpi4 = mpi2*mpi2; - - - //For the current code q0 is always real - //If q0 can have an imaginary part then only the real part is used - //until z and zp are calculated - double aux1 = M2 + q02 - dq2; - double aux2 = 2*q0*TMath::Sqrt(M2 + 3*kF2/5); - double aux3 = TMath::Sq(M + mpi); - double s = aux1 + aux2; - double sp = aux1 - aux2; - - if(s > aux3) - { - double srot = TMath::Sqrt(s); - double qcm = TMath::Sqrt(s*s + mpi4 + M4 - 2*(s*mpi2 + s*M2 + mpi2*M2))/2/srot; - double qcm2 = qcm*qcm; - gamma = fs2_f2*qcm*qcm2*(M + TMath::Sqrt(M2 + qcm2))/mpi2/12/kPi/srot; - } - - if(sp > aux3) - { - double srotp = TMath::Sqrt(sp); - double qcmp = TMath::Sqrt(sp*sp + mpi4 + M4 - 2*(sp*mpi2 + sp*M2 + mpi2*M2))/2/srotp; - double qcmp2 = qcmp*qcmp; - gammap = fs2_f2*qcmp*qcmp2*(M + TMath::Sqrt(M2 + qcmp2))/mpi2/12/kPi/srotp; - } - - std::complex z ( q0 - dq2/2./MD - wR, gamma/2. ); - std::complex zp(-q0 - dq2/2./MD - wR, gammap/2.); - z *= MD/dq/kF; - zp *= MD/dq/kF; - - std::complex pzeta(0, 0); - std::complex z2(z*z); - double abs_z = abs(z); - if(abs_z > 50) - { - pzeta = 2.*(1. + 1./5./z2)/3./z; - } - else if(abs_z < 1e-2) - { - pzeta = 2.*z*(1. - z2/3.) - 1i*kPi*(1. - z2)/2.; - } - else - { - pzeta = z + (1. - z2)*log((z + 1.)/(z - 1.))/2.; - } - - std::complex pzetap(0,0); - std::complex zp2(zp*zp); - double abs_zp = abs(zp); - if(abs_zp > 50) - { - pzetap = 2.*(1. + 1./5./zp2)/3./zp; - } - else if(abs_zp < 1e-2) - { - pzetap = 2.*zp*(1. - zp2/3.) - 1i*kPi*(1. - zp2)/2.; - } - else - { - pzetap = zp + (1. - zp2)*log((zp + 1.)/(zp - 1.))/2.; - } + double MD = 1.232; + double mpi = kPionMass; + + double fs2_f2 = 4.5; + double wR = MD - M; + double gamma = 0; + double gammap = 0; + + double q02 = q0*q0; + double dq2 = dq*dq; + double kF2 = kF*kF; + + double M2 = M*M; + double M4 = M2*M2; + double mpi2 = mpi*mpi; + double mpi4 = mpi2*mpi2; + //For the current code q0 is always real + //If q0 can have an imaginary part then only the real part is used + double aux1 = M2 + q02 - dq2; + double aux2 = 2*q0*TMath::Sqrt(M2 + 3*kF2/5); + double aux3 = TMath::Sq(M + mpi); + double s = aux1 + aux2; + double sp = aux1 - aux2; + + if (fLindhardFunction == "CJP46") + { + // Ref.4, Eq.30-31 + const double fs2 = 4*kPi*0.36; + if(s > aux3) + { + double srot = TMath::Sqrt(s); + double qcm = TMath::Sqrt(TMath::Sq(s) + mpi4 + M4 - 2*(s*mpi2 + s*M2 + mpi2*M2))/2/srot; + double qcm3 = qcm*qcm*qcm; + gamma = fs2*M*qcm3/mpi2/12/kPi/srot; + } + + if(sp > aux3) + { + double srotp = TMath::Sqrt(sp); + double qcmp = TMath::Sqrt(TMath::Sq(sp) + mpi4 + M4 - 2*(sp*mpi2 + sp*M2 + mpi2*M2))/2/srotp; + double qcmp3 = qcmp*qcmp*qcmp; + gammap = fs2*M*qcmp3/mpi2/12/kPi/srotp; + } + + double b = dq/MD; + double b3 = b*b*b; + std::complex a ( q0 - dq2/2/MD - wR, gamma ); + std::complex ap(-q0 - dq2/2/MD - wR, gammap); + a /= kF; + ap /= kF; + + std::complex a_plus_b = a + b; + std::complex a_minus_b = a - b; + std::complex ap_plus_b = ap + b; + std::complex ap_minus_b = ap - b; + + std::complex L, Lp; + + if (gamma <= 0) + L = log(abs(a_plus_b/a_minus_b)); + else + L = log(a_plus_b/a_minus_b); + + if (gammap <= 0) + Lp = log(abs(ap_plus_b/ap_minus_b)); + else + Lp = log(ap_plus_b/ap_minus_b); + + double factor = 4*kF2*fs2_f2/9/kPi2; + return factor*(b*(a + ap) - (a_plus_b*a_minus_b*L + ap_plus_b*ap_minus_b*Lp)/2.)/b3; + } + + // Following obtained from fortran code by J Nieves, which contained the following comment: + // complex Lindhard function for symmetric nuclear matter: + // from Appendix of + // E.Oset et al Phys. Rept. 188:79, 1990 + // formula A.4 + // + // ATTENTION!!! + // Only works properly for real q0, + // if q0 has an imaginary part calculates the L. function + // assuming Gamma= 0. + // Therefore this subroutine provides two different functions + // depending on whether q0 is real or not!!!!!!!!!!! + // For the current code q0 is always real + // If q0 can have an imaginary part then only the real part is used + // until z and zp are calculated + + // Ref.3, Eq. A4 + if(s > aux3) + { + double srot = TMath::Sqrt(s); + double qcm = TMath::Sqrt(s*s + mpi4 + M4 - 2*(s*mpi2 + s*M2 + mpi2*M2))/2/srot; + double qcm2 = qcm*qcm; + gamma = fs2_f2*qcm*qcm2*(M + TMath::Sqrt(M2 + qcm2))/mpi2/12/kPi/srot; + } + + if(sp > aux3) + { + double srotp = TMath::Sqrt(sp); + double qcmp = TMath::Sqrt(sp*sp + mpi4 + M4 - 2*(sp*mpi2 + sp*M2 + mpi2*M2))/2/srotp; + double qcmp2 = qcmp*qcmp; + gammap = fs2_f2*qcmp*qcmp2*(M + TMath::Sqrt(M2 + qcmp2))/mpi2/12/kPi/srotp; + } + + std::complex z ( q0 - dq2/2./MD - wR, gamma/2. ); + std::complex zp(-q0 - dq2/2./MD - wR, gammap/2.); + z *= MD/dq/kF; + zp *= MD/dq/kF; + + std::complex pzeta(0, 0); + std::complex z2(z*z); + double abs_z = abs(z); + if(abs_z > 50) + { + pzeta = 2.*(1. + 1./5./z2)/3./z; + } + else if(abs_z < 1e-2) + { + pzeta = 2.*z*(1. - z2/3.) - 1i*kPi*(1. - z2)/2.; + } + else + { + pzeta = z + (1. - z2)*log((z + 1.)/(z - 1.))/2.; + } + + std::complex pzetap(0,0); + std::complex zp2(zp*zp); + double abs_zp = abs(zp); + if(abs_zp > 50) + { + pzetap = 2.*(1. + 1./5./zp2)/3./zp; + } + else if(abs_zp < 1e-2) + { + pzetap = 2.*zp*(1. - zp2/3.) - 1i*kPi*(1. - zp2)/2.; + } + else + { + pzetap = zp + (1. - zp2)*log((zp + 1.)/(zp - 1.))/2.; + } + + return 2.*rho*MD*(pzeta + pzetap)*fs2_f2/dq/kF/3.; - return 2.*rho*MD*(pzeta + pzetap)*fs2_f2/dq/kF/3.; } - //____________________________________________________________________________ // Gives coulomb potential in units of GeV double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const @@ -1132,12 +1195,8 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i is_neutrino, M, T1,T2,T3,T4,T5,0); - - -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// std::cout << fFinalLeptonPolarization.Mag() << "\n"; -// std::cout << "NV@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - + if (fFinalLeptonPolarization.Mag2()>1) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + return fFinalLeptonPolarization; } diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 876f8cda6d..05bfb158dd 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -7,13 +7,19 @@ with RPA corrections Is a concrete implementation of the XSecAlgorithmI interface. \n -\ref 1. Physical Review C 70, 055503 (2004) +\ref 1. PRC70(2004)055503 + 2. EPJA25(2005)299-318 + 3. Phys.Rept.188(1990)79 + 4. CJP46(1996)0673-0720 \author Joe Johnston, University of Pittsburgh Steven Dytman, University of Pittsburgh + Igor Kakorin, JINR \created April 2016 +\updated March 2025 + \cpright Copyright (c) 2003-2023, The GENIE Collaboration For the full text of the license visit http://copyright.genie-mc.org */ @@ -89,6 +95,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { bool fLFG; const FermiMomentumTable * fKFTable; string fKFTableName; + string fLindhardFunction; /// Enum specifying the method to use when calculating the binding energy of /// the initial hit nucleon during spline generation @@ -124,16 +131,14 @@ class NievesQELCCPXSec : public XSecAlgorithmI { bool tgtIsNucleus, int A, int Z, int N, double & CN, double & CT, double & CL, bool assumeFreeNucleon) const; - //Equations to calculate the relativistic Lindhard function for Amunu - double relLindhardIm(double q0, double dq, - double kFn, double kFp, - double M, bool isNeutrino) const; - std::complex relLindhard(double q0, double dq, - double kF, double M) const; - double ruLinRelX(double q0, double qm, - double kf, double m) const; - std::complex deltaLindhard(double q0, double dq, - double rho, double kF, double M) const; + //Relativistic Lindhard function as is in Fortran code provided by j.Nieves + // Ref.1, Eq.B2 + double relLindhardIm(double q0, double dq, double kFn, double kFp, double M, bool isNeutrino) const; + // Ref.2, Eq.61 + double ruLinRelX(double q0, double qm, double kf, double m) const; + + std::complex LindhardNuclear(double q0, double dq, double kF, double M) const; + std::complex LindhardDelta (double q0, double dq, double kF, double M, double rho) const; // Potential for coulomb correction double vcr(const Target * target, double r) const; From 6fdf2d18e9539b7c6bbed886b89bd1c4c0625837 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Fri, 21 Mar 2025 16:04:14 +0300 Subject: [PATCH 44/78] fix bug --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index a6daf142da..a0bbca6477 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -523,12 +523,12 @@ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, double rho = rhop + rhon; double rho0 = A*nuclear::Density(0,A); - double fPrime = (0.33*rho/rho0 + 0.45*(1 - rho/rho0))*c0; + double fPrime = (0.33*rho/rho0 + 0.45*(1 - rho/rho0)); double kF = TMath::Power(1.5*kPi2*rho, 1./3.)*fhbarc; std::complex Unuc( LindhardNuclear(q0, dq, kF, M) ); - std::complex Udel( LindhardDelta(q0, dq, kF, M, rho) ); + std::complex Udel( LindhardDelta(q0, dq, kF, M, rho*hbarc2*fhbarc) ); std::complex Utot = Unuc + Udel; // CRho = 2, DeltaRho = 2500 MeV, (2.5 GeV)^2 = 6.25 GeV^2, mRho = 770 MeV, (0.770 GeV)^2 = 0.5929 GeV^2, g' = 0.63 From 36f108da18f62f053d252892f0d9975eb08c4bfa Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 24 Mar 2025 23:05:19 +0300 Subject: [PATCH 45/78] everything compiled --- config/NievesQELCCPXSec.xml | 5 +- config/NievesQELCCXSec.xml | 39 ++ config/master_config.xml | 1 + src/Physics/Common/PrimaryLeptonUtils.cxx | 2 +- src/Physics/QuasiElastic/XSection/LinkDef.h | 2 + .../XSection/NievesQELCCPXSec.cxx | 420 ++++++------------ .../QuasiElastic/XSection/NievesQELCCPXSec.h | 26 +- .../QuasiElastic/XSection/NievesQELCCXSec.cxx | 144 ++++++ .../QuasiElastic/XSection/NievesQELCCXSec.h | 109 +++++ 9 files changed, 444 insertions(+), 304 deletions(-) create mode 100644 config/NievesQELCCXSec.xml create mode 100644 src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx create mode 100644 src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h diff --git a/config/NievesQELCCPXSec.xml b/config/NievesQELCCPXSec.xml index 3a465a0e15..bbd7edf2c0 100644 --- a/config/NievesQELCCPXSec.xml +++ b/config/NievesQELCCPXSec.xml @@ -15,7 +15,6 @@ CabibboAngle double No Cabibbo angle RPA bool Yes Turn RPA effects on or off true Coulomb bool Yes Turn coulomb effects on or off true QEL-CC-XSecScale double Yes Scaling factor for CC GPL value -QEL-NC-XSecScale double Yes Scaling factor for NC GPL value PreciseLeptonPol bool Yes Do precise calculation of lepton polarization No LindhardFunction string Yes Which Lindhard functions to use? OriginalByNieves @@ -37,9 +36,8 @@ RmaxMode string Yes Method to use to comput CKM,FermiGas,NUCL 1.000 - 1.000 - genie::NewQELXSec/Default + genie::NievesQELCCXSec/Default genie::NuclearModelMap/Default UseNuclearModel 10.0 @@ -54,6 +52,7 @@ RmaxMode string Yes Method to use to comput VertexGenerator true + CJP46 + + + adaptive + 1e-5 + 7500 + 1e5 + + adaptive + 1e-5 + 1e5 + + + + + + + diff --git a/config/master_config.xml b/config/master_config.xml index b43cc93da7..c42a6884f9 100644 --- a/config/master_config.xml +++ b/config/master_config.xml @@ -156,6 +156,7 @@ QELXSec.xml NewQELXSec.xml + NievesQELCCXSec.xml SmithMonizQELCCXSec.xml DISXSec.xml COHDNuXSec.xml diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index e8bb0b63ef..d8ae533e06 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -265,7 +265,7 @@ void genie::utils::CalculatePolarizationVectorInTargetRestFrame( double El = leptonMomTRF.E(); double Pl = leptonMomTRF.P(); double cost = TMath::Cos( neutrinoMomTRF.Angle(leptonMomTRF.Vect()) ); - double sint = TMath::Sin( neutrinoMomTRF.Angle(leptonMomTRF.Vect()) ); + double sint = TMath::Sqrt(1 - cost*cost); int sign = isLeftPolarized?-1:1; double auxm = (El - Pl*cost)/2/M; double auxp = (El + Pl*cost)/2/M; diff --git a/src/Physics/QuasiElastic/XSection/LinkDef.h b/src/Physics/QuasiElastic/XSection/LinkDef.h index 4ed7a11be0..c5e00521c0 100644 --- a/src/Physics/QuasiElastic/XSection/LinkDef.h +++ b/src/Physics/QuasiElastic/XSection/LinkDef.h @@ -32,6 +32,7 @@ #pragma link C++ class genie::ZExpAxialFormFactorModel; #pragma link C++ class genie::MArunAxialFormFactorModel; #pragma link C++ class genie::NievesQELCCPXSec; +#pragma link C++ class genie::NievesQELCCXSec; #pragma link C++ class genie::SuSAv2QELPXSec; #pragma link C++ class genie::SmithMonizQELCCPXSec; #pragma link C++ class genie::SmithMonizQELCCXSec; @@ -46,5 +47,6 @@ // Wrappers for GSL/MathMore lib #pragma link C++ class genie::utils::gsl::d2Xsec_dQ2dv; +#pragma link C++ class genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E; #endif diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index a0bbca6477..8410289643 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -29,6 +29,7 @@ #include "Physics/NuclearState/FermiMomentumTablePool.h" #include "Physics/NuclearState/FermiMomentumTable.h" #include "Physics/QuasiElastic/XSection/NievesQELCCPXSec.h" +#include "Physics/QuasiElastic/XSection/NievesQELCCXSec.h" #include "Framework/Numerical/RandomGen.h" #include "Framework/ParticleData/PDGCodes.h" #include "Framework/ParticleData/PDGUtils.h" @@ -146,10 +147,10 @@ double NievesQELCCPXSec::XSec(const Interaction * interaction, double Vc = vcr(& target, r); // Outgoing lepton energy and momentum including Coulomb potential - int sign = is_neutrino ? 1 : -1; + int sign = is_neutrino ? -1 : 1; double El = leptonMom.E(); double pl = leptonMom.P(); - double ElLocal = El - sign*Vc; + double ElLocal = El + sign*Vc; if ( ElLocal - ml <= 0. ) { LOG("Nieves", pDEBUG) << "Event should be rejected. Coulomb effects" @@ -337,12 +338,16 @@ double NievesQELCCPXSec::Integral(const Interaction * in) const // let the cross section integrator do all of the work. It's smart // enough to handle free nucleon vs. nuclear targets, different // nuclear models (including the local Fermi gas model), etc. - if ( fXSecIntegrator->Id().Name() == "genie::NewQELXSec" ) { + if ( fXSecIntegrator->Id().Name() == "genie::NievesQELCCXSec" ) + { + Target * tgt = in->InitStatePtr()->TgtPtr(); + tgt->SetHitNucPosition(MaximalRadius(tgt) ); return fXSecIntegrator->Integrate(this, in); } - else { + else + { LOG("Nieves", pFATAL) << "Splines for the Nieves CCQE model must be" - << " generated using genie::NewQELXSec"; + << " generated using genie::NievesQELCCPXSec"; std::exit(1); } } @@ -355,6 +360,10 @@ bool NievesQELCCPXSec::ValidProcess(const Interaction * interaction) const const ProcessInfo & proc_info = interaction->ProcInfo(); if(!proc_info.IsQuasiElastic()) return false; + + // The calculation is only appropriate for complex nuclear targets, + // not free nucleons. + if ( !init_state.Tgt().IsNucleus() ) return false; int nuc = init_state.Tgt().HitNucPdg(); int nu = init_state.ProbePdg(); @@ -810,16 +819,14 @@ double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const int A = target->A(); int Z = target->Z(); - ROOT::Math::IBaseFunctionOneDim * func = new - utils::gsl::wrap::NievesQELvcrIntegrand(Rcurr,A,Z); - ROOT::Math::IntegrationOneDim::Type ig_type = - utils::gsl::Integration1DimTypeFromString("adaptive"); - - double abstol = 1; // We mostly care about relative tolerance; - double reltol = 1E-4; - int nmaxeval = 100000; - ROOT::Math::Integrator ig(*func,ig_type,abstol,reltol,nmaxeval); - double result = ig.Integral(0,Rmax); + + ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELvcrIntegrand(Rcurr,A,Z); + const NievesQELCCXSec * integrator = dynamic_cast(fXSecIntegrator); + ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( integrator->Get1DimIntgType() ); + double reltol = integrator->Get1DimRelTol(); + unsigned int nmaxeval = integrator->Get1DimMaxEval(); + ROOT::Math::Integrator ig(*func, ig_type, 0, reltol, nmaxeval); + double result = ig.Integral(0, Rmax); delete func; // Multiply by Z to normalize densities to number of protons @@ -876,11 +883,6 @@ double NievesQELCCPXSec::MaximalRadius(const Target * target) const } } //____________________________________________________________________________ -int NievesQELCCPXSec::leviCivita(int input[]) const -{ - return (input[1] - input[0])*(input[2] - input[0])*(input[3] - input[0])*(input[2] - input[1])*(input[3] - input[1])*(input[3] - input[2])/12; -} -//____________________________________________________________________________ // Calculates the constraction of the leptonic and hadronic tensors. The // expressions used here are valid in a frame in which the // initial nucleus is at rest, and qTilde must be in the z direction. @@ -956,8 +958,6 @@ const Target& target, bool assumeFreeNucleon) const //Additional constants and variables - const int g[4][4] = {{1,0,0,0},{0,-1,0,0},{0,0,-1,0},{0,0,0,-1}}; - int leviCivitaIndexArray[4]; double imaginaryPart = 0; std::complex sum(0.0,0.0); @@ -975,23 +975,19 @@ const Target& target, bool assumeFreeNucleon) const imaginaryPart = 0; if(mu == nu){ //if mu==nu then levi-civita = 0, so imaginary part = 0 - Lmunu = g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu]+g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu]-g[mu][nu]*kPrimek; + Lmunu = g(mu, mu)*kPrime[mu]*g(nu, nu)*k[nu]+g(nu, nu)*kPrime[nu]*g(mu, mu)*k[mu]-g(mu, nu)*kPrimek; }else{ //if mu!=nu, then g[mu][nu] = 0 //This same leviCivitaIndex array can be used in the else portion when //calculating Anumu - leviCivitaIndexArray[0] = mu; - leviCivitaIndexArray[1] = nu; for(int a=0;a<4;a++){ for(int b=0;b<4;b++){ - leviCivitaIndexArray[2] = a; - leviCivitaIndexArray[3] = b; - imaginaryPart += - leviCivita(leviCivitaIndexArray)*kPrime[a]*k[b]; + imaginaryPart -= e(mu, nu,a, b)*kPrime[a]*k[b]; } } //real(Lmunu) is symmetric, and imag(Lmunu) is antisymmetric - Lmunu = g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu]+g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu] + 1i*imaginaryPart; - Lnumu = g[nu][nu]*kPrime[nu]*g[mu][mu]*k[mu]+g[mu][mu]*kPrime[mu]*g[nu][nu]*k[nu ]- 1i*imaginaryPart; + Lmunu = g(mu, mu)*kPrime[mu]*g(nu, nu)*k[nu]+g(nu, nu)*kPrime[nu]*g(mu, mu)*k[mu] + 1i*imaginaryPart; + Lnumu = g(nu, nu)*kPrime[nu]*g(mu, mu)*k[mu]+g(mu, mu)*kPrime[mu]*g(nu, nu)*k[nu] - 1i*imaginaryPart; } // End Lmunu calculation double aux1 = 2*CL*Fp*(Fp*q2 + 4*FA*M); if(mu ==0 && nu == 0){ @@ -1088,12 +1084,11 @@ ROOT::Math::IBaseFunctionOneDim * //____________________________________________________________________________ utils::gsl::wrap::NievesQELSmithMonizIntegrand::NievesQELSmithMonizIntegrand( - const NievesQELCCPXSec* alg_, const Interaction* interaction_, int mu_, int nu_): + const NievesQELCCPXSec* alg_, const Interaction* interaction_, int mod_): ROOT::Math::IBaseFunctionOneDim(), alg(alg_), interaction(interaction_), -mu(mu_), -nu(nu_) +mod(mod_) { } @@ -1110,13 +1105,13 @@ unsigned int utils::gsl::wrap::NievesQELSmithMonizIntegrand::NDim(void) const //____________________________________________________________________________ double utils::gsl::wrap::NievesQELSmithMonizIntegrand::DoEval(double rin) const { - return alg->IntegratedAmunuOverMomentum(interaction, rin, mu, nu); + return alg->IntegratedOverMomentum(interaction, rin, mod); } //____________________________________________________________________________ ROOT::Math::IBaseFunctionOneDim * utils::gsl::wrap::NievesQELSmithMonizIntegrand::Clone(void) const { - return new utils::gsl::wrap::NievesQELSmithMonizIntegrand(alg, interaction, mu, nu); + return new utils::gsl::wrap::NievesQELSmithMonizIntegrand(alg, interaction, mod); } //____________________________________________________________________________ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const @@ -1128,72 +1123,48 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i const InitialState & init_state = interaction -> InitState(); const Target & target = init_state.Tgt(); - const double M = 1; // polarization doesn't depend on M - // common factor will be reduced - //double factor = fCos8c2*M*Omega/pl/El/kPi/4; double Rmax = MaximalRadius(&target); - double W00, Wxx, Wzz, ReW0z, ImWxy; - if (!target.IsNucleus() || Rmax <= 0) + if (Rmax <= 0) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + + const NievesQELCCXSec * integrator = dynamic_cast(fXSecIntegrator); + ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( integrator->Get1DimIntgType() ); + double reltol = integrator->Get1DimRelTol(); + unsigned int nmaxeval = integrator->Get1DimMaxEval(); + + ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 1); + ROOT::Math::Integrator ig(*func, ig_type, 0, reltol, nmaxeval); + double R = ig.Integral(0, Rmax); + delete func; + if (R == 0) { - FinalLeptonPolarizationOnFreeNucleon (interaction, W00, Wxx, Wzz, ReW0z, ImWxy); + fFinalLeptonPolarization = TVector3(0, 0, 0); + return fFinalLeptonPolarization; } - else - { - ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString("adaptive"); - double reltol = 1E-4; - int nmaxeval = 100000; - - ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 0, 0); - ROOT::Math::Integrator ig(*func,ig_type,0,reltol,nmaxeval); - W00 = ig.Integral(0, Rmax); - delete func; - - func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 1, 1); - ig.SetFunction(*func); - Wxx = ig.Integral(0, Rmax); - delete func; - - func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 3, 3); - ig.SetFunction(*func); - Wzz = ig.Integral(0, Rmax); - delete func; - - func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 0, 3); - ig.SetFunction(*func); - ReW0z = ig.Integral(0, Rmax); - delete func; - func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 1, 2); - ig.SetFunction(*func); - ImWxy= ig.Integral(0, Rmax); - delete func; - } + func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 2); + ig.SetFunction(*func); + double PLR = ig.Integral(0, Rmax); + delete func; + + func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 3); + ig.SetFunction(*func); + double PPR = ig.Integral(0, Rmax); + delete func; + + double PL = PLR/R; + double PP = PPR/R; - bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); TLorentzVector neutrinoMom = *tempNeutrino; delete tempNeutrino; const TLorentzVector leptonMom = kinematics.FSLeptonP4(); - TLorentzVector q4 = neutrinoMom - leptonMom; - - double q0 = q4.E(); - double q = q4.Vect().Mag(); - double q02 = q0*q0; - double q2 = q*q; - - double T1 = Wxx/2/M; - double T2 = (W00 + Wxx + q02/q2*(Wzz - Wxx) - 2*q0/q*ReW0z)/2/M; - double T3 = -ImWxy/q; - double T4 = M/2/q2*(Wzz - Wxx); - double T5 = (ReW0z - q0/q*(Wzz - Wxx))/q; - - CalculatePolarizationVectorInTargetRestFrame( - fFinalLeptonPolarization, - neutrinoMom, - leptonMom, - is_neutrino, - M, T1,T2,T3,T4,T5,0); + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + TVector3 Pz = leptonMom3.Unit(); + TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); + TVector3 Py = Pz.Cross(Px); + fFinalLeptonPolarization = PP*Py + PL*Pz; if (fFinalLeptonPolarization.Mag2()>1) return XSecAlgorithmI::FinalLeptonPolarization(interaction); @@ -1201,131 +1172,7 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i } //___________________________________________________________________________________ -void NievesQELCCPXSec::FinalLeptonPolarizationOnFreeNucleon (const Interaction* interaction, double & A00, double & Axx, double & Azz, double & A0z, double & Axy) const -{ - - A00 = Axx = Azz = A0z = Axy = 0; - // Get kinematics and init-state parameters - const Kinematics & kinematics = interaction -> Kine(); - const InitialState & init_state = interaction -> InitState(); - const Target & target = init_state.Tgt(); - - // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial - // struck nucleon - double Mi = target.HitNucMass(); - - // On-shell mass of final nucleon (from PDGLibrary) - double Mf = interaction->RecoilNucleon()->Mass(); - - // Isoscalar mass of nucleon - double M = (Mi + Mf)/2; - - // Note that GetProbeP4 defaults to returning the probe 4-momentum in the - // struck nucleon rest frame, so we have to explicitly ask for the lab frame - // here - TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); - TLorentzVector neutrinoMom = *tempNeutrino; - delete tempNeutrino; - - TLorentzVector leptonMom = kinematics.FSLeptonP4(); - - double q0Tilde = neutrinoMom.E() - leptonMom.E(); - - // Note that we're working in the lab frame (i.e., the rest frame - // of the target nucleus). We can therefore use Nieves' explicit - // form of the Amunu tensor if we rotate the 3-momenta so that - // qTilde is in the +z direction - TVector3 neutrinoMom3 = neutrinoMom.Vect(); - TVector3 leptonMom3 = leptonMom.Vect(); - - // If Coulomb corrections are being used, adjust the lepton 3-momentum used - // to get q3VecTilde so that its magnitude matches the local - // Coulomb-corrected value calculated earlier. Note that, although the - // treatment of Coulomb corrections by Nieves et al. doesn't change the - // direction of the lepton 3-momentum, it *does* change the direction of the - // 3-momentum transfer, and so the correction should be applied *before* - // rotating coordinates into a frame where q3VecTilde lies along the positive - // z axis. - TVector3 q3VecTilde = neutrinoMom3 - leptonMom3; - - // Find the rotation angle needed to put q3VecTilde along z - TVector3 zvec(0, 0, 1); - TVector3 rot = ( q3VecTilde.Cross(zvec) ).Unit(); // Vector to rotate about - // Angle between the z direction and q - double angle = zvec.Angle( q3VecTilde ); - - // Handle the edge case where q3VecTilde is along -z, so the - // cross product above vanishes - if ( q3VecTilde.Perp() == 0. && q3VecTilde.Z() < 0. ) - { - rot = TVector3(0., 1., 0.); - angle = kPi; - } - - // Rotate if the rotation vector is not 0 - if ( rot.Mag() > 0 ) - { - neutrinoMom3.Rotate(angle,rot); - neutrinoMom.SetVect(neutrinoMom3); - leptonMom3.Rotate(angle,rot); - leptonMom.SetVect(leptonMom3); - } - - // Calculate qTilde - TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); - - double Q2tilde = -qTildeP4.Mag2(); - - // Check that Q2tilde > 0 (accounting for rounding errors) - if (Q2tilde < 0) - { - return; - } - - // Store Q2tilde in the kinematic variable representing Q2. - // This will ensure that the form factors are calculated correctly - // using the de Forest prescription (Q2tilde instead of Q2). - interaction->KinePtr()->SetQ2(Q2tilde); - // Calculate form factors - fFormFactors.Calculate( interaction ); - - - - // Get the QEL form factors (were calculated before this method was called) - double F1V = 0.5*fFormFactors.F1V(); - double xiF2V = 0.5*fFormFactors.xiF2V(); - double FA = fFormFactors.FA(); - // According to Nieves' paper, Fp = 2.0*M*FA/(kPionMass2-q2), but Llewelyn- - // Smith uses Fp = 2.0*M^2*FA/(kPionMass2-q2), so I divide by M - // This gives units of GeV^-1 - double Fp = fFormFactors.Fp()/M; - - // Calculate auxiliary parameters - // Off shell mass of initial nucleon - double M2 = M*M; - double FA2 = FA*FA; - double F1V2 = F1V*F1V; - double xiF2V2 = xiF2V*xiF2V; - double q0 = qTildeP4.E(); - double dq = qTildeP4.Pz(); - double q02 = q0*q0; - double dq2 = dq*dq; - double q2 = q02 - dq2; - - double aux1 = 2*Fp*(Fp*q2 + 4*FA*M); - A00 = 32*F1V2*(M2 + q0*M + q2/4) + 8*q2*xiF2V2*(-q0/M - q02*(1/q2 + 1/M2/4)) + - 8*FA2*(q0*M + q2/4) - aux1*q02 - 16*F1V*xiF2V*dq2; - Axx = 8*(FA2*M2 - q2*( (F1V+xiF2V)*(F1V+xiF2V) + FA2/4 ) ); - Azz = -8*F1V2*q2 - 8*q2*xiF2V2*(1 + dq2*(1/q2 + 1/M2/4))+ - 8*FA2*(M2 - q2/4) - aux1*dq2 - 16*F1V*xiF2V*q02; - A0z = 16*F1V2*M*dq - 4*q2*xiF2V2*(dq/M + dq*q0*(2/q2 + 1/M2/2)) - + 4*FA2*M*dq - dq*q0*(aux1 + 16*F1V*xiF2V); - Axy = 16*FA*(xiF2V+F1V)*dq*M; - - return; -} -//___________________________________________________________________________________ -double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interaction, double r, int mu, int nu) const +double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, double r, int mod) const { // Get kinematics and init-state parameters const Kinematics & kinematics = interaction -> Kine(); @@ -1353,10 +1200,10 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac // Calculate Coulomb corrections double ml = interaction->FSPrimLepton()->Mass(); double ml2 = ml*ml; - double plLocal = leptonMom.P(); + double PlLocal = leptonMom.P(); bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); - int sign = is_neutrino ? 1 : -1; + int sign = is_neutrino ? -1 : 1; double ElLocal = leptonMom.E(); if ( fCoulomb ) @@ -1366,7 +1213,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac // Outgoing lepton energy and momentum including Coulomb potential double El = ElLocal; - ElLocal = El - sign*Vc; + ElLocal = El + sign*Vc; if ( ElLocal - ml <= 0 ) return 0; @@ -1378,7 +1225,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac if ( KEl <= TMath::Abs(Vc) ) return 0; // Local value of the lepton 3-momentum magnitude for the Coulomb correction - plLocal = TMath::Sqrt(ElLocal*ElLocal - ml2); + PlLocal = TMath::Sqrt(ElLocal*ElLocal - ml2); } @@ -1412,7 +1259,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac // If binding energy effects pull us into an unphysical region, return // zero - if ( q0Tilde <= 0 && tgtIsNucleus && !interaction->TestBit(kIAssumeFreeNucleon) ) return 0; + if ( q0Tilde <= 0 ) return 0; // Note that we're working in the lab frame (i.e., the rest frame // of the target nucleus). We can therefore use Nieves' explicit @@ -1429,34 +1276,10 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac // 3-momentum transfer, and so the correction should be applied *before* // rotating coordinates into a frame where q3VecTilde lies along the positive // z axis. - TVector3 leptonMomCoulomb3 = !fCoulomb ? leptonMom3: plLocal*leptonMom3*(1/leptonMom3.Mag()); + TVector3 leptonMomCoulomb3 = !fCoulomb ? leptonMom3: PlLocal*leptonMom3*(1/leptonMom3.Mag()); TVector3 q3VecTilde = neutrinoMom3 - leptonMomCoulomb3; // Calculate qTilde TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); - - // Find the rotation angle needed to put q3VecTilde along z - TVector3 zvec(0, 0, 1); - TVector3 rot = ( q3VecTilde.Cross(zvec) ).Unit(); // Vector to rotate about - // Angle between the z direction and q - double angle = zvec.Angle( q3VecTilde ); - - // Handle the edge case where q3VecTilde is along -z, so the - // cross product above vanishes - if ( q3VecTilde.Perp() == 0. && q3VecTilde.Z() < 0. ) - { - rot = TVector3(0., 1., 0.); - angle = kPi; - } - - // Rotate if the rotation vector is not 0 - if ( rot.Mag() > 0 ) - { - neutrinoMom3.Rotate(angle,rot); - neutrinoMom.SetVect(neutrinoMom3); - leptonMom3.Rotate(angle,rot); - leptonMom.SetVect(leptonMom3); - } - double Q2tilde = -qTildeP4.Mag2(); // Check that Q2tilde > 0 (accounting for rounding errors) @@ -1469,8 +1292,6 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac // Calculate form factors fFormFactors.Calculate( interaction ); - - // Get the QEL form factors (were calculated before this method was called) double F1V = 0.5*fFormFactors.F1V(); double xiF2V = 0.5*fFormFactors.xiF2V(); @@ -1499,8 +1320,7 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac double q02 = q0*q0; double q2 = q02 - dq2; - - double factor = plLocal*ElLocal*r*r/dq; + double factor = PlLocal*ElLocal*r*r/dq; double c = q0/dq; double d = q2/2/M/dq; @@ -1527,45 +1347,71 @@ double NievesQELCCPXSec::IntegratedAmunuOverMomentum (const Interaction* interac double a6 = c*b1 + d*b0; double a7 = b1; + double Ep = M*a7; + double Ep2 = M2*a4; + double px2 = 0.5*M2*(a2 - a3); //py2=px2 + double pz = M*a6; + double Eppz = M2*a5; + double pz2 = M2*a3; + + double aux = 2*CL*Fp*(Fp*q2 + 4*FA*M); + double W00 = 32*F1V2*(Ep2*CN + Ep*q0 + a1*q2/4)+ + 8*q2*xiF2V2*(a1*(1 - q02*(1/q2 + 1/M2/4)) - Ep2/M2 - Ep*q0/M2) + + 8*FA2*(Ep2 + Ep*q0 + a1*(q2/4 - M2)) - a1*(aux*q02 + 16*F1V*xiF2V*(q02 - q2)*CN); + double Wxx = 32*F1V2*(px2 - a1*q2/4) - 8*q2*xiF2V2*(a1*CT + px2/M2) + + 8*FA2*(px2 + a1*(CT*M2 - q2/4)) - 16*a1*F1V*xiF2V*CT*q2; + double Wzz = 32*F1V2*(pz2 + pz*dq - a1*q2/4)- + 8*q2*xiF2V2*(a1 + pz2/M2 + pz*dq/M2 + a1*dq2*(1/q2 + 1/M2/4))+ + 8*FA2*(pz2 + pz*dq + a1*(CL*M2 - q2/4)) - a1*(aux*dq2 + 16*F1V*xiF2V*q02); + double ReW0z = 16*F1V2*((2*Eppz + Ep*dq)*CN + pz*q0) + -4*q2*xiF2V2*(2*Eppz/M2 + (Ep*dq + pz*q0)/M2 + a1*dq*q0*(2/q2 + 1/M2/2))+ + 4*FA2*((2*Eppz + Ep*dq)*CL + pz*q0) - a1*dq*q0*(aux + 16*F1V*xiF2V); + double ImWxy = -16*FA*(xiF2V+F1V)*(pz*q0 - Ep*dq*CT); + + + TLorentzVector q4 = neutrinoMom - leptonMom; + double v = q4.E(); + double v2 = v*v; + double qv2 = q4.Vect().Mag2(); + double qv = TMath::Sqrt(q2); + + double W1 = Wxx/2/M; + double W2 = (W00 + Wxx + v2/qv2*(Wzz - Wxx) - 2*v/qv*ReW0z)/2/M; + double W3 = -ImWxy/qv; + double W4 = M/2/qv2*(Wzz - Wxx); + double W5 = (ReW0z - v/qv*(Wzz - Wxx))/qv; + + double Ev = neutrinoMom.E(); + double El = leptonMom.E(); + double Pl = leptonMom.P(); + double cost = TMath::Cos( neutrinoMom.Angle(leptonMom.Vect()) ); + double sint = TMath::Sqrt(1 - cost*cost); + + double auxm = (El - Pl*cost)/2/M; + double auxp = (El + Pl*cost)/2/M; + double aux1m = (Pl - El*cost)/2/M; + double aux1p = (Pl + El*cost)/2/M; + double aux1 = ml2/2/M2; + double aux2 = (Ev + El)/M; - double Ep = M*a7; - double Ep2 = M2*a4; - double px2 = 0.5*M2*(a2 - a3); //py2=px2 - double pz = M*a6; - double Eppz = M2*a5; - double pz2 = M2*a3; + if (mod == 2) return sign*(2*aux1m*(W1 - aux1*W4) + aux1p*W2 - sign*(aux2*aux1m + aux1*cost)*W3 - aux1*cost*W5); //PL*R + if (mod == 3) return sign*ml*sint*(2*W1 - W2 -sign*Ev*W3/M - ml2*W4/M2 + El*W5/M)/2/M; //PP*R + double R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; + if (mod == 1) return R; - double aux1 = 2*CL*Fp*(Fp*q2 + 4*FA*M); + double extrafactor = kGF2*fCos8c2*TMath::Sq(kMw2/(kMw2 - q4.Mag2() ) )/El; + + // Calculate xsec + double xsec = extrafactor*R; + xsec *= fXSecCCScale ; - if (mu == 0 && nu == 0) - { - return 32*F1V2*(Ep2*CN + Ep*q0 + a1*q2/4)+ - 8*q2*xiF2V2*(a1*(1 - q02*(1/q2 + 1/M2/4)) - Ep2/M2 - Ep*q0/M2) + - 8*FA2*(Ep2 + Ep*q0 + a1*(q2/4 - M2)) - a1*(aux1*q02 + 16*F1V*xiF2V*(q02 - q2)*CN); - } - if ( (mu == 1 && nu == 1) || (mu == 2 && nu == 2) ) - { - return 32*F1V2*(px2 - a1*q2/4)- - 8*q2*xiF2V2*(a1*CT + px2/M2) + - 8*FA2*(px2 + a1*(CT*M2 - q2/4))- - 16*a1*F1V*xiF2V*CT*q2; - } - if (mu == 3 && nu == 3) - { - return 32*F1V2*(pz2 + pz*dq - a1*q2/4)- - 8*q2*xiF2V2*(a1 + pz2/M2 + pz*dq/M2 + a1*dq2*(1/q2 + 1/M2/4))+ - 8*FA2*(pz2 + pz*dq + a1*(CL*M2 - q2/4)) - a1*(aux1*dq2 + 16*F1V*xiF2V*q02); - } - if (mu == 0 && nu == 3) - { - return 16*F1V2*((2*Eppz + Ep*dq)*CN + pz*q0) - -4*q2*xiF2V2*(2*Eppz/M2 + (Ep*dq + pz*q0)/M2 + a1*dq*q0*(2/q2 + 1/M2/2))+ - 4*FA2*((2*Eppz + Ep*dq)*CL + pz*q0) - a1*dq*q0*(aux1 + 16*F1V*xiF2V); - } - if (mu == 1 && nu == 2) // should be multiplied by i - { - return -16*FA*(xiF2V+F1V)*(pz*q0 - Ep*dq*CT); - } - return 0; + // Number of scattering centers in the target + int nucpdgc = target.HitNucPdg(); + int NNucl = (pdg::IsProton(nucpdgc)) ? target.Z() : target.N(); + + xsec *= NNucl; // nuclear xsec + + return xsec; + } //___________________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 05bfb158dd..f01b492610 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -63,7 +63,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; const TVector3 & FinalLeptonPolarization (const Interaction* i) const; - double IntegratedAmunuOverMomentum (const Interaction* interaction, double r, int mu, int nu) const; + double IntegratedOverMomentum (const Interaction* i, double r, int mod) const; // Override the Algorithm::Configure methods to load configuration // data to private data members @@ -86,7 +86,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double fhbarc; ///< hbar*c in GeV*fm // mutable for testing purposes only! - mutable bool fRPA; ///< use RPA corrections + mutable bool fRPA; ///< use RPA corrections bool fCoulomb; ///< use Coulomb corrections const NuclearModelI* fNuclModel; ///< Nuclear Model for integration @@ -144,20 +144,21 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double vcr(const Target * target, double r) const; double MaximalRadius(const Target * target) const; - - //input must be length 4. Returns 1 if input is an even permutation of 0123, - //-1 if input is an odd permutation of 0123, and 0 if any two elements - //are equal - int leviCivita(int input[]) const; + + inline int g(int a, int b) const///< metric g^{ab}=g_{ab}=diag(1,-1,-1,1) + { + return (a==b)*(2*(a==0) - 1); + } + inline int e(int a, int b, int c, int d) const ///< Levi-Chevita symbol, where e_{0123}=+1 + { + return (b - a)*(c - a)*(d - a)*(c - b)*(d - b)*(d - c)/12; + } double LmunuAnumu(const TLorentzVector neutrinoMom, const TLorentzVector inNucleonMom, const TLorentzVector leptonMom, const TLorentzVector outNucleonMom, double M, bool is_neutrino, const Target& target, bool assumeFreeNucleon) const; - void FinalLeptonPolarizationOnFreeNucleon (const Interaction* interaction, - double & A00, double & Axx, double & Azz, - double & A0z, double & Axy) const; }; } // genie namespace @@ -199,7 +200,7 @@ namespace genie { class NievesQELSmithMonizIntegrand : public ROOT::Math::IBaseFunctionOneDim { public: - NievesQELSmithMonizIntegrand(const NievesQELCCPXSec* alg_, const Interaction* interaction_, int mu_, int nu_); + NievesQELSmithMonizIntegrand(const NievesQELCCPXSec* alg_, const Interaction* interaction_, int mod_); ~NievesQELSmithMonizIntegrand(); // ROOT::Math::IBaseFunctionOneDim interface unsigned int NDim (void) const; @@ -208,8 +209,7 @@ namespace genie { private: const NievesQELCCPXSec* alg; const Interaction* interaction; - int mu; - int nu; + int mod; }; } // wrap namespace diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx new file mode 100644 index 0000000000..56563c7b48 --- /dev/null +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx @@ -0,0 +1,144 @@ +//____________________________________________________________________________ +/* + Copyright (c) 2003-2025, The GENIE Collaboration + For the full text of the license visit http://copyright.genie-mc.org + + Igor Kakorin JINR +*/ +//____________________________________________________________________________ + +#include "Framework/Algorithm/AlgConfigPool.h" +#include "Framework/Algorithm/AlgFactory.h" +#include "Framework/Conventions/GBuild.h" +#include "Framework/Conventions/Constants.h" +#include "Framework/Conventions/Controls.h" +#include "Framework/Conventions/Units.h" +#include "Framework/Conventions/KineVar.h" +#include "Framework/Conventions/RefFrame.h" +#include "Physics/QuasiElastic/XSection/NievesQELCCXSec.h" + +#include "Physics/XSectionIntegration/GSLXSecFunc.h" +#include "Framework/Messenger/Messenger.h" +#include "Framework/Numerical/RandomGen.h" +#include "Framework/ParticleData/PDGUtils.h" +#include "Framework/Utils/KineUtils.h" +#include "Framework/Utils/Range1.h" +#include "Framework/Numerical/GSLUtils.h" +#include "Physics/QuasiElastic/XSection/NievesQELCCPXSec.h" + + +using namespace genie; +using namespace genie::constants; +using namespace genie::utils::gsl; + +//____________________________________________________________________________ +NievesQELCCXSec::NievesQELCCXSec() : XSecIntegratorI("genie::NievesQELCCXSec") +{ + +} +//____________________________________________________________________________ +NievesQELCCXSec::NievesQELCCXSec(std::string config) : XSecIntegratorI("genie::NievesQELCCXSec", config) +{ + +} +//____________________________________________________________________________ +double NievesQELCCXSec::Integrate(const XSecAlgorithmI* model, const Interaction* in) const +{ + Target * tgt = in->InitStatePtr()->TgtPtr(); + double Rmax = tgt->HitNucPosition(); + utils::gsl::d3XSec_dElepdCosThetalepdR_E func(model, in, Rmax ) ; + ROOT::Math::IntegrationMultiDim::Type ig_type = utils::gsl::IntegrationNDimTypeFromString(fGSLIntgType); + ROOT::Math::IntegratorMultiDim ig(ig_type, 0, fGSLRelTol, fGSLMaxEval); + if (ig_type == ROOT::Math::IntegrationMultiDim::kADAPTIVE) + { + ROOT::Math::AdaptiveIntegratorMultiDim * cast = dynamic_cast( ig.GetIntegrator() ); + assert(cast); + cast->SetMinPts(fGSLMinEval); + } + ig.SetFunction(func); + double kine_min[3] = { 0., 0., 0.}; + double kine_max[3] = { 1., 1., 1.}; + double xsec = ig.Integral(kine_min, kine_max)*(1E-38 * units::cm2); + return xsec; +} +//____________________________________________________________________________ +void NievesQELCCXSec::Configure(const Registry & config) +{ + Algorithm::Configure(config); + this->LoadConfig(); +} +//____________________________________________________________________________ +void NievesQELCCXSec::Configure(string config) +{ + Algorithm::Configure(config); + this->LoadConfig(); +} +//____________________________________________________________________________ +void NievesQELCCXSec::LoadConfig(void) +{ + // Get GSL integration type & relative tolerance + GetParamDef( "gsl-integration-type", fGSLIntgType, std::string("adaptive") ); + GetParamDef( "gsl-relative-tolerance", fGSLRelTol, 1e-5 ); + int max; + GetParamDef( "gsl-max-eval", max, 100000 ); + fGSLMaxEval = static_cast( max ); + int min; + GetParamDef( "gsl-min-eval", min, 7500 ) ; + fGSLMinEval = static_cast( min ); + + GetParamDef( "gsl-1dim-integration-type", fGSLIntgType, std::string("adaptive") ); + GetParamDef( "gsl-1dim-relative-tolerance", fGSLRelTol, 1e-5 ); + GetParamDef( "gsl-1dim-max-eval", max, 100000 ); + fGSL1DimMaxEval = static_cast( max ); +} +//____________________________________________________________________________ +// GSL wrappers +//____________________________________________________________________________ +genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::d3XSec_dElepdCosThetalepdR_E( + const XSecAlgorithmI * m, const Interaction * interaction, double Rmax) : + ROOT::Math::IBaseFunctionMultiDim(), + fModel(m), + fInteraction(interaction), + fRmax(Rmax) +{ + // Get kinematical parameters + const InitialState & init_state = interaction -> InitState(); + fEnu = init_state.ProbeE(kRfHitNucRest); + fml = interaction->FSPrimLepton()->Mass(); +} +genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::~d3XSec_dElepdCosThetalepdR_E() +{ + +} +unsigned int genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::NDim(void) const +{ + return 3; +} +double genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::DoEval(const double * xin) const +{ + // outputs: + // differential cross section [1/GeV^3] for Resonance single pion production production + // + double El = fml + (fEnu - fml)*xin[0]; + double cost = -1 + 2*xin[1]; + double R = fRmax*xin[2]; + + double Pl = TMath::Sqrt(El*El - fml*fml); + double sint = TMath::Sqrt(1 - cost*cost); + + Kinematics * kinematics = fInteraction->KinePtr(); + kinematics->SetFSLeptonP4(Pl*sint, 0, Pl*cost, El); + + const NievesQELCCPXSec * xsec_model = dynamic_cast(fModel); + double xsec = xsec_model->IntegratedOverMomentum(fInteraction, R, 0); + + double J = (fEnu - fml)*2*fRmax; + + return xsec*J/(1E-38 * units::cm2); +} +ROOT::Math::IBaseFunctionMultiDim * +genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::Clone() const +{ + return + new genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E(fModel,fInteraction,fRmax); +} diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h new file mode 100644 index 0000000000..85769d8511 --- /dev/null +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h @@ -0,0 +1,109 @@ +//____________________________________________________________________________ +/*! + +\class genie::NievesQELCCXSec + +\brief Computes the Quasi Elastic (QEL) total cross section. \n + Is a concrete implementation of the XSecIntegratorI interface. \n + +\author Igor Kaorin JINR + +\created March 23, 2025 + +\cpright Copyright (c) 2003-2025, The GENIE Collaboration + For the full text of the license visit http://copyright.genie-mc.org +*/ +//____________________________________________________________________________ + +#ifndef _NIEVES_QEL_XSEC_H_ +#define _NIEVES_QEL_XSEC_H_ + +#include "Framework/EventGen/XSecAlgorithmI.h" +#include "Physics/XSectionIntegration/XSecIntegratorI.h" +#include "Physics/QuasiElastic/XSection/QELUtils.h" + +#include +#include +#include + +namespace genie { +class NievesQELCCXSec : public XSecIntegratorI { + +public: + + NievesQELCCXSec(void); + NievesQELCCXSec(std::string config); + + /// XSecIntegratorI interface implementation + double Integrate(const XSecAlgorithmI* model, const Interaction* i) const; + + std::string Get1DimIntgType() const + { + return fGSL1DimIntgType; + } + + unsigned int Get1DimMaxEval() const + { + return fGSL1DimMaxEval; + } + + double Get1DimRelTol() const + { + return fGSL1DimRelTol; + } + + /// Overload the Algorithm::Configure() methods to load private data + /// members from configuration options + void Configure(const Registry& config); + void Configure(std::string config); + +private: + + void LoadConfig (void); + + // XML configuration parameters + std::string fGSLIntgType; + double fGSLRelTol; + unsigned int fGSLMaxEval; + + std::string fGSL1DimIntgType; + double fGSL1DimRelTol; + unsigned int fGSL1DimMaxEval; + +}; + +class XSecAlgorithmI; +class Interaction; + +namespace utils { +namespace gsl { +//..................................................................................... +// +// A 3-D cross section function: d3xsec/dEldCosThetadR = f(El,CosTheta, R)|(fixed E) +// +class d3XSec_dElepdCosThetalepdR_E: public ROOT::Math::IBaseFunctionMultiDim +{ +public: + d3XSec_dElepdCosThetalepdR_E(const XSecAlgorithmI * m, const Interaction * i, double Rmax); + ~d3XSec_dElepdCosThetalepdR_E(); + + // ROOT::Math::IBaseFunctionMultiDim interface + unsigned int NDim (void) const; + double DoEval (const double * xin) const; + ROOT::Math::IBaseFunctionMultiDim * Clone (void) const; + +private: + const XSecAlgorithmI * fModel; + const Interaction * fInteraction; + double fRmax; + double fEnu; + double fml; + +}; + +} // gsl namespace +} // utils namespace + +} // genie namespace + +#endif // _NIEVES_QEL_XSEC_H_ From 1a4ee081e8618da2caacc12e75b1ebe51a54ab4d Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 25 Mar 2025 10:32:59 +0300 Subject: [PATCH 46/78] fix bug --- config/master_config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/master_config.xml b/config/master_config.xml index c42a6884f9..e385ffac9a 100644 --- a/config/master_config.xml +++ b/config/master_config.xml @@ -156,7 +156,7 @@ QELXSec.xml NewQELXSec.xml - NievesQELCCXSec.xml + NievesQELCCXSec.xml SmithMonizQELCCXSec.xml DISXSec.xml COHDNuXSec.xml From 27e0c7e6a357ab2bec2e65b2172d0bfc41e90a40 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 25 Mar 2025 11:46:45 +0300 Subject: [PATCH 47/78] fix bugs --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 3 +-- src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 8410289643..134b6afe8b 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -402,8 +402,7 @@ void NievesQELCCPXSec::LoadConfig(void) GetParamDef( "PreciseLeptonPol", fIsPreciseLeptonPolarization, false ) ; // Cross section scaling factor - GetParam( "QEL-CC-XSecScale", fXSecCCScale ) ; - GetParam( "QEL-NC-XSecScale", fXSecNCScale ) ; + GetParam( "QEL-CC-XSecScale", fXSecCCScale ); // hbarc for unit conversion, GeV*fm fhbarc = kLightSpeed*kPlankConstant/genie::units::fermi; diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx index 56563c7b48..86a3f3e0bf 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx @@ -86,8 +86,8 @@ void NievesQELCCXSec::LoadConfig(void) GetParamDef( "gsl-min-eval", min, 7500 ) ; fGSLMinEval = static_cast( min ); - GetParamDef( "gsl-1dim-integration-type", fGSLIntgType, std::string("adaptive") ); - GetParamDef( "gsl-1dim-relative-tolerance", fGSLRelTol, 1e-5 ); + GetParamDef( "gsl-1dim-integration-type", fGSL1DimIntgType, std::string("adaptive") ); + GetParamDef( "gsl-1dim-relative-tolerance", fGSL1DimRelTol, 1e-5 ); GetParamDef( "gsl-1dim-max-eval", max, 100000 ); fGSL1DimMaxEval = static_cast( max ); } From 860471029de5449d1107e1eaab7e96bd683cf7b1 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 25 Mar 2025 12:30:57 +0300 Subject: [PATCH 48/78] fix bugs --- config/NievesQELCCXSec.xml | 8 ++++---- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/NievesQELCCXSec.xml b/config/NievesQELCCXSec.xml index 65dd5890ef..40ec948558 100644 --- a/config/NievesQELCCXSec.xml +++ b/config/NievesQELCCXSec.xml @@ -11,12 +11,12 @@ Name Type Optional Comment gsl-integration-type string Yes name of GSL numerical integrator adaptive (adaptive, vegas, miser, plain) -gsl-max-eval int Yes GSL maximal number of function calls 1e5 +gsl-max-eval int Yes GSL maximal number of function calls 100000 gsl-min-eval int Yes GSL minimal number of function calls 7500 gsl-relative-tolerance double Yes relative tolerance of integration 1e-5 gsl-1dim-integration-type string Yes name of GSL numerical integrator adaptive -gsl-1dim-max-eval int Yes GSL maximal number of function calls 1e5 +gsl-1dim-max-eval int Yes GSL maximal number of function calls 100000 gsl-1dim-relative-tolerance double Yes relative tolerance of integration 1e-5 ..................................................................................................... --> @@ -25,11 +25,11 @@ gsl-1dim-relative-tolerance double Yes relative tolerance of integrat adaptive 1e-5 7500 - 1e5 + 100000 adaptive 1e-5 - 1e5 + 100000 diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 134b6afe8b..a333b33a83 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1372,7 +1372,7 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, double v = q4.E(); double v2 = v*v; double qv2 = q4.Vect().Mag2(); - double qv = TMath::Sqrt(q2); + double qv = TMath::Sqrt(qv2); double W1 = Wxx/2/M; double W2 = (W00 + Wxx + v2/qv2*(Wzz - Wxx) - 2*v/qv*ReW0z)/2/M; From 1ae7ed630c3519bd9d6f9714ab56898b128db0d5 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 31 Mar 2025 19:37:30 +0300 Subject: [PATCH 49/78] add a new integration method --- .../EventGen/QELEventGeneratorSM.cxx | 6 +- .../XSection/NievesQELCCPXSec.cxx | 55 +++++++---- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 2 +- .../QuasiElastic/XSection/NievesQELCCXSec.cxx | 43 ++++++--- .../QuasiElastic/XSection/NievesQELCCXSec.h | 7 +- .../XSection/SmithMonizQELCCPXSec.cxx | 20 ++-- .../QuasiElastic/XSection/SmithMonizUtils.cxx | 94 ++++++++++++------- .../QuasiElastic/XSection/SmithMonizUtils.h | 9 +- 8 files changed, 153 insertions(+), 83 deletions(-) diff --git a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx index 56f6294d90..db4ad196af 100644 --- a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx +++ b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx @@ -179,7 +179,7 @@ void QELEventGeneratorSM::ProcessEventRecord(GHepRecord * evrec) const Range1D_t rkF = sm_utils->kFQES_SM_lim(Q2, v); // rkF.max = Fermi momentum - kF = rnd->RndKine().Rndm()*sm_utils->GetFermiMomentum(); + kF = rnd->RndKine().Rndm()*sm_utils->GetInitialFermiMomentum(); if (kF < rkF.min) { continue; @@ -473,7 +473,7 @@ double QELEventGeneratorSM::ComputeMaxXSec(const Interaction * interaction) cons const double logQ2min = TMath::Log(TMath::Max(rQ2.min, eps)); const double logQ2max = TMath::Log(TMath::Min(rQ2.max, fQ2Min)); Kinematics * kinematics = interaction->KinePtr(); - const double pFmax = sm_utils->GetFermiMomentum(); + const double pFmax = sm_utils->GetInitialFermiMomentum(); // Now scan through kinematical variables Q2,v,kF for (int Q2_n=0; Q2_n <= N_Q2; Q2_n++) { @@ -558,7 +558,7 @@ double QELEventGeneratorSM::ComputeMaxXSec(const Interaction * interaction, cons const double logQ2min = TMath::Log(fQ2Min); const double logQ2max = TMath::Log(rQ2.max); Kinematics * kinematics = interaction->KinePtr(); - const double pFmax = sm_utils->GetFermiMomentum(); + const double pFmax = sm_utils->GetInitialFermiMomentum(); // Now scan through kinematical variables Q2,v,kF for (int Q2_n=0; Q2_n <= N_Q2; Q2_n++) { diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index a333b33a83..15e3d4708c 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -338,7 +338,11 @@ double NievesQELCCPXSec::Integral(const Interaction * in) const // let the cross section integrator do all of the work. It's smart // enough to handle free nucleon vs. nuclear targets, different // nuclear models (including the local Fermi gas model), etc. - if ( fXSecIntegrator->Id().Name() == "genie::NievesQELCCXSec" ) + if ( fXSecIntegrator->Id().Name() == "genie::NewQELXSec" ) + { + return fXSecIntegrator->Integrate(this, in); + } + else if ( fXSecIntegrator->Id().Name() == "genie::NievesQELCCXSec" ) { Target * tgt = in->InitStatePtr()->TgtPtr(); tgt->SetHitNucPosition(MaximalRadius(tgt) ); @@ -1195,10 +1199,11 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, TLorentzVector neutrinoMom = *tempNeutrino; delete tempNeutrino; TLorentzVector leptonMom = kinematics.FSLeptonP4(); - - // Calculate Coulomb corrections double ml = interaction->FSPrimLepton()->Mass(); double ml2 = ml*ml; + + + // Calculate Coulomb corrections double PlLocal = leptonMom.P(); bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); @@ -1230,19 +1235,22 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, double q0Tilde = neutrinoMom.E() - leptonMom.E(); - int nucl_pdg_ini = target.HitNucPdg(); - double kFi = fPauliBlocker->GetFermiMomentum(target, nucl_pdg_ini, r); - double kFf = fPauliBlocker->GetFermiMomentum(target, interaction->RecoilNucleonPdg(), r); + double kFi, kFf; + ModelNuclParams(interaction, r, kFi, kFf); + + double EFi = TMath::Hypot(M, kFi); double EFf = TMath::Hypot(M, kFf); + int nucl_pdg_ini = target.HitNucPdg(); bool tgtIsNucleus = target.IsNucleus(); int A = target.A(); int Z = target.Z(); int N = target.N(); bool hitNucIsProton = pdg::IsProton( nucl_pdg_ini ); + // This part of the code is strictly in accordance with the original Nieves' paper double Mi = target.Mass(); int Zf = (hitNucIsProton) ? Z - 1 : Z + 1; @@ -1374,11 +1382,12 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, double qv2 = q4.Vect().Mag2(); double qv = TMath::Sqrt(qv2); - double W1 = Wxx/2/M; - double W2 = (W00 + Wxx + v2/qv2*(Wzz - Wxx) - 2*v/qv*ReW0z)/2/M; - double W3 = -ImWxy/qv; - double W4 = M/2/qv2*(Wzz - Wxx); - double W5 = (ReW0z - v/qv*(Wzz - Wxx))/qv; + // Naumov definitions + double W1 = Wxx; + double W2 = W00 + Wxx + v2/qv2*(Wzz - Wxx) - 2*v/qv*ReW0z; + double W3 = -2*ImWxy/qv; + double W4 = (Wzz - Wxx)/qv2; + double W5 = 2*(ReW0z - v/qv*(Wzz - Wxx))/qv; double Ev = neutrinoMom.E(); double El = leptonMom.E(); @@ -1386,19 +1395,19 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, double cost = TMath::Cos( neutrinoMom.Angle(leptonMom.Vect()) ); double sint = TMath::Sqrt(1 - cost*cost); - double auxm = (El - Pl*cost)/2/M; - double auxp = (El + Pl*cost)/2/M; - double aux1m = (Pl - El*cost)/2/M; - double aux1p = (Pl + El*cost)/2/M; - double aux1 = ml2/2/M2; - double aux2 = (Ev + El)/M; + double auxm = (El - Pl*cost)/2; + double auxp = (El + Pl*cost)/2; + double aux1m = (Pl - El*cost)/2; + double aux1p = (Pl + El*cost)/2; + double aux1 = ml2/2; + double aux2 = (Ev + El); if (mod == 2) return sign*(2*aux1m*(W1 - aux1*W4) + aux1p*W2 - sign*(aux2*aux1m + aux1*cost)*W3 - aux1*cost*W5); //PL*R - if (mod == 3) return sign*ml*sint*(2*W1 - W2 -sign*Ev*W3/M - ml2*W4/M2 + El*W5/M)/2/M; //PP*R + if (mod == 3) return sign*ml*sint*(2*W1 - W2 -sign*Ev*W3 - ml2*W4 + El*W5)/2; //PP*R double R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; if (mod == 1) return R; - double extrafactor = kGF2*fCos8c2*TMath::Sq(kMw2/(kMw2 - q4.Mag2() ) )/El; + double extrafactor = kGF2*fCos8c2*TMath::Sq(kMw2/(kMw2 - q4.Mag2() ) )/El/4/kPi2; // Calculate xsec double xsec = extrafactor*R; @@ -1414,3 +1423,11 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, } //___________________________________________________________________________________ +void NievesQELCCPXSec::ModelNuclParams(const Interaction* interaction, double r, double & kFi, double & kFf) const +{ + const InitialState & init_state = interaction -> InitState(); + const Target & target = init_state.Tgt(); + int nucl_pdg_ini = target.HitNucPdg(); + kFi = fPauliBlocker->GetFermiMomentum(target, nucl_pdg_ini, r); + kFf = fPauliBlocker->GetFermiMomentum(target, interaction->RecoilNucleonPdg(), r); +} diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index f01b492610..c5aa626174 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -64,7 +64,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { bool ValidProcess (const Interaction * i) const; const TVector3 & FinalLeptonPolarization (const Interaction* i) const; double IntegratedOverMomentum (const Interaction* i, double r, int mod) const; - + void ModelNuclParams(const Interaction* interaction, double r, double & kFi, double & kFf) const; // Override the Algorithm::Configure methods to load configuration // data to private data members void Configure (const Registry & config); diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx index 86a3f3e0bf..9eb52ea863 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx @@ -24,7 +24,6 @@ #include "Framework/Utils/KineUtils.h" #include "Framework/Utils/Range1.h" #include "Framework/Numerical/GSLUtils.h" -#include "Physics/QuasiElastic/XSection/NievesQELCCPXSec.h" using namespace genie; @@ -98,13 +97,19 @@ genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::d3XSec_dElepdCosThetalepdR_E( const XSecAlgorithmI * m, const Interaction * interaction, double Rmax) : ROOT::Math::IBaseFunctionMultiDim(), fModel(m), + fXsec_model( dynamic_cast(fModel) ), fInteraction(interaction), fRmax(Rmax) { // Get kinematical parameters + AlgFactory * algf = AlgFactory::Instance(); + sm_utils = const_cast(dynamic_cast(algf->GetAlgorithm("genie::SmithMonizUtils","Default"))); const InitialState & init_state = interaction -> InitState(); fEnu = init_state.ProbeE(kRfHitNucRest); fml = interaction->FSPrimLepton()->Mass(); + fml2 = fml*fml; + sm_utils->SetInteraction(interaction); + fKinematics = fInteraction->KinePtr(); } genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::~d3XSec_dElepdCosThetalepdR_E() { @@ -116,23 +121,37 @@ unsigned int genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::NDim(void) const } double genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::DoEval(const double * xin) const { + // inputs: + // normalized Q2 from 0 to 1 + // normalized v from 0 to 1 + // normalized R from 0 to 1 // outputs: - // differential cross section [1/GeV^3] for Resonance single pion production production + // differential cross section [10^-38 cm^2] // - double El = fml + (fEnu - fml)*xin[0]; - double cost = -1 + 2*xin[1]; - double R = fRmax*xin[2]; + double R = fRmax*xin[2]; + double kFi, kFf; + fXsec_model->ModelNuclParams(fInteraction, R, kFi, kFf); + sm_utils->SetBindingEnergy(0); + sm_utils->SetInitialFermiMomentum(kFi); + sm_utils->SetFinalFermiMomentum(kFf); - double Pl = TMath::Sqrt(El*El - fml*fml); - double sint = TMath::Sqrt(1 - cost*cost); + Range1D_t rQ2 = sm_utils->Q2QES_SM_lim(); + double Q2 = (rQ2.max - rQ2.min)*xin[0] + rQ2.min; + Range1D_t rv = sm_utils->vQES_SM_lim(Q2); + double v = (rv.max - rv.min)*xin[1] + rv.min; - Kinematics * kinematics = fInteraction->KinePtr(); - kinematics->SetFSLeptonP4(Pl*sint, 0, Pl*cost, El); + double El = fEnu - v; + if (El < fml) return 0.0; + double Pl = TMath::Sqrt(El*El - fml2); + double cosTl = (El - (Q2 + fml2)/2/fEnu)/Pl; + if (cosTl < -1.0 || cosTl > 1.0 ) return 0.0; + double sinTl = TMath::Sqrt(1 - cosTl*cosTl); + fKinematics->SetFSLeptonP4(Pl*sinTl, 0, Pl*cosTl, El); - const NievesQELCCPXSec * xsec_model = dynamic_cast(fModel); - double xsec = xsec_model->IntegratedOverMomentum(fInteraction, R, 0); + double xsec = fXsec_model->IntegratedOverMomentum(fInteraction, R, 0); - double J = (fEnu - fml)*2*fRmax; + // Jacobian for transformation d/dEldcosT->d/dQ2dv + double J = (rQ2.max - rQ2.min)*(rv.max - rv.min)*fRmax/2/fEnu/Pl; return xsec*J/(1E-38 * units::cm2); } diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h index 85769d8511..4a5ce6beef 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h @@ -21,6 +21,8 @@ #include "Framework/EventGen/XSecAlgorithmI.h" #include "Physics/XSectionIntegration/XSecIntegratorI.h" #include "Physics/QuasiElastic/XSection/QELUtils.h" +#include "Physics/QuasiElastic/XSection/SmithMonizUtils.h" +#include "Physics/QuasiElastic/XSection/NievesQELCCPXSec.h" #include #include @@ -94,11 +96,14 @@ class d3XSec_dElepdCosThetalepdR_E: public ROOT::Math::IBaseFunctionMultiDim private: const XSecAlgorithmI * fModel; + const NievesQELCCPXSec * fXsec_model; const Interaction * fInteraction; + mutable SmithMonizUtils * sm_utils; + Kinematics * fKinematics; double fRmax; double fEnu; double fml; - + double fml2; }; } // gsl namespace diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index e26843596d..702b462d9f 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -221,8 +221,6 @@ double SmithMonizQELCCPXSec::d3sQES_dQ2dvdkF_SM(const Interaction * interaction) double mm_ini = m_ini*m_ini; double m_fin = interaction->RecoilNucleon()->Mass(); // Mass of final hadron or hadron system (GeV) double mm_fin = m_fin*m_fin; - double m_tar = target.Mass(); // Mass of target nucleus (GeV) - double mm_tar = m_tar*m_tar; // One of the xsec terms changes sign for antineutrinos bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); @@ -259,12 +257,12 @@ double SmithMonizQELCCPXSec::d3sQES_dQ2dvdkF_SM(const Interaction * interaction) double c2_flux = kkF*(1 - cosT_p*cosT_p)*(1 - cosT_k*cosT_k); double k1 = fVud2*mm_ini*kPi; - double k2 = mm_lep/(2*mm_tar); + double k2 = mm_lep/2; double k7 = P_lep*cosT_lep; - double P_Fermi = sm_utils->GetFermiMomentum(); + double P_Fermi = sm_utils->GetInitialFermiMomentum(); double FV_SM = 4.0*kPi/3*TMath::Power(P_Fermi, 3); - double factor = k1*(m_tar*kF/(FV_SM*qv*TMath::Sqrt(b2_flux-c2_flux)))*SmithMonizUtils::rho(P_Fermi, 0.0, kF)*(1-SmithMonizUtils::rho(P_Fermi, 0.01, pF)); + double factor = k1*kF/(FV_SM*qv*TMath::Sqrt(b2_flux-c2_flux))*SmithMonizUtils::rho(P_Fermi, 0.0, kF)*(1-SmithMonizUtils::rho(P_Fermi, 0.01, pF)); double a2 = kkF/mm_ini; double a3 = a2*cosT_p*cosT_p; @@ -275,7 +273,7 @@ double SmithMonizQELCCPXSec::d3sQES_dQ2dvdkF_SM(const Interaction * interaction) double k3 = v/qv; double k4 = (3*a3-a2)/qqv; - double k5 = (a7-a6*k3)*m_tar/m_ini; + double k5 = (a7-a6*k3)/m_ini; // Calculate the QEL form factors fFormFactors.Calculate(interaction); @@ -297,11 +295,11 @@ double SmithMonizQELCCPXSec::d3sQES_dQ2dvdkF_SM(const Interaction * interaction) double T_1 = 1.0*W_1+(a2-a3)*0.5*W_2; //Ref.[1], W_1 double T_2 = ((a2-a3)*Q2/(2*qqv)+a4-k3*(a5-k3*a3))*W_2; //Ref.[1], W_2 double T_3 = k5*W_3; //Ref.[1], W_8 - double T_4 = mm_tar*(0.5*W_2*k4+1.0*W_4/mm_ini+a6*W_5/(m_ini*qv)); //Ref.[1], W_\alpha - double T_5 = k5*W_5+m_tar*(a5/qv-v*k4)*W_2; + double T_4 = 0.5*W_2*k4+1.0*W_4/mm_ini+a6*W_5/(m_ini*qv); //Ref.[1], W_\alpha + double T_5 = k5*W_5+(a5/qv-v*k4)*W_2; - double xsec = kGF2*factor*((E_lep-k7)*(T_1+k2*T_4)/m_tar+(E_lep+k7)*T_2/(2*m_tar) - +n_NT*T_3*((E_nu+E_lep)*(E_lep-k7)/(2*mm_tar)-k2)-k2*T_5) + double xsec = kGF2*factor*((E_lep-k7)*(T_1+k2*T_4)+(E_lep+k7)*T_2/2 + +n_NT*T_3*((E_nu+E_lep)*(E_lep-k7)/2-k2)-k2*T_5) *(kMw2/(kMw2+Q2))*(kMw2/(kMw2+Q2))/E_nu/kPi; return xsec; @@ -540,7 +538,7 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio return fFinalLeptonPolarization; } - double P_Fermi = sm_utils->GetFermiMomentum(); + double P_Fermi = sm_utils->GetInitialFermiMomentum(); int d = fR.size(); double a1(0), a2(0), a3(0), a4(0), a5(0), a6(0), a7(0); diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizUtils.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizUtils.cxx index 1094461d87..9d2063f0c9 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizUtils.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizUtils.cxx @@ -146,7 +146,7 @@ void SmithMonizUtils::SetInteraction(const Interaction * interaction) // RFG is not applied for A<4 if (target.A()<4) { - E_BIN = P_Fermi = m_rnu = mm_rnu = 0; + E_BIN = kFi = m_rnu = mm_rnu = 0; return; } @@ -170,27 +170,33 @@ void SmithMonizUtils::SetInteraction(const Interaction * interaction) int Z = target.Z(); int A = target.A(); int N = A-Z; - - - // maximum value of Fermi momentum of target nucleon (GeV) + if (A < 6 || !fUseParametrization) { // look up the Fermi momentum for this Target FermiMomentumTablePool * kftp = FermiMomentumTablePool::Instance(); const FermiMomentumTable * kft = kftp->GetTable(fKFTable); - P_Fermi = kft->FindClosestKF(pdg::IonPdgCode(A, Z), nucl_pdg_ini); + kFi = kft->FindClosestKF(pdg::IonPdgCode(A, Z), nucl_pdg_ini); + kFf = kft->FindClosestKF(pdg::IonPdgCode(A, Z), nucl_pdg_fin); } else { // define the Fermi momentum for this Target - // - P_Fermi = utils::nuclear::FermiMomentumForIsoscalarNucleonParametrization(target); + double P_Fermi = utils::nuclear::FermiMomentumForIsoscalarNucleonParametrization(target); // correct the Fermi momentum for the struck nucleon - if(is_p) P_Fermi *= TMath::Power( 2.*Z/A, 1./3); + if(is_p) + { + kFi = P_Fermi*TMath::Power( 2.*Z/A, 1./3); + kFf = P_Fermi*TMath::Power( 2.*N/A, 1./3); + } else - P_Fermi *= TMath::Power( 2.*N/A, 1./3); + { + kFf = P_Fermi*TMath::Power( 2.*Z/A, 1./3); + kFi = P_Fermi*TMath::Power( 2.*N/A, 1./3); + } } + // neutrino binding energy (GeV) if (target.A() < 6 || !fUseParametrization) { @@ -221,7 +227,7 @@ double SmithMonizUtils::E_nu_thr_SM(void) const double E_min = ((m_lep + m_rnu + m_fin)*(m_lep + m_rnu + m_fin) - mm_tar)/2/m_tar; // Energy threshold of scattering on bound nucleon (Eq. (2) of Ref. 3) - double E_min2 = ((m_lep + m_fin)*(m_lep + m_fin)-mm_ini-E_BIN*E_BIN+2*E_BIN*TMath::Sqrt(mm_ini+P_Fermi*P_Fermi))/2/(TMath::Sqrt(mm_ini+P_Fermi*P_Fermi)-E_BIN+P_Fermi); + double E_min2 = ((m_lep + m_fin)*(m_lep + m_fin)-mm_ini-E_BIN*E_BIN+2*E_BIN*TMath::Sqrt(mm_ini+kFi*kFi))/2/(TMath::Sqrt(mm_ini+kFi*kFi)-E_BIN+kFi); E_min = TMath::Max(E_min, E_min2); @@ -275,11 +281,11 @@ double SmithMonizUtils::Q2lim1_SM(double Q2, double Enu) const // maximal energy transfer (see Eq. (9) of Ref.3) double nu_max = Enu*Q2/(Q2+mm_lep)-(Q2+mm_lep)/4/Enu; - double E = sqrt(P_Fermi*P_Fermi+mm_ini); - double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi; + double E = TMath::Sqrt(kFi*kFi+mm_ini); + double b = (E-E_BIN)*(E-E_BIN)-kFi*kFi; double a = 0.5*(Q2+mm_fin-b); // minimal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3), - double nu_1 = (a*(E-E_BIN)-P_Fermi*TMath::Sqrt(a*a+Q2*b))/b; + double nu_1 = (a*(E-E_BIN)-kFi*TMath::Sqrt(a*a+Q2*b))/b; return nu_1-nu_max; } @@ -290,11 +296,11 @@ double SmithMonizUtils::Q2lim2_SM(double Q2) const // minimal energy transfer for scattering on nucleus (see Eq. (7) of Ref.3) double nu_min = ((m_rnu+m_fin)*(m_rnu+m_fin)+Q2-mm_tar)/(2*m_tar); - double E = sqrt(P_Fermi*P_Fermi+mm_ini); - double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi; + double E = TMath::Sqrt(kFi*kFi+mm_ini); + double b = (E-E_BIN)*(E-E_BIN)-kFi*kFi; double a = (Q2+mm_fin-b)*0.5; // maximal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3) - double nu_2 = (a*(E-E_BIN)+P_Fermi*TMath::Sqrt(a*a+Q2*b))/b; + double nu_2 = (a*(E-E_BIN)+kFi*TMath::Sqrt(a*a+Q2*b))/b; return nu_min-nu_2; } @@ -323,7 +329,7 @@ Range1D_t SmithMonizUtils::Q2QES_SM_lim(void) const const double EPSREL = 1.0e-08; const double Precision = std::numeric_limits::epsilon(); // if the nucleus mass is less than 4 then this is a special case - if (E_BIN == 0 && P_Fermi == 0) + if (E_BIN == 0 && kFi == 0) { double s = 2*E_nu*m_ini+mm_ini; // minimal W2 for scattering on nucleus (see Eq. (6) of Ref.3) @@ -427,18 +433,18 @@ Range1D_t SmithMonizUtils::vQES_SM_lim(double Q2) const double nu_min= ((m_rnu+m_fin)*(m_rnu+m_fin)+Q2-mm_tar)/2/m_tar; // if the target is nucleon then nu_min=nu_max=(m_fin^2+Q^2-m_ini^2)/(2*m_ini) - if (E_BIN == 0 && P_Fermi == 0) + if (E_BIN == 0 && kFi == 0) return Range1D_t(nu_min, nu_min); // maximal energy transfer (see Eq. (9) of Ref.3) double nu_max = E_nu*Q2/(Q2+mm_lep)-(Q2+mm_lep)/4/E_nu; // now we find limits for bound nucleon - double E = TMath::Sqrt(P_Fermi*P_Fermi+mm_ini); - double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi; + double E = TMath::Sqrt(kFi*kFi+mm_ini); + double b = (E-E_BIN)*(E-E_BIN)-kFi*kFi; double a = (Q2+mm_fin-b)*0.5; double tmp1 = a*(E-E_BIN); - double tmp2 = P_Fermi*TMath::Sqrt(a*a+Q2*b); + double tmp2 = kFi*TMath::Sqrt(a*a+Q2*b); // minimal and maximal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3) double nu_1 = (tmp1-tmp2)/b; double nu_2 = (tmp1+tmp2)/b; @@ -462,7 +468,7 @@ double SmithMonizUtils::vQES_SM_min(double Q2_min, double Q2_max) const const double EPS = 1.0e-08; const double Delta= 1.0e-14; - if (E_BIN == 0 && P_Fermi == 0) + if (E_BIN == 0 && kFi == 0) return vQES_SM_lim(Q2_min).min; double F_MIN, Q2_0; @@ -482,7 +488,7 @@ double SmithMonizUtils::vQES_SM_max(double Q2_min, double Q2_max) const const double EPS = 1.0e-08; const double Delta= 1.0e-14; - if (E_BIN == 0 && P_Fermi == 0) + if (E_BIN == 0 && kFi == 0) return vQES_SM_lim(Q2_max).min; double F_MIN, Q2_0; @@ -501,11 +507,11 @@ double SmithMonizUtils::vlim1_SM(double Q2) const // minimal energy transfer for scattering on nucleus (see Eq. (7) of Ref.3) double nu_min = ((m_rnu+m_fin)*(m_rnu+m_fin)+Q2-mm_tar)/(2*m_tar); - double E = sqrt(P_Fermi*P_Fermi+mm_ini); - double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi; + double E = TMath::Sqrt(kFi*kFi+mm_ini); + double b = (E-E_BIN)*(E-E_BIN)-kFi*kFi; double a = (Q2+mm_fin-b)*0.5; // minimal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3) - double nu_1 = (a*(E-E_BIN)-P_Fermi*TMath::Sqrt(a*a+Q2*b))/b; + double nu_1 = (a*(E-E_BIN)-kFi*TMath::Sqrt(a*a+Q2*b))/b; nu_min= TMath::Max(nu_min,nu_1); return nu_min; } @@ -516,11 +522,11 @@ double SmithMonizUtils::vlim2_SM(double Q2) const // maximal energy transfer (see Eq. (9) of Ref.3) double nu_max = E_nu*Q2/(Q2+mm_lep)-(Q2+mm_lep)/4/E_nu; - double E = sqrt(P_Fermi*P_Fermi+mm_ini); - double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi; + double E = TMath::Sqrt(kFi*kFi+mm_ini); + double b = (E-E_BIN)*(E-E_BIN)-kFi*kFi; double a = 0.5*(Q2+mm_fin-b); // maximal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3) - double nu_2 = (a*(E-E_BIN)+P_Fermi*TMath::Sqrt(a*a+Q2*b))/b; + double nu_2 = (a*(E-E_BIN)+kFi*TMath::Sqrt(a*a+Q2*b))/b; nu_max= TMath::Min(nu_max,nu_2); return -nu_max; } @@ -532,9 +538,9 @@ Range1D_t SmithMonizUtils::kFQES_SM_lim(double Q2, double nu) const double c_f = (nu-E_BIN)/qv; double d_f = (E_BIN*E_BIN-2*nu*E_BIN-Q2+mm_ini-mm_fin)/(2*qv*m_ini); // minimal energy of initial nucleon (see Eq. (13) of Ref.3) - double Ef_min= TMath::Max(m_ini*(c_f*d_f+TMath::Sqrt(1.0-c_f*c_f+d_f*d_f))/(1.0-c_f*c_f), TMath::Sqrt(P_Fermi*P_Fermi+mm_ini)-nu); - double kF_min= P_Fermi!=0?TMath::Sqrt(TMath::Max(Ef_min*Ef_min-mm_ini,0.0)):0.; - double kF_max= P_Fermi; + double Ef_min= TMath::Max(m_ini*(c_f*d_f+TMath::Sqrt(1.0-c_f*c_f+d_f*d_f))/(1.0-c_f*c_f), TMath::Sqrt(kFi*kFi+mm_ini)-nu); + double kF_min= kFi!=0?TMath::Sqrt(TMath::Max(Ef_min*Ef_min-mm_ini,0.0)):0.; + double kF_max= kFi; Range1D_t R; if (kF_min<=kF_max) R = Range1D_t(kF_min,kF_max); @@ -632,9 +638,29 @@ double SmithMonizUtils::GetBindingEnergy(void) const return E_BIN; } //____________________________________________________________________________ -double SmithMonizUtils::GetFermiMomentum(void) const +double SmithMonizUtils::GetInitialFermiMomentum(void) const +{ + return kFi; +} +//____________________________________________________________________________ +double SmithMonizUtils::GetFinalFermiMomentum(void) const +{ + return kFf; +} +//____________________________________________________________________________ +void SmithMonizUtils::SetBindingEnergy(double val) +{ + E_BIN = val; +} +//____________________________________________________________________________ +void SmithMonizUtils::SetInitialFermiMomentum(double val) +{ + kFi = val; +} +//____________________________________________________________________________ +void SmithMonizUtils::SetFinalFermiMomentum(double val) { - return P_Fermi; + kFf = val; } //____________________________________________________________________________ double SmithMonizUtils::GetTheta_k(double v, double qv) const diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizUtils.h b/src/Physics/QuasiElastic/XSection/SmithMonizUtils.h index 73011e760e..4cbb853dcd 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizUtils.h +++ b/src/Physics/QuasiElastic/XSection/SmithMonizUtils.h @@ -58,7 +58,11 @@ class SmithMonizUtils : public Algorithm { virtual ~SmithMonizUtils(); void SetInteraction(const Interaction * i); double GetBindingEnergy(void) const; - double GetFermiMomentum(void) const; + double GetInitialFermiMomentum(void) const; + double GetFinalFermiMomentum(void) const; + void SetBindingEnergy(double val); + void SetInitialFermiMomentum(double val); + void SetFinalFermiMomentum(double val); double GetTheta_k(double v, double qv) const; double GetTheta_p(double pv, double v, double qv, double &E_p) const; double E_nu_thr_SM(void) const; @@ -138,7 +142,8 @@ double QEL_EnuMin_SM(double E_nu) const; double mm_tar; ///< Squared mass of target nucleus (GeV) double m_rnu; ///< Mass of residual nucleus (GeV) double mm_rnu; ///< Squared mass of residual nucleus (GeV) - double P_Fermi; ///< Maximum value of Fermi momentum of target nucleon (GeV) + double kFi; ///< Fermi momentum of initial nucleon + double kFf; ///< Fermi momentum of finial nucleon double E_BIN; ///< Binding energy (GeV) From e30f7dfc218c109ce7fc05a7c82728f4ae045f68 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 31 Mar 2025 19:49:36 +0300 Subject: [PATCH 50/78] restore old integrator in config --- config/NievesQELCCPXSec.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/NievesQELCCPXSec.xml b/config/NievesQELCCPXSec.xml index bbd7edf2c0..8ce8e66fae 100644 --- a/config/NievesQELCCPXSec.xml +++ b/config/NievesQELCCPXSec.xml @@ -37,7 +37,7 @@ RmaxMode string Yes Method to use to comput 1.000 - genie::NievesQELCCXSec/Default + genie::NewQELXSec/Default genie::NuclearModelMap/Default UseNuclearModel 10.0 From 0f2e9bcb733ed455c01589b76b8258a2a4286787 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 3 Apr 2025 16:07:05 +0300 Subject: [PATCH 51/78] add minimal number of evaluations --- config/HybridXSecAlgorithm.xml | 2 -- config/SmithMonizQELCCXSec.xml | 16 +++++----- .../XSection/NievesQELCCPXSec.cxx | 7 +++-- .../XSection/SmithMonizQELCCXSec.cxx | 29 ++++++++++++------- .../XSection/SmithMonizQELCCXSec.h | 1 + .../QuasiElastic/XSection/SmithMonizUtils.h | 4 +-- 6 files changed, 33 insertions(+), 26 deletions(-) diff --git a/config/HybridXSecAlgorithm.xml b/config/HybridXSecAlgorithm.xml index bb8895f205..1aa1ed2fc8 100644 --- a/config/HybridXSecAlgorithm.xml +++ b/config/HybridXSecAlgorithm.xml @@ -271,7 +271,6 @@ XSecAlg@Interaction=XX alg Yes Algorithm to use to handle interactio - genie::SmithMonizQELCCPXSec/Dipole @@ -289,7 +288,6 @@ XSecAlg@Interaction=XX alg Yes Algorithm to use to handle interactio - genie::SmithMonizQELCCPXSec/RunningMA diff --git a/config/SmithMonizQELCCXSec.xml b/config/SmithMonizQELCCXSec.xml index 9b44299aed..5542e83025 100644 --- a/config/SmithMonizQELCCXSec.xml +++ b/config/SmithMonizQELCCXSec.xml @@ -11,24 +11,26 @@ Name Type Optional Comment gsl-integration-type string Yes name of GSL 1D numerical integrator gauss gsl-max-size-of-subintervals int Yes GSL maximum number of sub-intervals 40000 for 1D integrator -gsl-relative-tolerance double Yes GSL max evaluations for 1D integrator 1e-3 +gsl-relative-tolerance double Yes GSL max evaluations for 1D integrator 1e-5 gsl-rule int Yes GSL Gauss-Kronrod integration rule 3 (only for GSL 1D adaptive type) gsl-integration-type-2D string Yes name of GSL 2D numerical integrator adaptive -gsl-max-eval int Yes required relative tolerance (error) 1000000000 - for 2D integrator -gsl-relative-tolerance-2D double Yes GSL max evaluations for 2D integrator 1e-7 +gsl-max-eval int Yes GSL max evaluations for 2D integrator 100000 +gsl-min-eval int Yes GSL min evaluations for 2D integrator 7500 +gsl-relative-tolerance-2D double Yes required relative tolerance (error) + for 2D integrator 1e-5 ..................................................................................................... --> gauss 40000 - 1e-3 + 1e-5 3 adaptive - 1000000000 - 1e-4 + 100000 + 7500 + 1e-5 diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 15e3d4708c..8daf39f8dd 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -398,9 +398,10 @@ void NievesQELCCPXSec::Configure(string config) void NievesQELCCPXSec::LoadConfig(void) { bool good_config = true ; - double thc; - GetParam( "CabibboAngle", thc ) ; - fCos8c2 = TMath::Power(TMath::Cos(thc), 2); + + double Vud; + GetParam( "CKM-Vud", Vud ) ; + fCos8c2 = TMath::Power( Vud, 2 ); // Do precise calculation of lepton polarization GetParamDef( "PreciseLeptonPol", fIsPreciseLeptonPolarization, false ) ; diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCXSec.cxx index 63d141bf14..73c360ebbe 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCXSec.cxx @@ -92,7 +92,7 @@ double SmithMonizQELCCXSec::Integrate( { Interaction * interaction = new Interaction(*in); sm_utils->SetInteraction(in); - if (interaction->InitState().ProbeE(kRfLab)E_nu_thr_SM()) + if (interaction->InitState().ProbeE(kRfLab) < sm_utils->E_nu_thr_SM()) { return 0; } @@ -100,18 +100,22 @@ double SmithMonizQELCCXSec::Integrate( interaction->SetBit(kISkipKinematicChk); double xsec = 0; + utils::gsl::d2Xsec_dQ2dv func(model, interaction); + ROOT::Math::IntegrationMultiDim::Type ig_type = utils::gsl::IntegrationNDimTypeFromString(fGSLIntgType2D); + ROOT::Math::IntegratorMultiDim ig(ig_type, 0, fGSLRelTol2D, fGSLMaxEval); + if (ig_type == ROOT::Math::IntegrationMultiDim::kADAPTIVE) + { + ROOT::Math::AdaptiveIntegratorMultiDim * cast = dynamic_cast( ig.GetIntegrator() ); + assert(cast); + cast->SetMinPts(fGSLMinEval); + } + ig.SetFunction(func); - ROOT::Math::IBaseFunctionMultiDim * func = new utils::gsl::d2Xsec_dQ2dv(model, interaction); double kine_min[2] = { 0, 0}; double kine_max[2] = { 1, 1}; - ROOT::Math::IntegrationMultiDim::Type ig_type = utils::gsl::IntegrationNDimTypeFromString(fGSLIntgType2D); - - double abstol = 0; //We mostly care about relative tolerance. - ROOT::Math::IntegratorMultiDim ig(*func, ig_type, abstol, fGSLRelTol2D, fGSLMaxEval); + xsec = ig.Integral(kine_min, kine_max)*(1E-38 * units::cm2); - xsec = ig.Integral(kine_min, kine_max) * (1E-38 * units::cm2); - delete func; delete interaction; return xsec; @@ -143,7 +147,7 @@ void SmithMonizQELCCXSec::LoadConfig(void) // Get GSL integration type & relative tolerance GetParamDef( "gsl-integration-type", fGSLIntgType, string("gauss") ); - GetParamDef( "gsl-relative-tolerance", fGSLRelTol, 1e-3 ); + GetParamDef( "gsl-relative-tolerance", fGSLRelTol, 1e-5 ); int max_size_of_subintervals; GetParamDef( "gsl-max-size-of-subintervals", max_size_of_subintervals, 40000); fGSLMaxSizeOfSubintervals = (unsigned int) max_size_of_subintervals; @@ -152,8 +156,11 @@ void SmithMonizQELCCXSec::LoadConfig(void) fGSLRule = (unsigned int) rule; if (fGSLRule>6) fGSLRule=3; GetParamDef( "gsl-integration-type-2D", fGSLIntgType2D, string("adaptive") ); - GetParamDef( "gsl-relative-tolerance-2D", fGSLRelTol2D, 1e-7); - GetParamDef( "gsl-max-eval", fGSLMaxEval, 1000000000); + GetParamDef( "gsl-relative-tolerance-2D", fGSLRelTol2D, 1e-5); + GetParamDef( "gsl-max-eval", fGSLMaxEval, 100000); + int min; + GetParamDef( "gsl-min-eval", min, 7500 ) ; + fGSLMinEval = static_cast( min ); sm_utils = const_cast( dynamic_cast( diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCXSec.h b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCXSec.h index 107725cd83..856a7e01f7 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCXSec.h +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCXSec.h @@ -33,6 +33,7 @@ #define _SMITH_MONIZ_QEL_XSEC_H_ #include +#include #include "Physics/XSectionIntegration/XSecIntegratorI.h" #include "Physics/QuasiElastic/XSection/SmithMonizUtils.h" diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizUtils.h b/src/Physics/QuasiElastic/XSection/SmithMonizUtils.h index 4cbb853dcd..ed70bacf65 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizUtils.h +++ b/src/Physics/QuasiElastic/XSection/SmithMonizUtils.h @@ -77,8 +77,6 @@ class SmithMonizUtils : public Algorithm { //! to build the fragmentation function from configuration data void Configure(const Registry & config); void Configure(string config); - -double QEL_EnuMin_SM(double E_nu) const; private: class Functor1D @@ -115,7 +113,7 @@ double QEL_EnuMin_SM(double E_nu) const; }; void LoadConfig (void); - // double QEL_EnuMin_SM(double E_nu) const; + double QEL_EnuMin_SM(double E_nu) const; double Q2lim1_SM(double Q2, double Enu) const; double Q2lim2_SM(double Q2) const; void DMINFC(Functor1D &F, double A,double B, double EPS, double DELTA, double &X, double &Y, bool &LLM) const; From 7180d084e3aa347b100f4aa943295a2f69d9d87d Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 3 Apr 2025 17:22:02 +0300 Subject: [PATCH 52/78] a few cosmetics --- config/SmithMonizQELCCXSec.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/SmithMonizQELCCXSec.xml b/config/SmithMonizQELCCXSec.xml index 5542e83025..e6b9d55fda 100644 --- a/config/SmithMonizQELCCXSec.xml +++ b/config/SmithMonizQELCCXSec.xml @@ -29,7 +29,7 @@ gsl-relative-tolerance-2D double Yes required relative tolerance (er 3 adaptive 100000 - 7500 + 7500 1e-5 From 120c3cbcda098483ca044af292d1f4a59717046d Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Fri, 4 Apr 2025 09:57:55 +0300 Subject: [PATCH 53/78] a cosmetic fix --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 8daf39f8dd..80b66f5eba 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1408,6 +1408,7 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, double R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; if (mod == 1) return R; + // factor kPi2 comes from above definition of b; coloumb corrections factor also is taken into account double extrafactor = kGF2*fCos8c2*TMath::Sq(kMw2/(kMw2 - q4.Mag2() ) )/El/4/kPi2; // Calculate xsec From a468f2a12b64b90901faaa8f91db08655adb3fa4 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Fri, 4 Apr 2025 23:52:08 +0300 Subject: [PATCH 54/78] read 1d integration parameters in LoadConfig --- .../QuasiElastic/XSection/NievesQELCCPXSec.cxx | 15 ++++++++++----- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 4 ++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 80b66f5eba..2d1ab0ca93 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -513,6 +513,14 @@ void NievesQELCCPXSec::LoadConfig(void) // Scaling factor for the Coulomb potential GetParamDef( "CoulombScale", fCoulombScale, 1.0 ); + + + AlgFactory * algf = AlgFactory::Instance(); + NievesQELCCXSec* nvi = dynamic_cast(algf->AdoptAlgorithm("genie::NievesQELCCXSec", "Default")); + f1DimIntgType = nvi->Get1DimIntgType(); + f1DimRelTol = nvi->Get1DimRelTol(); + f1DimMaxEval = nvi->Get1DimMaxEval(); + } //___________________________________________________________________________ void NievesQELCCPXSec::CNCTCLimUcalc(TLorentzVector qTildeP4, @@ -825,11 +833,8 @@ double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const int Z = target->Z(); ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELvcrIntegrand(Rcurr,A,Z); - const NievesQELCCXSec * integrator = dynamic_cast(fXSecIntegrator); - ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( integrator->Get1DimIntgType() ); - double reltol = integrator->Get1DimRelTol(); - unsigned int nmaxeval = integrator->Get1DimMaxEval(); - ROOT::Math::Integrator ig(*func, ig_type, 0, reltol, nmaxeval); + ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( f1DimIntgType ); + ROOT::Math::Integrator ig(*func, ig_type, 0, f1DimRelTol, f1DimMaxEval); double result = ig.Integral(0, Rmax); delete func; diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index c5aa626174..62d8b37dc9 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -77,6 +77,10 @@ class NievesQELCCPXSec : public XSecAlgorithmI { const QELFormFactorsModelI * fFormFactorsModel; ///< const XSecIntegratorI * fXSecIntegrator; ///< double fCos8c2; ///< cos^2(cabibbo angle) + + string f1DimIntgType; ///< Type of 1D integrator from NievesQELCCXSec config + double f1DimRelTol; ///< Relative tolerance for 1D integrator from NievesQELCCXSec config + unsigned int f1DimMaxEval; ///< Number of max evaluations for 1D integrator from NievesQELCCXSec config double fXSecCCScale; ///< external xsec scaling factor for CC double fXSecNCScale; ///< external xsec scaling factor for NC From 6a68015603e10ee400696f35539301eef05aa8b0 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 6 Apr 2025 12:07:33 +0300 Subject: [PATCH 55/78] add energy threshold check --- src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx index 9eb52ea863..2471fa12fa 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx @@ -43,6 +43,8 @@ NievesQELCCXSec::NievesQELCCXSec(std::string config) : XSecIntegratorI("genie::N //____________________________________________________________________________ double NievesQELCCXSec::Integrate(const XSecAlgorithmI* model, const Interaction* in) const { + if(! model->ValidProcess(in)) return 0; + Target * tgt = in->InitStatePtr()->TgtPtr(); double Rmax = tgt->HitNucPosition(); utils::gsl::d3XSec_dElepdCosThetalepdR_E func(model, in, Rmax ) ; @@ -135,6 +137,8 @@ double genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::DoEval(const double * xi sm_utils->SetInitialFermiMomentum(kFi); sm_utils->SetFinalFermiMomentum(kFf); + if (fEnu < sm_utils->E_nu_thr_SM()) return 0; + Range1D_t rQ2 = sm_utils->Q2QES_SM_lim(); double Q2 = (rQ2.max - rQ2.min)*xin[0] + rQ2.min; Range1D_t rv = sm_utils->vQES_SM_lim(Q2); From 6a273ba9c44b139e5396be930c002de5c2ff6a9b Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sat, 12 Apr 2025 20:59:16 +0300 Subject: [PATCH 56/78] add transform fm^3->GeV^-3 --- config/NievesQELCCXSec.xml | 8 ++-- .../XSection/NievesQELCCPXSec.cxx | 42 +++++++++---------- .../QuasiElastic/XSection/NievesQELCCXSec.cxx | 3 +- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/config/NievesQELCCXSec.xml b/config/NievesQELCCXSec.xml index 40ec948558..0a7b211b13 100644 --- a/config/NievesQELCCXSec.xml +++ b/config/NievesQELCCXSec.xml @@ -23,13 +23,13 @@ gsl-1dim-relative-tolerance double Yes relative tolerance of integrat adaptive - 1e-5 + 1e-4 7500 - 100000 + 1000000 adaptive - 1e-5 - 100000 + 1e-4 + 1000000 diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 2d1ab0ca93..12c3a6c904 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -636,24 +636,27 @@ std::complex NievesQELCCPXSec::LindhardNuclear(double q0, double dq, dou if (fLindhardFunction == "CJP46") { // Ref.4, Eqs.27-29 - double v = q0*M/kF/kF; - double q = dq/kF; - double q2 = q*q; - double auxm = v/q - q/2; - double auxp = v/q + q/2; - double auxm2 = auxm*auxm; - double auxp2 = auxp*auxp; - double ReUnuc = M*kF/kPi2*(-1 + ( (1 - auxm2)*TMath::Log( TMath::Abs( (auxm + 1)/(auxm - 1) ) ) - - (1 - auxp2)*TMath::Log( TMath::Abs( (auxp + 1)/(auxp - 1) ) ) )/2/q); - - double uplim = q + q2/2; - double lowlim = q - q2/2; + double ReUnuc = 0; double ImUnuc = 0; - if ((q > 2 && uplim >= v && v >= -lowlim ) || (q < 2 && uplim >= v && v >= lowlim) ) - ImUnuc = -M*kF*(1 - auxm2 )/2/kPi/q; - else if (q < 2 && 0 <= v && v <= lowlim) - ImUnuc = -M*kF*v/kPi/q; + if (kF != 0) + { + double v = q0*M/kF/kF; + double q = dq/kF; + double q2 = q*q; + double auxm = v/q - q/2; + double auxp = v/q + q/2; + double auxm2 = auxm*auxm; + double auxp2 = auxp*auxp; + ReUnuc = M*kF/kPi2*(-1 + ( (1 - auxm2)*TMath::Log( TMath::Abs( (auxm + 1)/(auxm - 1) ) ) - + (1 - auxp2)*TMath::Log( TMath::Abs( (auxp + 1)/(auxp - 1) ) ) )/2/q); + double uplim = q + q2/2; + double lowlim = q - q2/2; + if ((q > 2 && uplim >= v && v >= -lowlim ) || (q < 2 && uplim >= v && v >= lowlim) ) + ImUnuc = -M*kF*(1 - auxm2 )/2/kPi/q; + else if (q < 2 && 0 <= v && v <= lowlim) + ImUnuc = -M*kF*v/kPi/q; + } return std::complex(ReUnuc, ImUnuc); } @@ -697,6 +700,7 @@ std::complex NievesQELCCPXSec::LindhardDelta(double q0, double dq, doubl if (fLindhardFunction == "CJP46") { + if (kF == 0) return 0.*1i; // Ref.4, Eq.30-31 const double fs2 = 4*kPi*0.36; if(s > aux3) @@ -1420,12 +1424,6 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, double xsec = extrafactor*R; xsec *= fXSecCCScale ; - // Number of scattering centers in the target - int nucpdgc = target.HitNucPdg(); - int NNucl = (pdg::IsProton(nucpdgc)) ? target.Z() : target.N(); - - xsec *= NNucl; // nuclear xsec - return xsec; } diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx index 2471fa12fa..dfecc6c1f2 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx @@ -60,6 +60,7 @@ double NievesQELCCXSec::Integrate(const XSecAlgorithmI* model, const Interaction double kine_min[3] = { 0., 0., 0.}; double kine_max[3] = { 1., 1., 1.}; double xsec = ig.Integral(kine_min, kine_max)*(1E-38 * units::cm2); + if (ig.Status() != 0) std::cout << "Status = " << ig.Status() << "\n"; return xsec; } //____________________________________________________________________________ @@ -157,7 +158,7 @@ double genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::DoEval(const double * xi // Jacobian for transformation d/dEldcosT->d/dQ2dv double J = (rQ2.max - rQ2.min)*(rv.max - rv.min)*fRmax/2/fEnu/Pl; - return xsec*J/(1E-38 * units::cm2); + return xsec*J*units::fm3/(1E-38 * units::cm2); } ROOT::Math::IBaseFunctionMultiDim * genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::Clone() const From 383c82f3cfdf14dccd6dc78cf71fa6f6c0fbdca0 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 13 Apr 2025 19:23:48 +0300 Subject: [PATCH 57/78] change default params --- config/NievesQELCCPXSec.xml | 2 +- config/NievesQELCCXSec.xml | 8 ++++---- src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx | 9 ++++----- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/config/NievesQELCCPXSec.xml b/config/NievesQELCCPXSec.xml index 8ce8e66fae..32e84b68c4 100644 --- a/config/NievesQELCCPXSec.xml +++ b/config/NievesQELCCPXSec.xml @@ -52,7 +52,7 @@ RmaxMode string Yes Method to use to comput VertexGenerator true - CJP46 + OriginalByNieves diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx index dfecc6c1f2..e5c14a85cb 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx @@ -60,7 +60,6 @@ double NievesQELCCXSec::Integrate(const XSecAlgorithmI* model, const Interaction double kine_min[3] = { 0., 0., 0.}; double kine_max[3] = { 1., 1., 1.}; double xsec = ig.Integral(kine_min, kine_max)*(1E-38 * units::cm2); - if (ig.Status() != 0) std::cout << "Status = " << ig.Status() << "\n"; return xsec; } //____________________________________________________________________________ @@ -80,17 +79,17 @@ void NievesQELCCXSec::LoadConfig(void) { // Get GSL integration type & relative tolerance GetParamDef( "gsl-integration-type", fGSLIntgType, std::string("adaptive") ); - GetParamDef( "gsl-relative-tolerance", fGSLRelTol, 1e-5 ); + GetParamDef( "gsl-relative-tolerance", fGSLRelTol, 1e-4 ); int max; - GetParamDef( "gsl-max-eval", max, 100000 ); + GetParamDef( "gsl-max-eval", max, 1000000 ); fGSLMaxEval = static_cast( max ); int min; GetParamDef( "gsl-min-eval", min, 7500 ) ; fGSLMinEval = static_cast( min ); GetParamDef( "gsl-1dim-integration-type", fGSL1DimIntgType, std::string("adaptive") ); - GetParamDef( "gsl-1dim-relative-tolerance", fGSL1DimRelTol, 1e-5 ); - GetParamDef( "gsl-1dim-max-eval", max, 100000 ); + GetParamDef( "gsl-1dim-relative-tolerance", fGSL1DimRelTol, 1e-4 ); + GetParamDef( "gsl-1dim-max-eval", max, 1000000 ); fGSL1DimMaxEval = static_cast( max ); } //____________________________________________________________________________ From 799783c95a1ae680b94b7bbe8412c70e2826d86d Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 14 Apr 2025 15:39:15 +0300 Subject: [PATCH 58/78] fix an integration issue --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 12c3a6c904..adc027c63e 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1138,14 +1138,10 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i double Rmax = MaximalRadius(&target); if (Rmax <= 0) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - - const NievesQELCCXSec * integrator = dynamic_cast(fXSecIntegrator); - ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( integrator->Get1DimIntgType() ); - double reltol = integrator->Get1DimRelTol(); - unsigned int nmaxeval = integrator->Get1DimMaxEval(); + ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( f1DimIntgType ); ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 1); - ROOT::Math::Integrator ig(*func, ig_type, 0, reltol, nmaxeval); + ROOT::Math::Integrator ig(*func, ig_type, 0, f1DimRelTol, f1DimMaxEval); double R = ig.Integral(0, Rmax); delete func; if (R == 0) From 6f171a74493c3e2fa6412481ee5e58f9a249ff20 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 10 Jun 2025 16:15:16 +0300 Subject: [PATCH 59/78] add kinematics check for smith-monitz; make nuclear models hybrids - update configs according to this --- config/HybridXSecAlgorithm.xml | 210 +++++++++++++++++- config/LwlynSmithQELCCPXSec.xml | 11 +- config/NievesQELCCPXSec.xml | 12 +- .../XSection/SmithMonizQELCCPXSec.cxx | 31 +++ 4 files changed, 253 insertions(+), 11 deletions(-) diff --git a/config/HybridXSecAlgorithm.xml b/config/HybridXSecAlgorithm.xml index 1aa1ed2fc8..9147f91989 100644 --- a/config/HybridXSecAlgorithm.xml +++ b/config/HybridXSecAlgorithm.xml @@ -270,7 +270,7 @@ XSecAlg@Interaction=XX alg Yes Algorithm to use to handle interactio genie::RosenbluthPXSec/Default - + genie::SmithMonizQELCCPXSec/Dipole @@ -287,7 +287,24 @@ XSecAlg@Interaction=XX alg Yes Algorithm to use to handle interactio genie::LwlynSmithQELCCPXSec/Dipole - + + genie::SmithMonizQELCCPXSec/ZExp + + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + + genie::SmithMonizQELCCPXSec/RunningMA @@ -303,6 +320,195 @@ XSecAlg@Interaction=XX alg Yes Algorithm to use to handle interactio genie::LwlynSmithQELCCPXSec/Dipole + + + genie::SmithMonizQELCCPXSec/RunningMA + + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + + + genie::NievesQELCCPXSec/IsoscalarDipole + + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + + + genie::NievesQELCCPXSec/IsoscalarDipoleNoRPA + + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + + + genie::NievesQELCCPXSec/IsoscalarDipoleNoCoulomb + + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + + + genie::NievesQELCCPXSec/IsoscalarDipoleNoPauli + + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + genie::LwlynSmithQELCCPXSec/IsoscalarDipole + + + + genie::NievesQELCCPXSec/IsoscalarIsoscalarZExp + + + genie::LwlynSmithQELCCPXSec/IsoscalarZExp + + genie::LwlynSmithQELCCPXSec/IsoscalarZExp + + genie::LwlynSmithQELCCPXSec/IsoscalarZExp + + genie::LwlynSmithQELCCPXSec/IsoscalarZExp + + genie::LwlynSmithQELCCPXSec/IsoscalarZExp + + genie::LwlynSmithQELCCPXSec/IsoscalarZExp + + + + genie::NievesQELCCPXSec/Dipole + + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + + + genie::NievesQELCCPXSec/DipoleNoRPA + + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + + + genie::NievesQELCCPXSec/DipoleNoCoulomb + + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + + + genie::NievesQELCCPXSec/DipoleNoPauli + + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + genie::LwlynSmithQELCCPXSec/Dipole + + + + genie::NievesQELCCPXSec/ZExp + + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + genie::LwlynSmithQELCCPXSec/ZExp + + + diff --git a/config/LwlynSmithQELCCPXSec.xml b/config/LwlynSmithQELCCPXSec.xml index d6a28deec0..6b0dc0f45a 100644 --- a/config/LwlynSmithQELCCPXSec.xml +++ b/config/LwlynSmithQELCCPXSec.xml @@ -48,6 +48,10 @@ IntegralNuclearInfluenceCutoffEnergy double No genie::LwlynSmithFFCC/Dipole + + + genie::LwlynSmithIsoFFCC/Dipole + @@ -58,12 +62,15 @@ IntegralNuclearInfluenceCutoffEnergy double No genie::LwlynSmithFFCC/ZExp - + + + + genie::LwlynSmithIsoFFCC/ZExp + genie::LwlynSmithFFCC/RunningMA - diff --git a/config/NievesQELCCPXSec.xml b/config/NievesQELCCPXSec.xml index 32e84b68c4..6e552502a7 100644 --- a/config/NievesQELCCPXSec.xml +++ b/config/NievesQELCCPXSec.xml @@ -60,30 +60,29 @@ RmaxMode string Yes Method to use to comput - + genie::LwlynSmithIsoFFCC/Dipole - + genie::LwlynSmithIsoFFCC/Dipole false - + genie::LwlynSmithIsoFFCC/Dipole false - + genie::LwlynSmithIsoFFCC/Dipole false - + genie::LwlynSmithIsoFFCC/ZExp - diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 702b462d9f..4cf9ca85ef 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -95,11 +95,42 @@ double SmithMonizQELCCPXSec::XSec( if(kpsdim == 2) { + if(!interaction->TestBit(kISkipProcessChk)) + { + sm_utils->SetInteraction(interaction); + const InitialState & init_state = interaction->InitState(); + double E_nu = init_state.ProbeE(kRfLab); + if ( E_nu < sm_utils->E_nu_thr_SM() ) return 0.; + const Kinematics & kinematics = interaction -> Kine(); + double Q2 = kinematics.GetKV(kKVQ2); + Range1D_t rQ2 = sm_utils->Q2QES_SM_lim(); + if (Q2 < rQ2.min || Q2 > rQ2.max) return 0.; + Range1D_t rv = sm_utils->vQES_SM_lim(Q2); + double v = kinematics.GetKV(kKVv); + if (v < rv.min || v > rv.max) return 0.; + } xsec = this->d2sQES_dQ2dv_SM(interaction); } if(kpsdim == 3) { + if(!interaction->TestBit(kISkipProcessChk)) + { + sm_utils->SetInteraction(interaction); + const InitialState & init_state = interaction->InitState(); + double E_nu = init_state.ProbeE(kRfLab); + if ( E_nu < sm_utils->E_nu_thr_SM() ) return 0.; + const Kinematics & kinematics = interaction -> Kine(); + double Q2 = kinematics.GetKV(kKVQ2); + Range1D_t rQ2 = sm_utils->Q2QES_SM_lim(); + if (Q2 < rQ2.min || Q2 > rQ2.max) return 0.; + Range1D_t rv = sm_utils->vQES_SM_lim(Q2); + double v = kinematics.GetKV(kKVv); + if (v < rv.min || v > rv.max) return 0.; + Range1D_t rkF = sm_utils->kFQES_SM_lim(Q2, v); + double kF = kinematics.GetKV(kKVPn); + if (kF < rkF.min || kF > rkF.max) return 0.; + } xsec = this->d3sQES_dQ2dvdkF_SM(interaction); } From 7217f910b61c253e535ec155292ad0848771a3d3 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 10 Jun 2025 21:17:00 +0300 Subject: [PATCH 60/78] fix CalculatePolarizationVectorWithStructureFunctions method --- src/Physics/Common/PrimaryLeptonUtils.cxx | 21 +++++++++---------- src/Physics/Common/PrimaryLeptonUtils.h | 1 - .../XSection/LwlynSmithQELCCPXSec.cxx | 3 ++- .../Strange/XSection/PaisQELLambdaPXSec.cxx | 3 +-- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index d8ae533e06..215d297cfe 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -73,19 +73,19 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( { double k[4], l[4], s[4], eskl[4]; std::complex jp[4], jm[4]; - + // k_\mu k[0] = neutrinoMom.E(); k[1] = -neutrinoMom.Px(); k[2] = -neutrinoMom.Py(); k[3] = -neutrinoMom.Pz(); - + // l_\mu l[0] = leptonMom.E(); l[1] = -leptonMom.Px(); l[2] = -leptonMom.Py(); l[3] = -leptonMom.Pz(); double ml = leptonMom.M(); - + // s_\mu s[0] = leptonMom.P()/ml; s[1] = -leptonMom.Vect().Unit().X()*leptonMom.E()/ml; s[2] = -leptonMom.Vect().Unit().Y()*leptonMom.E()/ml; @@ -173,9 +173,9 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); TVector3 Py = Pz.Cross(Px); polarization = PT*Px + PP*Py + PL*Pz; -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << "\n"; -// std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + //std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << "\n"; + //std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; } //____________________________________________________________________________ void genie::utils::CalculatePolarizationVectorWithStructureFunctions( @@ -185,7 +185,6 @@ void genie::utils::CalculatePolarizationVectorWithStructureFunctions( const TLorentzVector & inNucleonMom, const TLorentzVector & q4, bool isLeftPolarized, - double M, double W1, double W2, double W3, @@ -194,7 +193,7 @@ void genie::utils::CalculatePolarizationVectorWithStructureFunctions( double W6 ) { - double M2 = M*M; + double M2 = inNucleonMom.M2(); double p[4], q[4], epq[4][4]; p[0] = inNucleonMom.E(); p[1] = inNucleonMom.Px(); @@ -290,9 +289,9 @@ void genie::utils::CalculatePolarizationVectorInTargetRestFrame( TVector3 Px = neutrinoMomTRF3.Cross(leptonMomTRF3).Unit(); TVector3 Py = Pz.Cross(Px); polarization = PT*Px + PP*Py + PL*Pz; -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << ", R = " << R << "\n"; -// std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; + //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; + //std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << ", R = " << R << "\n"; + //std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; } //____________________________________________________________________________ diff --git a/src/Physics/Common/PrimaryLeptonUtils.h b/src/Physics/Common/PrimaryLeptonUtils.h index c79d420d03..723b1ff338 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.h +++ b/src/Physics/Common/PrimaryLeptonUtils.h @@ -49,7 +49,6 @@ namespace utils { const TLorentzVector & inNucleonMom, const TLorentzVector & q4, bool isLeftPolarized, - double M, double W1, double W2, double W3, diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index c8bbcd1468..360fc37a83 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -627,9 +627,10 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio inNucleonMom, qP4, is_neutrino, - M, W1,W2,W3,W4,W5,0); + W1,W2,W3,W4,W5,0); // std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// fFinalLeptonPolarization.Print(); // std::cout << fFinalLeptonPolarization.Mag() << "\n"; // std::cout << "LW@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx index 454ccab27d..db3fffd843 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx @@ -288,7 +288,6 @@ const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* double Mm = Mf - Mi; double Mm2 = Mm*Mm; double Mp2 = Mp*Mp; - double M = 0.5*Mp; //Powers of Form Factors double FA2 = FA*FA; @@ -305,7 +304,7 @@ const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* inNucleonMom, qP4, is_neutrino, - M, W1,W2,W3,0,0,0); + W1,W2,W3,0,0,0); // std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; From b2a51b3c6c3546de54f790358abcdeb86fccaaf5 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Wed, 11 Jun 2025 22:53:19 +0300 Subject: [PATCH 61/78] comment out output --- src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 633f7123c5..5e682761ff 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -1208,9 +1208,9 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int M, W1,W2,W3,W4,W5,0); - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "SU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << fFinalLeptonPolarization.Mag() << "\n"; +// std::cout << "SU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } From 53227d905059e89bf7ca5273040505102abbb323 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Wed, 11 Jun 2025 23:34:11 +0300 Subject: [PATCH 62/78] comment out output --- .../Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx | 6 +++--- src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index 5b0f5a1024..5bfc0b0ba4 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -756,9 +756,9 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int M, W1,W2,W3,W4,W5,0); - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "NVMEC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << fFinalLeptonPolarization.Mag() << "\n"; +// std::cout << "NVMEC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index 9561c13424..a73c3325f4 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -598,9 +598,9 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int M, W1,W2,W3,W4,W5,0); - std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - std::cout << fFinalLeptonPolarization.Mag() << "\n"; - std::cout << "SU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; +// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; +// std::cout << fFinalLeptonPolarization.Mag() << "\n"; +// std::cout << "SU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } From 1ec3aaa092080e9b657453ceee28d70b509ecc0a Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 12 Jun 2025 08:21:19 +0300 Subject: [PATCH 63/78] add SuSAQEL to Messenger configs --- config/Messenger.xml | 1 + config/Messenger_inuke_verbose.xml | 1 + config/Messenger_laconic.xml | 1 + config/Messenger_rambling.xml | 1 + config/Messenger_whisper.xml | 1 + 5 files changed, 5 insertions(+) diff --git a/config/Messenger.xml b/config/Messenger.xml index 1cfd3ce03c..d23d5badf0 100644 --- a/config/Messenger.xml +++ b/config/Messenger.xml @@ -154,6 +154,7 @@ NOTICE INFO NOTICE + NOTICE WARN NOTICE WARN diff --git a/config/Messenger_inuke_verbose.xml b/config/Messenger_inuke_verbose.xml index e53bb4f358..bb37d6487a 100644 --- a/config/Messenger_inuke_verbose.xml +++ b/config/Messenger_inuke_verbose.xml @@ -130,6 +130,7 @@ NOTICE INFO NOTICE + NOTICE NOTICE NOTICE NOTICE diff --git a/config/Messenger_laconic.xml b/config/Messenger_laconic.xml index 1cfaf6590e..e54b8878c8 100644 --- a/config/Messenger_laconic.xml +++ b/config/Messenger_laconic.xml @@ -148,6 +148,7 @@ WARN WARN WARN + WARN WARN WARN WARN diff --git a/config/Messenger_rambling.xml b/config/Messenger_rambling.xml index e591abc5e9..64024fca5c 100644 --- a/config/Messenger_rambling.xml +++ b/config/Messenger_rambling.xml @@ -147,6 +147,7 @@ NOTICE INFO NOTICE + NOTICE NOTICE NOTICE NOTICE diff --git a/config/Messenger_whisper.xml b/config/Messenger_whisper.xml index c8d945a861..f10c5fbc92 100644 --- a/config/Messenger_whisper.xml +++ b/config/Messenger_whisper.xml @@ -146,6 +146,7 @@ FATAL FATAL FATAL + FATAL FATAL FATAL FATAL From 2b49c67a8917272c70c1e6b813f2b82291e555a0 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 17 Jun 2025 11:54:45 +0300 Subject: [PATCH 64/78] small fix --- src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 5e682761ff..2766d8775a 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -684,7 +684,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int int target_pdg = tgt.Pdg(); int probe_pdg = interaction->InitState().ProbePdg(); - bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + bool is_neutrino = pdg::IsNeutrino(probe_pdg); + bool is_antineutrino = pdg::IsAntiNeutrino(probe_pdg); const double M = 1; // the polarization doesn't depend on mass of target in target rest frame @@ -738,7 +739,7 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int HadronTensorType_t tensor_type_crpa = kHT_Undefined; HadronTensorType_t tensor_type_blen = kHT_Undefined; - if ( pdg::IsNeutrino(probe_pdg) ) + if ( is_neutrino ) { tensor_type_susa = kHT_QE_Full; tensor_type_blen = kHT_QE_SuSABlend; @@ -771,7 +772,7 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int else tensor_type_crpa = kHT_QE_HFPW_High; } } - else if ( pdg::IsAntiNeutrino(probe_pdg) ) + else if ( is_antineutrino ) { // SuSA implementation doesn't accoutn for asymmetry between protons // and neutrons. In general this is a small effect. From a3ed1e44a33c36bb65ea797e141f04a92963c05b Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 13 Jul 2025 05:45:52 +0300 Subject: [PATCH 65/78] add new method --- .../QuasiElastic/XSection/NievesQELCCPXSec.cxx | 16 ++++++++++++++++ .../QuasiElastic/XSection/NievesQELCCPXSec.h | 1 + 2 files changed, 17 insertions(+) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index adc027c63e..503526ebec 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1424,6 +1424,22 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, } //___________________________________________________________________________________ +double NievesQELCCPXSec::d2sigma_dQ2dv(const Interaction* interaction) const +{ + const InitialState & init_state = interaction -> InitState(); + const Target & target = init_state.Tgt(); + + double Rmax = MaximalRadius(&target); + if (Rmax <= 0) return 0; + + ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( f1DimIntgType ); + ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 0); + ROOT::Math::Integrator ig(*func, ig_type, 0, f1DimRelTol, f1DimMaxEval); + double xsec = ig.Integral(0, Rmax); + delete func; + return xsec; +} +//___________________________________________________________________________________ void NievesQELCCPXSec::ModelNuclParams(const Interaction* interaction, double r, double & kFi, double & kFf) const { const InitialState & init_state = interaction -> InitState(); diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 62d8b37dc9..6107788974 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -60,6 +60,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { // XSecAlgorithmI interface implementation double XSec (const Interaction * i, KinePhaseSpace_t k) const; + double d2sigma_dQ2dv (const Interaction * i) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; const TVector3 & FinalLeptonPolarization (const Interaction* i) const; From 078aa64d7a21bfc85a1323e551672a1fef62c4f1 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 18 Aug 2025 10:48:13 +0300 Subject: [PATCH 66/78] Fix missing IsAboveThreshold check for single pion production --- src/Framework/Interaction/KPhaseSpace.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Framework/Interaction/KPhaseSpace.cxx b/src/Framework/Interaction/KPhaseSpace.cxx index 50b8302021..1cce481eb9 100644 --- a/src/Framework/Interaction/KPhaseSpace.cxx +++ b/src/Framework/Interaction/KPhaseSpace.cxx @@ -311,6 +311,7 @@ bool KPhaseSpace::IsAboveThreshold(void) const pi.IsDarkMatterDeepInelastic() || pi.IsDiffractive() || pi.IsSingleKaon() || + pi.IsSinglePion() || pi.IsAMNuGamma()) { E = init_state.ProbeE(kRfHitNucRest); From 022566b6ea65364e2e9ffec65ed8c19e9a7a53e9 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Mon, 22 Sep 2025 23:12:15 +0300 Subject: [PATCH 67/78] add jacobian for Tlctl->Q2v transformation --- src/Framework/Utils/KineUtils.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Framework/Utils/KineUtils.cxx b/src/Framework/Utils/KineUtils.cxx index 9abbe4d9b0..8ec6d8cd71 100644 --- a/src/Framework/Utils/KineUtils.cxx +++ b/src/Framework/Utils/KineUtils.cxx @@ -460,6 +460,17 @@ double genie::utils::kinematics::Jacobian( delete ki4; } + else if ( TransformMatched(fromps,tops, kPSTlctl, kPSQ2vfE, forward) ) + { + TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); + TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); + double Ev = ki4->Energy(); + double l = kf4.Vect().Mag(); + J = TMath::Abs(2*Ev*l); + + delete ki4; + } + else if ( TransformMatched(fromps,tops, kPSxyfE, kPSWQ2fE, forward) ) { const InitialState & init_state = i->InitState(); From c4ec6cb05cf278db7f410586a6947c2822893cfc Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 23 Sep 2025 19:34:07 +0300 Subject: [PATCH 68/78] delete unused jacobians --- src/Framework/Utils/KineUtils.cxx | 113 +----------------------------- 1 file changed, 2 insertions(+), 111 deletions(-) diff --git a/src/Framework/Utils/KineUtils.cxx b/src/Framework/Utils/KineUtils.cxx index 8ec6d8cd71..eb50e5bb55 100644 --- a/src/Framework/Utils/KineUtils.cxx +++ b/src/Framework/Utils/KineUtils.cxx @@ -321,116 +321,7 @@ double genie::utils::kinematics::Jacobian( // (it will be inverted below for the inverse transformation) J = W / ( 2. * pv * pl * M ); } - - else if ( TransformMatched(fromps,tops, kPSyphi0fEx, kPSQELEvGen, forward) ) - { - TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); - TLorentzVector* pi4 = i->InitStatePtr()->TgtPtr()->HitNucP4Ptr(); - TLorentzVector totMom = *ki4 + *pi4; - TVector3 beta = totMom.BoostVector(); - TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); - kf4.Boost(-beta); - - TVector3 zvec(0., 0., 1.); - TVector3 rot = ( zvec.Cross(beta) ).Unit(); - double angle = beta.Angle( zvec ); - // Handle the edge case where beta is along z, so the - // cross product above vanishes - if ( beta.Perp() == 0. && beta.Z() < 0. ) - { - rot = TVector3(0., 1., 0.); - angle = genie::constants::kPi; - } - - if ( rot.Mag() > 0 ) - { - kf4.Rotate(angle, -rot); - } - - double kf4_mag = kf4.Vect().Mag(); - double theta_star = kf4.Theta(); - double phi_star = kf4.Phi(); - - TLorentzVector kf4_dtheta(kf4_mag*TMath::Cos(phi_star)*TMath::Cos(theta_star), kf4_mag*TMath::Sin(phi_star)*TMath::Cos(theta_star), -kf4_mag*TMath::Sin(theta_star), 0); - TLorentzVector kf4_dphi( -kf4_mag*TMath::Sin(phi_star)*TMath::Sin(theta_star), kf4_mag*TMath::Cos(phi_star)*TMath::Sin(theta_star), 0, 0); - if ( theta_star <= 0 || theta_star >= genie::constants::kPi) - { - kf4_dphi = TLorentzVector( -kf4_mag*TMath::Sin(phi_star), kf4_mag*TMath::Cos(phi_star), 0, 0 ); - } - // to LAB frame - if ( rot.Mag() > 0 ) - { - kf4_dtheta.Rotate(angle, rot); - kf4_dphi.Rotate(angle, rot); - } - kf4_dtheta.Boost(beta); - kf4_dphi.Boost(beta); - kf4 = i->KinePtr()->FSLeptonP4(); - - double dQ2dtheta = 2*((*ki4)*kf4_dtheta); - double dQ2dphi = 2*((*ki4)*kf4_dphi); - - // to hit nucleon rest frame - TVector3 beta1 = pi4->BoostVector(); - kf4_dtheta.Boost(-beta1); - kf4_dphi.Boost(-beta1); - kf4.Boost(-beta1); - - ki4->Boost(-beta1); - TVector3 ki3 = ki4->Vect(); - TVector3 rot1 = ( ki3.Cross(zvec) ).Unit(); - double angle1 = zvec.Angle( ki3 ); - // Handle the edge case where beta is along z, so the - // cross product above vanishes - if ( ki3.Perp() == 0. && ki3.Z() < 0. ) - { - rot1 = TVector3(0., 1., 0.); - angle1 = genie::constants::kPi; - } - if ( rot1.Mag() > 0 ) - { - kf4_dtheta.Rotate(angle1, rot1); - kf4_dphi.Rotate(angle1, rot1); - kf4.Rotate(angle1, rot1); - } - double t = 1/( kf4.Px()*kf4.Px() + kf4.Py()*kf4.Py() ); - double dphi0dtheta = t*(kf4_dtheta.Py()*kf4.Px() - kf4_dtheta.Px()*kf4.Py()); - double dphi0dphi = t*(kf4_dphi.Py()*kf4.Px() - kf4_dphi.Px()*kf4.Py()); - - double Q2 = i->Kine().GetKV( kKVQ2 ); - // mass of initial nucleon - double Mi = i->InitStatePtr()->TgtPtr()->HitNucMass(); - // Look up the (on-shell) mass of the final nucleon - TDatabasePDG *tb = TDatabasePDG::Instance(); - double Mf = tb->GetParticle( i->RecoilNucleonPdg() )->Mass(); - // Mandelstam s for the probe/hit nucleon system - double s = TMath::Sq( i->InitState().CMEnergy() ); - double dydQ2 = (s - Mi*Mi)/TMath::Sq(s - Mf*Mf - Q2); - if ( theta_star <= 0 || theta_star >= genie::constants::kPi) - J = 1; - else - J = 1/TMath::Sin(theta_star); - - // It is not entirely correct to divide by 2 pi, but solely to simplify the code it is better to do it here (Igor Kakorin) - J = TMath::Abs(J*dydQ2*(dQ2dtheta*dphi0dphi - dQ2dphi*dphi0dtheta)/2/genie::constants::kPi); - - delete ki4; - } - - else if ( TransformMatched(fromps,tops, kPSyphi0fEx, kPSQ2fE, forward) ) - { - double Q2 = i->Kine().GetKV( kKVQ2 ); - // mass of initial nucleon - double Mi = i->InitStatePtr()->TgtPtr()->HitNucMass(); - // Look up the (on-shell) mass of the final nucleon - TDatabasePDG *tb = TDatabasePDG::Instance(); - double Mf = tb->GetParticle( i->RecoilNucleonPdg() )->Mass(); - // Mandelstam s for the probe/hit nucleon system - double s = TMath::Sq( i->InitState().CMEnergy() ); - double dydQ2 = (s - Mi*Mi)/TMath::Sq(s - Mf*Mf - Q2); - J = dydQ2; - } - + else if ( TransformMatched(fromps,tops, kPSxyfE, kPSTlctl, forward) ) { TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(); @@ -460,7 +351,7 @@ double genie::utils::kinematics::Jacobian( delete ki4; } - else if ( TransformMatched(fromps,tops, kPSTlctl, kPSQ2vfE, forward) ) + else if ( TransformMatched(fromps,tops, kPSQ2vfE, kPSTlctl, forward) ) { TLorentzVector* ki4 = i->InitStatePtr()->GetProbeP4(genie::kRfLab); TLorentzVector kf4(i->KinePtr()->FSLeptonP4()); From 6c67b1768194414881f9a6326fc4b182c7445893 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 5 Oct 2025 21:45:36 +0300 Subject: [PATCH 69/78] rename functions --- src/Physics/QuasiElastic/XSection/LinkDef.h | 2 +- .../QuasiElastic/XSection/NievesQELCCPXSec.cxx | 4 ++-- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 2 +- .../QuasiElastic/XSection/NievesQELCCXSec.cxx | 16 +++++++--------- .../QuasiElastic/XSection/NievesQELCCXSec.h | 6 +++--- .../Resonance/XSection/BostedChristyEMPXSec.cxx | 1 - 6 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/Physics/QuasiElastic/XSection/LinkDef.h b/src/Physics/QuasiElastic/XSection/LinkDef.h index c5e00521c0..7edcf62d39 100644 --- a/src/Physics/QuasiElastic/XSection/LinkDef.h +++ b/src/Physics/QuasiElastic/XSection/LinkDef.h @@ -47,6 +47,6 @@ // Wrappers for GSL/MathMore lib #pragma link C++ class genie::utils::gsl::d2Xsec_dQ2dv; -#pragma link C++ class genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E; +#pragma link C++ class genie::utils::gsl::d3XSec_dQ2dvdR_E; #endif diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 503526ebec..e90baf2107 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1416,7 +1416,7 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, // factor kPi2 comes from above definition of b; coloumb corrections factor also is taken into account double extrafactor = kGF2*fCos8c2*TMath::Sq(kMw2/(kMw2 - q4.Mag2() ) )/El/4/kPi2; - // Calculate xsec + // Calculate d3XSec/dEldCosThetadR double xsec = extrafactor*R; xsec *= fXSecCCScale ; @@ -1424,7 +1424,7 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, } //___________________________________________________________________________________ -double NievesQELCCPXSec::d2sigma_dQ2dv(const Interaction* interaction) const +double NievesQELCCPXSec::d2XSec_dEldCosTheta(const Interaction* interaction) const { const InitialState & init_state = interaction -> InitState(); const Target & target = init_state.Tgt(); diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 6107788974..853abef8ed 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -60,7 +60,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { // XSecAlgorithmI interface implementation double XSec (const Interaction * i, KinePhaseSpace_t k) const; - double d2sigma_dQ2dv (const Interaction * i) const; + double d2XSec_dEldCosTheta (const Interaction * i) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; const TVector3 & FinalLeptonPolarization (const Interaction* i) const; diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx index e5c14a85cb..d26169de16 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx @@ -2,8 +2,6 @@ /* Copyright (c) 2003-2025, The GENIE Collaboration For the full text of the license visit http://copyright.genie-mc.org - - Igor Kakorin JINR */ //____________________________________________________________________________ @@ -47,7 +45,7 @@ double NievesQELCCXSec::Integrate(const XSecAlgorithmI* model, const Interaction Target * tgt = in->InitStatePtr()->TgtPtr(); double Rmax = tgt->HitNucPosition(); - utils::gsl::d3XSec_dElepdCosThetalepdR_E func(model, in, Rmax ) ; + utils::gsl::d3XSec_dQ2dvdR_E func(model, in, Rmax ) ; ROOT::Math::IntegrationMultiDim::Type ig_type = utils::gsl::IntegrationNDimTypeFromString(fGSLIntgType); ROOT::Math::IntegratorMultiDim ig(ig_type, 0, fGSLRelTol, fGSLMaxEval); if (ig_type == ROOT::Math::IntegrationMultiDim::kADAPTIVE) @@ -95,7 +93,7 @@ void NievesQELCCXSec::LoadConfig(void) //____________________________________________________________________________ // GSL wrappers //____________________________________________________________________________ -genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::d3XSec_dElepdCosThetalepdR_E( +genie::utils::gsl::d3XSec_dQ2dvdR_E::d3XSec_dQ2dvdR_E( const XSecAlgorithmI * m, const Interaction * interaction, double Rmax) : ROOT::Math::IBaseFunctionMultiDim(), fModel(m), @@ -113,15 +111,15 @@ genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::d3XSec_dElepdCosThetalepdR_E( sm_utils->SetInteraction(interaction); fKinematics = fInteraction->KinePtr(); } -genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::~d3XSec_dElepdCosThetalepdR_E() +genie::utils::gsl::d3XSec_dQ2dvdR_E::~d3XSec_dQ2dvdR_E() { } -unsigned int genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::NDim(void) const +unsigned int genie::utils::gsl::d3XSec_dQ2dvdR_E::NDim(void) const { return 3; } -double genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::DoEval(const double * xin) const +double genie::utils::gsl::d3XSec_dQ2dvdR_E::DoEval(const double * xin) const { // inputs: // normalized Q2 from 0 to 1 @@ -160,8 +158,8 @@ double genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::DoEval(const double * xi return xsec*J*units::fm3/(1E-38 * units::cm2); } ROOT::Math::IBaseFunctionMultiDim * -genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E::Clone() const +genie::utils::gsl::d3XSec_dQ2dvdR_E::Clone() const { return - new genie::utils::gsl::d3XSec_dElepdCosThetalepdR_E(fModel,fInteraction,fRmax); + new genie::utils::gsl::d3XSec_dQ2dvdR_E(fModel,fInteraction,fRmax); } diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h index 4a5ce6beef..cc22391a40 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h @@ -83,11 +83,11 @@ namespace gsl { // // A 3-D cross section function: d3xsec/dEldCosThetadR = f(El,CosTheta, R)|(fixed E) // -class d3XSec_dElepdCosThetalepdR_E: public ROOT::Math::IBaseFunctionMultiDim +class d3XSec_dQ2dvdR_E: public ROOT::Math::IBaseFunctionMultiDim { public: - d3XSec_dElepdCosThetalepdR_E(const XSecAlgorithmI * m, const Interaction * i, double Rmax); - ~d3XSec_dElepdCosThetalepdR_E(); + d3XSec_dQ2dvdR_E(const XSecAlgorithmI * m, const Interaction * i, double Rmax); + ~d3XSec_dQ2dvdR_E(); // ROOT::Math::IBaseFunctionMultiDim interface unsigned int NDim (void) const; diff --git a/src/Physics/Resonance/XSection/BostedChristyEMPXSec.cxx b/src/Physics/Resonance/XSection/BostedChristyEMPXSec.cxx index 6417d24e50..06d29dece0 100644 --- a/src/Physics/Resonance/XSection/BostedChristyEMPXSec.cxx +++ b/src/Physics/Resonance/XSection/BostedChristyEMPXSec.cxx @@ -466,7 +466,6 @@ double BostedChristyEMPXSec::XSec( // Cross section for proton or neutron if (A<2 && Wsq>1.155) { - double xb = Q2/(Wsq+Q2-Mp2); sigmaT = sigmaR(0, Q2, W) + sigmaNR(0, Q2, W); sigmaL = sigmaR(1, Q2, W) + sigmaNR(1, Q2, W); F1p = sigmaT*(Wsq-Mp2)/8./kPi2/kAem; From 916798ca6566d6519f03e1d6315da50cb823bd75 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 5 Oct 2025 22:59:08 +0300 Subject: [PATCH 70/78] polarization in the lab frame --- src/Framework/EventGen/XSecAlgorithmI.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Framework/EventGen/XSecAlgorithmI.cxx b/src/Framework/EventGen/XSecAlgorithmI.cxx index 7d168ecc60..f8c3938d7d 100644 --- a/src/Framework/EventGen/XSecAlgorithmI.cxx +++ b/src/Framework/EventGen/XSecAlgorithmI.cxx @@ -61,23 +61,23 @@ bool XSecAlgorithmI::ValidKinematics(const Interaction* interaction) const return true; } //___________________________________________________________________________ -const TVector3 & XSecAlgorithmI::FinalLeptonPolarization (const Interaction* i) const +const TVector3 & XSecAlgorithmI::FinalLeptonPolarization (const Interaction* interaction) const { - if ( i->ProcInfo().IsEM() ) + if ( interaction->ProcInfo().IsEM() ) { LOG("XSecBase", pWARN) << "For EM processes doesn't work yet. Set it to zero."; fFinalLeptonPolarization = TVector3(0, 0, 0); return fFinalLeptonPolarization; } - int pdg = i->FSPrimLeptonPdg(); + const Kinematics & kinematics = interaction -> Kine(); + TLorentzVector leptonMom = kinematics.FSLeptonP4(); + int pdg = interaction->FSPrimLeptonPdg(); + fFinalLeptonPolarization = TVector3(leptonMom.Px(), leptonMom.Py(), leptonMom.Pz()); if ( pdg::IsNeutrino(pdg) || pdg::IsElectron(pdg) || pdg::IsMuon(pdg) || pdg::IsTau(pdg) ) { - fFinalLeptonPolarization = TVector3(0, 0, -1); - } - else - { - fFinalLeptonPolarization = TVector3(0, 0, 1); + fFinalLeptonPolarization = -1.*fFinalLeptonPolarization; } + return fFinalLeptonPolarization; } //___________________________________________________________________________ From 2e2202b644352dd50273646bce4a34828bf22cac Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sat, 18 Oct 2025 22:30:49 +0300 Subject: [PATCH 71/78] add polarization undefined bit flag --- src/Framework/EventGen/XSecAlgorithmI.cxx | 7 ++-- src/Framework/EventGen/XSecAlgorithmI.h | 1 + src/Physics/Common/PrimaryLeptonUtils.cxx | 4 +- .../XSection/NievesSimoVacasMECPXSec2016.cxx | 20 ++++----- .../Multinucleon/XSection/SuSAv2MECPXSec.cxx | 17 ++++---- .../XSection/LwlynSmithQELCCPXSec.cxx | 13 +++--- .../XSection/NievesQELCCPXSec.cxx | 6 +-- .../QuasiElastic/XSection/RosenbluthPXSec.cxx | 4 +- .../XSection/SmithMonizQELCCPXSec.cxx | 5 ++- .../QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 41 ++++++++++--------- .../Strange/XSection/PaisQELLambdaPXSec.cxx | 1 + 11 files changed, 63 insertions(+), 56 deletions(-) diff --git a/src/Framework/EventGen/XSecAlgorithmI.cxx b/src/Framework/EventGen/XSecAlgorithmI.cxx index f8c3938d7d..c18132c17d 100644 --- a/src/Framework/EventGen/XSecAlgorithmI.cxx +++ b/src/Framework/EventGen/XSecAlgorithmI.cxx @@ -65,14 +65,15 @@ const TVector3 & XSecAlgorithmI::FinalLeptonPolarization (const Interaction* int { if ( interaction->ProcInfo().IsEM() ) { - LOG("XSecBase", pWARN) << "For EM processes doesn't work yet. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("XSecBase", pWARN) << "For EM processes doesn't work yet."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } + fFinalLeptonPolarization.ResetBit(kPolarizationUndef); const Kinematics & kinematics = interaction -> Kine(); TLorentzVector leptonMom = kinematics.FSLeptonP4(); int pdg = interaction->FSPrimLeptonPdg(); - fFinalLeptonPolarization = TVector3(leptonMom.Px(), leptonMom.Py(), leptonMom.Pz()); + fFinalLeptonPolarization = leptonMom.Vect().Unit(); if ( pdg::IsNeutrino(pdg) || pdg::IsElectron(pdg) || pdg::IsMuon(pdg) || pdg::IsTau(pdg) ) { fFinalLeptonPolarization = -1.*fFinalLeptonPolarization; diff --git a/src/Framework/EventGen/XSecAlgorithmI.h b/src/Framework/EventGen/XSecAlgorithmI.h index 43eaccf09a..27447c72eb 100644 --- a/src/Framework/EventGen/XSecAlgorithmI.h +++ b/src/Framework/EventGen/XSecAlgorithmI.h @@ -25,6 +25,7 @@ #include "Framework/Interaction/Interaction.h" namespace genie { + const UInt_t kPolarizationUndef = 1<<14; ///< if set, the lepton polarization is undefined class XSecAlgorithmI : public Algorithm { diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index 215d297cfe..94881a6df9 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -156,7 +156,7 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( std::complex LWppmm = LWpp + LWmm; if (LWppmm.real() == 0 && LWppmm.imag() == 0) { - polarization = TVector3(0, 0, 0); + polarization.SetBit(kPolarizationUndef); return; } std::complex rhopp = LWpp/LWppmm; @@ -275,7 +275,7 @@ void genie::utils::CalculatePolarizationVectorInTargetRestFrame( double R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; if (R == 0) { - polarization = TVector3(0, 0, 0); + polarization.SetBit(kPolarizationUndef); return; } double PL = sign*(2*aux1m*(W1 - aux1*W4) + aux1p*W2 - sign*(aux2*aux1m + aux1*cost)*W3 - aux1*cost*W5)/R; diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index 5bfc0b0ba4..9b0a8f0e58 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -417,7 +417,7 @@ void NievesSimoVacasMECPXSec2016::LoadConfig(void) const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Interaction* interaction) const { if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - + fFinalLeptonPolarization.ResetBit(kPolarizationUndef); const Kinematics& kinematics = interaction -> Kine(); const InitialState& init_state = interaction -> InitState(); const Target& tgt = init_state.Tgt(); @@ -486,7 +486,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int MAXLOG("NievesSimoVacasMEC", pWARN, 10) << "Asked to scale to deuterium through boron " << target_pdg << " nope, lets not do that."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } else if (A_request >= 9 && A_request < 15) @@ -528,8 +528,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int } else { - MAXLOG("NievesSimoVacasMEC", pWARN, 10) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + MAXLOG("NievesSimoVacasMEC", pWARN, 10) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } @@ -543,7 +543,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a" " hadronic tensor for the nuclide " << tensor_pdg; - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -557,7 +557,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int double Q3max = tensor->qMagMax(); if (Q0 < Q0min || Q0 > Q0max || Q3 < Q3min || Q3 > Q3max) { - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -592,7 +592,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"DeltaAll\"" << " hadronic tensor for nuclide " << tensor_pdg; - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -604,7 +604,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"Deltapn\"" << " hadronic tensor for nuclide " << tensor_pdg; - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -629,7 +629,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"FullAll\"" << " hadronic tensor for nuclide " << tensor_pdg; - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -641,7 +641,7 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"Fullpn\"" << " hadronic tensor for nuclide " << tensor_pdg; - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index a73c3325f4..130021f7ea 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -481,11 +481,12 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int const ProcessInfo& proc_info = interaction->ProcInfo(); if ( proc_info.IsEM() ) { - LOG("SuSAv2MECPXSec", pWARN) << "For EM processes doesn't work yet. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2MECPXSec", pWARN) << "For EM processes doesn't work yet."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + fFinalLeptonPolarization.ResetBit(kPolarizationUndef); // Get the hadron tensor for the selected nuclide. Check the probe PDG code // to know whether to use the tensor for CC neutrino scattering or for // electron scattering @@ -501,8 +502,8 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int } else { - LOG("SuSAv2MECPXSec", pWARN) << "Doesn't work for processes other than weak ones. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2MECPXSec", pWARN) << "Doesn't work for processes other than weak ones."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } //else @@ -525,8 +526,8 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int // If retrieving the tensor failed, complain and return zero if ( !tensor ) { - LOG("SuSAv2MEC", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2MEC", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -561,7 +562,7 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int double Q3max = tensor->qMagMax(); if (Q0-Delta_Q_value < Q0min || Q0-Delta_Q_value > Q0max || Q3 < Q3min || Q3 > Q3max) { - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -578,7 +579,7 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int double Q2 = Q3*Q3 - Q0*Q0; if ( Q2 < Q2min ) { - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index 360fc37a83..27e7248f55 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -482,6 +482,7 @@ void LwlynSmithQELCCPXSec::LoadConfig(void) const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + fFinalLeptonPolarization.ResetBit(kPolarizationUndef); const QELFormFactorsModelI* qel_ff_mod = dynamic_cast (this->SubAlg("FormFactorsAlg")); const AlgId & qel_ff_mod_id = qel_ff_mod->Id(); std::string qel_ff_mod_name = qel_ff_mod_id.Name(); @@ -527,8 +528,8 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio double pNf = outNucleonMom.P(); if ( pNf < kF ) { - LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } @@ -557,15 +558,15 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio // of q0Tilde or Q2tilde, just return 0. if ( qTildeP4.E() < 0 && init_state.Tgt().IsNucleus() && !interaction->TestBit(kIAssumeFreeNucleon) ) { - LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } double Q2tilde = -qTildeP4.Mag2(); if ( Q2tilde < 0 ) { - LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization. Set it to zero"; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index e90baf2107..927b6b4823 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1130,7 +1130,7 @@ ROOT::Math::IBaseFunctionOneDim * const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - + fFinalLeptonPolarization.ResetBit(kPolarizationUndef); // Get kinematics and init-state parameters const Kinematics & kinematics = interaction -> Kine(); const InitialState & init_state = interaction -> InitState(); @@ -1146,7 +1146,7 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i delete func; if (R == 0) { - fFinalLeptonPolarization = TVector3(0, 0, 0); + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -1175,7 +1175,7 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i TVector3 Py = Pz.Cross(Px); fFinalLeptonPolarization = PP*Py + PL*Pz; - if (fFinalLeptonPolarization.Mag2()>1) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + //if (fFinalLeptonPolarization.Mag2()>1) return XSecAlgorithmI::FinalLeptonPolarization(interaction); return fFinalLeptonPolarization; diff --git a/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.cxx b/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.cxx index b2f73371af..e3113d4e2e 100644 --- a/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.cxx @@ -204,7 +204,7 @@ void RosenbluthPXSec::LoadConfig(void) //____________________________________________________________________________ const TVector3 & RosenbluthPXSec::FinalLeptonPolarization (const Interaction* interaction) const { - LOG("Rosenbluth", pWARN) << "For EM processes doesn't work yet. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("Rosenbluth", pWARN) << "For EM processes doesn't work yet."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 4cf9ca85ef..153e3f0b7e 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -526,6 +526,7 @@ double SmithMonizQELCCPXSec::dsQES_dQ2_SM(const Interaction * interaction) const const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + fFinalLeptonPolarization.ResetBit(kPolarizationUndef); // Get kinematics & init-state parameters const Kinematics & kinematics = interaction -> Kine(); sm_utils->SetInteraction(interaction); @@ -564,8 +565,8 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio double cosT_k = (v + aux1)/qv; if (cosT_k < -1.0 || cosT_k > 1.0 ) { - LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 2766d8775a..ecc7bd4dae 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -673,11 +673,12 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int const ProcessInfo& proc_info = interaction->ProcInfo(); if ( proc_info.IsEM() ) { - LOG("SuSAv2QE", pWARN) << "For EM processes doesn't work yet. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "For EM processes doesn't work yet."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } if (!fIsPreciseLeptonPolarization || proc_info.IsWeakNC()) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + fFinalLeptonPolarization.ResetBit(kPolarizationUndef); const Kinematics& kinematics = interaction -> Kine(); const InitialState& init_state = interaction -> InitState(); const Target& tgt = init_state.Tgt(); @@ -717,8 +718,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int double Q2 = Q3*Q3 - Q0*Q0; if ( Q2 < Q2min ) { - LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -829,8 +830,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int //} else { - LOG("SuSAv2QE", pWARN) << "Doesn't work for processes other than weak ones. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Doesn't work for processes other than weak ones."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } @@ -935,8 +936,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if ( !tensor_susa ) { - LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } @@ -950,8 +951,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if ( !tensor_blen ) { - LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } @@ -963,8 +964,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if ( !tensor_crpa ) { - LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } @@ -1012,8 +1013,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int double Q3max = tensor_susa->qMagMax(); if (Q0-Delta_Q_value_susa < Q0min || Q0-Delta_Q_value_susa > Q0max || Q3 < Q3min || Q3 > Q3max) { - LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } @@ -1026,8 +1027,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int double Q3max = tensor_crpa->qMagMax(); if (Q0-Delta_Q_value_crpa < Q0min || Q0-Delta_Q_value_crpa > Q0max || Q3 < Q3min || Q3 > Q3max) { - LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } @@ -1039,8 +1040,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int double Q3max = tensor_blen->qMagMax(); if (Q0-Delta_Q_value_blen < Q0min || Q0-Delta_Q_value_blen > Q0max || Q3 < Q3min || Q3 > Q3max) { - LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } @@ -1052,8 +1053,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int double Q3max = tensor_blen->qMagMax(); if (Q0-Delta_Q_value_crpa < Q0min || Q0-Delta_Q_value_blen > Q0max || Q3 < Q3min || Q3 > Q3max) { - LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization. Set it to zero."; - fFinalLeptonPolarization = TVector3(0, 0, 0); + LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; + fFinalLeptonPolarization.SetBit(kPolarizationUndef); return fFinalLeptonPolarization; } } diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx index db3fffd843..073eaab125 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx @@ -242,6 +242,7 @@ void PaisQELLambdaPXSec::LoadConfig(void) const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* interaction) const { if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + fFinalLeptonPolarization.ResetBit(kPolarizationUndef); // First we need access to all of the particles in the interaction // The particles were stored in the lab frame //----- get kinematics & init state - compute auxiliary vars From b96905a105adebf8f51087b7b1503ea775c9c0d8 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Sun, 16 Nov 2025 19:42:41 +0300 Subject: [PATCH 72/78] Improve APFEL detection: support modern CMake builds (no .la) --- configure | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/configure b/configure index ccf74eaba5..4e8f411e08 100755 --- a/configure +++ b/configure @@ -589,12 +589,17 @@ if($gopt_enable_apfel eq "YES") { } print "Setting --with-apfel-lib=$gopt_with_apfel_lib\n"; } - # check - my $file = "$gopt_with_apfel_lib/libAPFEL.la"; - if(! -e $file) { - print "*** Error *** You need to specify the path to APFEL library using --with-apfel-lib=/some/path/\n"; - print "*** Error *** Otherwise, you should --disable-apfel\n\n"; - exit 1; + + # check for APFEL libraries + my $file_so = "$gopt_with_apfel_lib/libAPFEL.so"; + my $file_a = "$gopt_with_apfel_lib/libAPFEL.a"; + my $file_la = "$gopt_with_apfel_lib/libAPFEL.la"; + + if(! -e $file_so && ! -e $file_a && ! -e $file_la) { + print "*** Error *** Could not find libAPFEL.[so|a|la] in $gopt_with_apfel_lib\n"; + print "*** Error *** You need to specify the path to APFEL library using --with-apfel-lib=/some/path/\n"; + print "*** Error *** Otherwise, you should --disable-apfel\n\n"; + exit 1; } } From a8ea072e1c22a7057d6394c5c1511976605197fd Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 19 Mar 2026 11:24:46 +0300 Subject: [PATCH 73/78] test stage --- config/NievesQELCCPXSec.xml | 20 +- .../XSection/NievesQELCCPXSec.cxx | 509 +++++++++++++++++- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 38 +- .../XSection/NievesQELException.cxx | 15 +- .../XSection/NievesQELException.h | 15 +- .../libGPhQELXS682a3e2da9_dictContent.h | 0 .../libGPhQELXS6a99ba76fa_dictUmbrella.h | 0 .../libGPhQELXSb26666628a_dictUmbrella.h | 0 .../libGPhQELXScacac3b134_dictContent.h | 0 9 files changed, 555 insertions(+), 42 deletions(-) create mode 100644 src/Physics/QuasiElastic/XSection/libGPhQELXS682a3e2da9_dictContent.h create mode 100644 src/Physics/QuasiElastic/XSection/libGPhQELXS6a99ba76fa_dictUmbrella.h create mode 100644 src/Physics/QuasiElastic/XSection/libGPhQELXSb26666628a_dictUmbrella.h create mode 100644 src/Physics/QuasiElastic/XSection/libGPhQELXScacac3b134_dictContent.h diff --git a/config/NievesQELCCPXSec.xml b/config/NievesQELCCPXSec.xml index 6e552502a7..d2aa19af71 100644 --- a/config/NievesQELCCPXSec.xml +++ b/config/NievesQELCCPXSec.xml @@ -23,12 +23,13 @@ Parameters needed when Integrating with this model to generate splines: ........................................................................................................................... Name Type Optional Comment Default ........................................................................................................................... -IntegralAverageOverNucleonMomentum bool Yes Will be overridden to true if nuclear model is LFG false -IntegralNumberOfNucleonThrows int Yes Number of nucleons to sample when computing splines 5000 -IntegralNuclearModel alg No -IntegralNuclearInfluenceCutoffEnergy double Yes 2.0 -RmaxMode string Yes Method to use to compute Rmax for integrating the VertexGenerator - Coulomb potential in NievesQELCCPXSec::vcr() +IntegralAverageOverNucleonMomentum bool Yes Will be overridden to true if nuclear model is LFG false +IntegralNumberOfNucleonThrows int Yes Number of nucleons to sample when computing splines 5000 +IntegralNuclearModel alg No +IntegralNuclearInfluenceCutoffEnergy double Yes 2.0 +NumOfIntegPoints unsigned int Yes Number of points for Gauss Legendre integration method 96 +RmaxMode string Yes Method to use to compute Rmax for integrating the VertexGenerator + Coulomb potential in NievesQELCCPXSec::vcr() --> @@ -48,16 +49,15 @@ RmaxMode string Yes Method to use to comput genie::PauliBlocker/Default true + VertexGenerator true OriginalByNieves - - diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index b36eef1c63..831e555b7c 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -30,6 +30,7 @@ #include "Physics/NuclearState/FermiMomentumTable.h" #include "Physics/QuasiElastic/XSection/NievesQELCCPXSec.h" #include "Physics/QuasiElastic/XSection/NievesQELCCXSec.h" +#include "Physics/QuasiElastic/XSection/NievesQELException.h" #include "Framework/Numerical/RandomGen.h" #include "Framework/ParticleData/PDGCodes.h" #include "Framework/ParticleData/PDGUtils.h" @@ -40,7 +41,6 @@ #include "Framework/Utils/PrintUtils.h" #include "Framework/Numerical/GSLUtils.h" #include "Physics/Common/PrimaryLeptonUtils.h" - #include "Physics/NuclearState/NuclearModelI.h" using namespace genie; @@ -437,20 +437,40 @@ void NievesQELCCPXSec::LoadConfig(void) // Get nuclear model for use in Integral() RgKey nuclkey = "IntegralNuclearModel"; - fNuclModel = dynamic_cast (this->SubAlg(nuclkey)); - assert(fNuclModel); + const NuclearModelI* NuclModel = dynamic_cast (this->SubAlg(nuclkey)); + assert(NuclModel); // Check if the model is a local Fermi gas - fLFG = fNuclModel->ModelType(Target()) == kNucmLocalFermiGas; - - if(!fLFG){ - // get the Fermi momentum table for relativistic Fermi gas - GetParam( "FermiMomentumTable", fKFTableName ) ; + bool LFG = NuclModel->ModelType(Target()) == kNucmLocalFermiGas; - fKFTable = 0; - FermiMomentumTablePool * kftp = FermiMomentumTablePool::Instance(); - fKFTable = kftp->GetTable( fKFTableName ); - assert( fKFTable ); + if(!LFG) + { + // NOTE: + // The Nieves model (see Ref.1) is formulated within the Local Fermi Gas (LFG) framework. + // Using it with a Relativistic Fermi Gas (RFG) is theoretically inconsistent, + // as the model relies on local density and position-dependent Fermi momentum. + // + // The Nieves model is formulated within the Local Fermi Gas (LFG) framework. + // Previous GENIE implementations allowed RFG-like configurations, introducing + // an inconsistency with the model assumptions. This implementation enforces LFG usage. + // + // Users requiring RFG-based QE calculations should use: + // - SmithMoniz (RFG-based) + // - LlewellynSmith (RFG-based) + + LOG("Nieves", pERROR) + << "NievesQELCCPXSec requires a Local Fermi Gas (LFG) nuclear model " + << "as defined in Nieves et al., PRC 70, 055503 (2004). " + << "The current configuration is incompatible. " + << "For RFG-based calculations, use SmithMoniz or LlewellynSmith models."; + exceptions::NievesQELException e; + e.SetReason( + "NievesQELCCPXSec requires LFG (PRC 70, 055503 (2004)). " + "For RFG use SmithMonizQELCCPXSec or LlewellynSmithQELCCPXSec." + ); + e.SetIsConfigError(true); + throw e; + } // Nuclear radius parameter (R = R0*A^(1/3)) to use when computing @@ -514,7 +534,9 @@ void NievesQELCCPXSec::LoadConfig(void) // Scaling factor for the Coulomb potential GetParamDef( "CoulombScale", fCoulombScale, 1.0 ); - + GetParamDef("NumOfIntegPoints", fNumGLPoints, 96); + + this->InitGaussLegendre(fNumGLPoints, fGLPoints, fGLWeights); AlgFactory * algf = AlgFactory::Instance(); NievesQELCCXSec* nvi = dynamic_cast(algf->AdoptAlgorithm("genie::NievesQELCCXSec", "Default")); f1DimIntgType = nvi->Get1DimIntgType(); @@ -1139,6 +1161,9 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i double Rmax = MaximalRadius(&target); if (Rmax <= 0) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + double t_root = 0.0; + double t_gauss = 0.0; + double t0 = Now(); ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( f1DimIntgType ); ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 1); ROOT::Math::Integrator ig(*func, ig_type, 0, f1DimRelTol, f1DimMaxEval); @@ -1162,7 +1187,62 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i double PL = PLR/R; double PP = PPR/R; - + double t1 = Now(); + t_root += (t1 - t0); + + t0 = Now(); + +/* + double IRPL = 0, IRPP = 0, IR = 0; + for (int i = 0; i < fNumGLPoints; ++i) + { + double r = 0.5*Rmax*(1. + fGLPoints[i]); + double weight = 0.5*Rmax*fGLWeights[i]; + double RPL, RPP, R; + IntegratedOverMomentumAll(interaction, r, &RPL, &RPP, &R); + IRPL += weight * RPL; + IRPP += weight * RPP; + IR += weight * R; + } +*/ + double RPL, RPP; + double IRPL = 0, IRPP = 0, IR = 0; + for (int i = 0; i < fNumGLPoints/2; ++i) + { + double xi = fGLPoints[i]; + double wi = fGLWeights[i]; + double weight = 0.5 * Rmax * wi; + // --- x = -xi --- + double r = 0.5 * Rmax * (1.0 - xi); + IntegratedOverMomentumAll(interaction, r, &RPL, &RPP, &R); + IRPL += weight * RPL; + IRPP += weight * RPP; + IR += weight * R; + // --- x = +xi --- + r = 0.5 * Rmax * (1.0 + xi); + IntegratedOverMomentumAll(interaction, r, &RPL, &RPP, &R); + IRPL += weight * RPL; + IRPP += weight * RPP; + IR += weight * R; + } + PL = IRPL/IR; + PP = IRPP/IR; + t1 = Now(); + t_gauss += (t1 - t0); + //---------------------------------------- + //запись в файл + //---------------------------------------- + std::ofstream out("integration_benchmark.txt", std::ios::app); + out << std::setprecision(15) << std::scientific; + out << "ROOT_time = " << t_root << " s\n"; + out << "GAUSS_time = " << t_gauss << " s\n"; + out << "ROOT_result = " << PL << " " << PP << "\n"; + out << "GAUSS_result= " << IRPL/IR << " " << IRPP/IR << "\n"; + out << "ROOT_time/GAUSS_time = " << t_root/t_gauss << " s\n"; + out << "ROOT_result - GAUSS_result = " << PL - IRPL/IR << " " << PP - IRPP/IR << "\n"; + out << "----------------------------------------\n"; + out.close(); + TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); TLorentzVector neutrinoMom = *tempNeutrino; delete tempNeutrino; @@ -1424,6 +1504,257 @@ double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, } //___________________________________________________________________________________ +double NievesQELCCPXSec::IntegratedOverMomentumAll(const Interaction* interaction, double r, + double* RPL,double* RPP,double* R) const +{ + if (RPL) + *RPL = 0; + if (RPP) + *RPP = 0; + if (R) + *R = 0; + // Get kinematics and init-state parameters + const Kinematics & kinematics = interaction -> Kine(); + const InitialState & init_state = interaction -> InitState(); + const Target & target = init_state.Tgt(); + + // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial + // struck nucleon + double Mi_onshell = target.HitNucMass(); + + // On-shell mass of final nucleon (from PDGLibrary) + double Mf = interaction->RecoilNucleon()->Mass(); + + // Isoscalar mass of nucleon + double M = (Mi_onshell + Mf)/2; + + // Note that GetProbeP4 defaults to returning the probe 4-momentum in the + // struck nucleon rest frame, so we have to explicitly ask for the lab frame + // here + TLorentzVector neutrinoMom = *init_state.GetProbeP4(kRfLab); + TLorentzVector leptonMom = kinematics.FSLeptonP4(); + double ml = interaction->FSPrimLepton()->Mass(); + double ml2 = ml*ml; + + + // Calculate Coulomb corrections + double PlLocal = leptonMom.P(); + + bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); + int sign = is_neutrino ? -1 : 1; + + double ElLocal = leptonMom.E(); + if ( fCoulomb ) + { + // Coulomb potential + double Vc = vcr(&target, r); + + // Outgoing lepton energy and momentum including Coulomb potential + double El = ElLocal; + ElLocal = El + sign*Vc; + + if ( ElLocal - ml <= 0 ) return 0; + + // The Coulomb correction factor blows up as pl -> 0. To guard against + // unphysically huge corrections here, require that the lepton kinetic energy + // (at infinity) is larger than the magnitude of the Coulomb potential + // (should be around a few MeV) + double KEl = El - ml; + if ( KEl <= TMath::Abs(Vc) ) return 0; + + // Local value of the lepton 3-momentum magnitude for the Coulomb correction + PlLocal = TMath::Sqrt(ElLocal*ElLocal - ml2); + + } + + double q0Tilde = neutrinoMom.E() - leptonMom.E(); + + + double kFi, kFf; + ModelNuclParams(interaction, r, kFi, kFf); + + + double EFi = TMath::Hypot(M, kFi); + double EFf = TMath::Hypot(M, kFf); + + int nucl_pdg_ini = target.HitNucPdg(); + bool tgtIsNucleus = target.IsNucleus(); + int A = target.A(); + int Z = target.Z(); + int N = target.N(); + bool hitNucIsProton = pdg::IsProton( nucl_pdg_ini ); + + + // This part of the code is strictly in accordance with the original Nieves' paper + double Mi = target.Mass(); + int Zf = (hitNucIsProton) ? Z - 1 : Z + 1; + PDGLibrary * pdglib = PDGLibrary::Instance(); + TParticlePDG * nucl_f = pdglib->Find( pdg::IonPdgCode(A, Zf) ); + double Q = 0; + if(nucl_f) Q = nucl_f -> Mass() - Mi; + double Q_LFG = EFf - EFi; + q0Tilde -= (Q - Q_LFG); + + // Shift the q0Tilde if required: + if( fQvalueShifter ) q0Tilde += q0Tilde * fQvalueShifter->Shift(*interaction) ; + + // If binding energy effects pull us into an unphysical region, return + // zero + if ( q0Tilde <= 0 ) return 0; + + // Note that we're working in the lab frame (i.e., the rest frame + // of the target nucleus). We can therefore use Nieves' explicit + // form of the Amunu tensor if we rotate the 3-momenta so that + // qTilde is in the +z direction + TVector3 neutrinoMom3 = neutrinoMom.Vect(); + TVector3 leptonMom3 = leptonMom.Vect(); + + // If Coulomb corrections are being used, adjust the lepton 3-momentum used + // to get q3VecTilde so that its magnitude matches the local + // Coulomb-corrected value calculated earlier. Note that, although the + // treatment of Coulomb corrections by Nieves et al. doesn't change the + // direction of the lepton 3-momentum, it *does* change the direction of the + // 3-momentum transfer, and so the correction should be applied *before* + // rotating coordinates into a frame where q3VecTilde lies along the positive + // z axis. + TVector3 leptonMomCoulomb3 = !fCoulomb ? leptonMom3: PlLocal*leptonMom3*(1/leptonMom3.Mag()); + TVector3 q3VecTilde = neutrinoMom3 - leptonMomCoulomb3; + // Calculate qTilde + TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); + double Q2tilde = -qTildeP4.Mag2(); + + // Check that Q2tilde > 0 (accounting for rounding errors) + if (Q2tilde < 0) return 0; + + // Store Q2tilde in the kinematic variable representing Q2. + // This will ensure that the form factors are calculated correctly + // using the de Forest prescription (Q2tilde instead of Q2). + interaction->KinePtr()->SetQ2(Q2tilde); + // Calculate form factors + fFormFactors.Calculate( interaction ); + + // Get the QEL form factors (were calculated before this method was called) + double F1V = 0.5*fFormFactors.F1V(); + double xiF2V = 0.5*fFormFactors.xiF2V(); + double FA = fFormFactors.FA(); + // According to Nieves' paper, Fp = 2.0*M*FA/(kPionMass2-q2), but Llewelyn- + // Smith uses Fp = 2.0*M^2*FA/(kPionMass2-q2), so I divide by M + // This gives units of GeV^-1 + double Fp = fFormFactors.Fp()/M; + + double CN(1), CT(1), CL(1); + if (fRPA) + { + CNCTCLimUcalc(qTildeP4, M, r, tgtIsNucleus, A, Z, N, + CN, CT, CL, interaction->TestBit(kIAssumeFreeNucleon) ); + } + + // Calculate auxiliary parameters + // Off shell mass of initial nucleon + double M2 = M*M; + double FA2 = FA*FA; + double F1V2 = F1V*F1V; + double xiF2V2 = xiF2V*xiF2V; + double q0 = qTildeP4.E(); + double dq = qTildeP4.Pz(); + double dq2 = dq*dq; + double q02 = q0*q0; + double q2 = q02 - dq2; + + double factor = PlLocal*ElLocal*r*r/dq; + + double c = q0/dq; + double d = q2/2/M/dq; + + double Elow = TMath::Max( EFf - q0, M*(c*d + TMath::Sqrt(1- c*c + d*d))/(1 - c*c) ); + double Eup = EFi; + + if (Elow >= Eup) return 0; + + double Elow2 = Elow*Elow; + double Elow3 = Elow*Elow2; + double Eup2 = Eup*Eup; + double Eup3 = Eup*Eup2; + + double b0 = factor*(Eup - Elow); + double b1 = factor/M/2*(Eup2 - Elow2); + double b2 = factor/M2/3*(Eup3 - Elow3); + + double a1 = b0; + double a2 = b2 - b0; + double a3 = c*c*b2 + 2*c*d*b1 + d*d*b0; + double a4 = b2; + double a5 = c*b2 + d*b1; + double a6 = c*b1 + d*b0; + double a7 = b1; + + double Ep = M*a7; + double Ep2 = M2*a4; + double px2 = 0.5*M2*(a2 - a3); //py2=px2 + double pz = M*a6; + double Eppz = M2*a5; + double pz2 = M2*a3; + + double aux = 2*CL*Fp*(Fp*q2 + 4*FA*M); + double W00 = 32*F1V2*(Ep2*CN + Ep*q0 + a1*q2/4)+ + 8*q2*xiF2V2*(a1*(1 - q02*(1/q2 + 1/M2/4)) - Ep2/M2 - Ep*q0/M2) + + 8*FA2*(Ep2 + Ep*q0 + a1*(q2/4 - M2)) - a1*(aux*q02 + 16*F1V*xiF2V*(q02 - q2)*CN); + double Wxx = 32*F1V2*(px2 - a1*q2/4) - 8*q2*xiF2V2*(a1*CT + px2/M2) + + 8*FA2*(px2 + a1*(CT*M2 - q2/4)) - 16*a1*F1V*xiF2V*CT*q2; + double Wzz = 32*F1V2*(pz2 + pz*dq - a1*q2/4)- + 8*q2*xiF2V2*(a1 + pz2/M2 + pz*dq/M2 + a1*dq2*(1/q2 + 1/M2/4))+ + 8*FA2*(pz2 + pz*dq + a1*(CL*M2 - q2/4)) - a1*(aux*dq2 + 16*F1V*xiF2V*q02); + double ReW0z = 16*F1V2*((2*Eppz + Ep*dq)*CN + pz*q0) + -4*q2*xiF2V2*(2*Eppz/M2 + (Ep*dq + pz*q0)/M2 + a1*dq*q0*(2/q2 + 1/M2/2))+ + 4*FA2*((2*Eppz + Ep*dq)*CL + pz*q0) - a1*dq*q0*(aux + 16*F1V*xiF2V); + double ImWxy = -16*FA*(xiF2V+F1V)*(pz*q0 - Ep*dq*CT); + + + TLorentzVector q4 = neutrinoMom - leptonMom; + double v = q4.E(); + double v2 = v*v; + double qv2 = q4.Vect().Mag2(); + double qv = TMath::Sqrt(qv2); + + // Naumov definitions + double W1 = Wxx; + double W2 = W00 + Wxx + v2/qv2*(Wzz - Wxx) - 2*v/qv*ReW0z; + double W3 = -2*ImWxy/qv; + double W4 = (Wzz - Wxx)/qv2; + double W5 = 2*(ReW0z - v/qv*(Wzz - Wxx))/qv; + + double Ev = neutrinoMom.E(); + double El = leptonMom.E(); + double Pl = leptonMom.P(); + double cost = TMath::Cos( neutrinoMom.Angle(leptonMom.Vect()) ); + double sint = TMath::Sqrt(1 - cost*cost); + + double auxm = (El - Pl*cost)/2; + double auxp = (El + Pl*cost)/2; + double aux1m = (Pl - El*cost)/2; + double aux1p = (Pl + El*cost)/2; + double aux1 = ml2/2; + double aux2 = (Ev + El); + if (RPL) + *RPL = sign*(2*aux1m*(W1 - aux1*W4) + aux1p*W2 - sign*(aux2*aux1m + aux1*cost)*W3 - aux1*cost*W5); + if (RPP) + *RPP = sign*ml*sint*(2*W1 - W2 -sign*Ev*W3 - ml2*W4 + El*W5)/2; + if (R) + *R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; + if (!RPL && !RPP && !R) + { + double Rf = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; + // factor kPi2 comes from above definition of b; coloumb corrections factor also is taken into account + double extrafactor = kGF2*fCos8c2*TMath::Sq(kMw2/(kMw2 - q4.Mag2() ) )/El/4/kPi2; + // Calculate d3XSec/dEldCosThetadR + double xsec = extrafactor*Rf; + xsec *= fXSecCCScale ; + return xsec; + } + else + return 0; +} +//___________________________________________________________________________________ double NievesQELCCPXSec::d2XSec_dEldCosTheta(const Interaction* interaction) const { const InitialState & init_state = interaction -> InitState(); @@ -1431,13 +1762,72 @@ double NievesQELCCPXSec::d2XSec_dEldCosTheta(const Interaction* interaction) con double Rmax = MaximalRadius(&target); if (Rmax <= 0) return 0; - +/* + double t_root = 0.0; + double t_gauss = 0.0; + double t0 = Now(); ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( f1DimIntgType ); ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 0); ROOT::Math::Integrator ig(*func, ig_type, 0, f1DimRelTol, f1DimMaxEval); double xsec = ig.Integral(0, Rmax); delete func; - return xsec; + double t1 = Now(); + t_root += (t1 - t0); + t0 = Now(); + double Ixsec = 0; + //double RPL, RPP, R; + //for (int i = 0; i < fNumGLPoints; ++i) + //{ + //double r = 0.5*Rmax*(1. + fGLPoints[i]); + //double weight = 0.5*Rmax*fGLWeights[i]; + //double xsec = IntegratedOverMomentumAll(interaction, r, RPL, RPP, R); + //Ixsec += weight * xsec; + //} +*/ + double Ixsec = 0; + for (int i = 0; i < fNumGLPoints/2; ++i) + { + double xi = fGLPoints[i]; + double wi = fGLWeights[i]; + double weight = 0.5 * Rmax * wi; + // --- x = -xi --- + double r = 0.5 * Rmax * (1.0 - xi); + double xsec = IntegratedOverMomentumAll(interaction, r); + Ixsec += weight * xsec; + // --- x = +xi --- + r = 0.5 * Rmax * (1.0 + xi); + xsec = IntegratedOverMomentumAll(interaction, r); + Ixsec += weight * xsec; + } +/* + t1 = Now(); + t_gauss += (t1 - t0); + + // ---------------------------------------- + // запись в файл + // ---------------------------------------- + double rel; + if (xsec > 0) + rel = TMath::Abs(Ixsec/xsec - 1); + else + rel = -1.; + if (rel > 5e-3) + { + std::ofstream out("integration_benchmark.txt", std::ios::app); + out << std::setprecision(15) << std::scientific; + out << "ROOT_time = " << t_root << " s\n"; + out << "GAUSS_time = " << t_gauss << " s\n"; + out << "ROOT_result = " << xsec*units::fm3/(1E-38*units::cm2) << "\n"; + out << "GAUSS_result= " << Ixsec*units::fm3/(1E-38*units::cm2) << "\n"; + out << "ROOT_time/GAUSS_time = " << t_root/t_gauss << " s\n"; + out << "abs = " << TMath::Abs(xsec - Ixsec)*units::fm3/(1E-38*units::cm2) << "\n"; + out << "rel = " << rel << "\n"; + out << "----------------------------------------\n"; + out.close(); + } + +*/ + return Ixsec*units::fm3; } //___________________________________________________________________________________ void NievesQELCCPXSec::ModelNuclParams(const Interaction* interaction, double r, double & kFi, double & kFf) const @@ -1448,3 +1838,90 @@ void NievesQELCCPXSec::ModelNuclParams(const Interaction* interaction, double r, kFi = fPauliBlocker->GetFermiMomentum(target, nucl_pdg_ini, r); kFf = fPauliBlocker->GetFermiMomentum(target, interaction->RecoilNucleonPdg(), r); } +//___________________________________________________________________________________ +//void NievesQELCCPXSec::InitGaussLegendre(int n, std::vector& x, std::vector& w) +//{ + //// calculation of Gauss-Legendre nodes and weights + //x.resize(n); + //w.resize(n); + + //int m = (n + 1) / 2; + //const double eps = 1e-14; + + //for (int i = 0; i < m; ++i) + //{ + //double z = TMath::Cos(kPi * (i + 0.75) / (n + 0.5)); + //double z1; + + //do + //{ + //double p1 = 1.0, p2 = 0.0; + //for (int j = 1; j <= n; ++j) { + //double p3 = p2; + //p2 = p1; + //p1 = ((2*j-1)*z*p2 - (j-1)*p3)/j; + //} + //double pp = n * (z*p1 - p2) / (z*z - 1); + //z1 = z; + //z = z1 - p1/pp; + //} while (TMath::Abs(z - z1) > eps); + + //x[i] = -z; + //x[n-1-i] = z; + + //double p1 = 1.0, p2 = 0.0; + //for (int j = 1; j <= n; ++j) + //{ + //double p3 = p2; + //p2 = p1; + //p1 = ((2*j-1)*z*p2 - (j-1)*p3)/j; + //} + //double pp = n * (z*p1 - p2) / (z*z - 1); + + //w[i] = 2 / ((1 - z*z) * pp * pp); + //w[n-1-i] = w[i]; + //} +//} +void NievesQELCCPXSec::InitGaussLegendre(int n, std::vector& x, std::vector& w) +{ + // assume: n is even + int m = n / 2; + + x.resize(m); + w.resize(m); + + const double eps = 1e-14; + + for (int i = 0; i < m; ++i) + { + double z = TMath::Cos(kPi * (i + 0.75) / (n + 0.5)); + double z1; + + double p1, p2, pp; + + do + { + p1 = 1.0; + p2 = 0.0; + + for (int j = 1; j <= n; ++j) + { + double p3 = p2; + p2 = p1; + p1 = ((2*j - 1)*z*p2 - (j - 1)*p3) / j; + } + + pp = n * (z*p1 - p2) / (z*z - 1); + + z1 = z; + z = z1 - p1 / pp; + + } while (TMath::Abs(z - z1) > eps); + + // we keep only the positive root + x[i] = z; + + // weight (we use the already calculated pp!) + w[i] = 2.0 / ((1.0 - z*z) * pp * pp); + } +} diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 04f30c3ac7..f2186cb1b4 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -32,13 +32,20 @@ #include "Framework/EventGen/XSecAlgorithmI.h" #include "Physics/QuasiElastic/XSection/QELFormFactors.h" #include "Physics/NuclearState/FermiMomentumTable.h" -#include #include #include "Physics/NuclearState/NuclearModelI.h" #include "Physics/NuclearState/PauliBlocker.h" #include "Physics/QuasiElastic/XSection/QELUtils.h" #include "Physics/Common/QvalueShifter.h" +#include +#include + + +#include +#include +#include + namespace genie { typedef enum EQELRmax { @@ -65,12 +72,12 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; const TVector3 & FinalLeptonPolarization (const Interaction* i) const; - double IntegratedOverMomentum (const Interaction* i, double r, int mod) const; void ModelNuclParams(const Interaction* interaction, double r, double & kFi, double & kFf) const; // Override the Algorithm::Configure methods to load configuration // data to private data members void Configure (const Registry & config); void Configure (string param_set); + double IntegratedOverMomentum (const Interaction* i, double r, int mod) const; private: void LoadConfig (void); @@ -90,17 +97,15 @@ class NievesQELCCPXSec : public XSecAlgorithmI { const QvalueShifter * fQvalueShifter ; ///< Optional algorithm to retrieve the qvalue shift for a given target double fhbarc; ///< hbar*c in GeV*fm - + + std::vector fGLPoints; + std::vector fGLWeights; + int fNumGLPoints; + // mutable for testing purposes only! mutable bool fRPA; ///< use RPA corrections bool fCoulomb; ///< use Coulomb corrections - const NuclearModelI* fNuclModel; ///< Nuclear Model for integration - // Detect whether the nuclear model is local Fermi gas, and store - // the relativistic Fermi momentum table if not - bool fLFG; - const FermiMomentumTable * fKFTable; - string fKFTableName; string fLindhardFunction; /// Enum specifying the method to use when calculating the binding energy of @@ -129,6 +134,11 @@ class NievesQELCCPXSec : public XSecAlgorithmI { Nieves_Coulomb_Rmax_t fCoulombRmaxMode; //Functions needed to calculate XSec: + void InitGaussLegendre(int n, std::vector& x, std::vector& w); + double IntegratedOverMomentumAll(const Interaction*, double, + double* RPL = nullptr, + double* RPP = nullptr, + double* R = nullptr) const; // Calculates values of CN, CT, CL, and imU, and stores them in the provided // variables. If target is not a nucleus, then CN, CN, and CL are all 1.0. @@ -165,6 +175,16 @@ class NievesQELCCPXSec : public XSecAlgorithmI { const TLorentzVector outNucleonMom, double M, bool is_neutrino, const Target& target, bool assumeFreeNucleon) const; + + // ---------------------------------------- + // вспомогательная функция времени + // ---------------------------------------- + double Now() const + { + using namespace std::chrono; + return duration(high_resolution_clock::now().time_since_epoch()).count(); + } + }; } // genie namespace diff --git a/src/Physics/QuasiElastic/XSection/NievesQELException.cxx b/src/Physics/QuasiElastic/XSection/NievesQELException.cxx index dfc73c93ce..ec9efad776 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELException.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELException.cxx @@ -46,15 +46,28 @@ NievesQELException::~NievesQELException() void NievesQELException::Init(void) { fReason = ""; + fIsConfigError = false; } //___________________________________________________________________________ void NievesQELException::Copy(const NievesQELException & exc) { fReason = exc.fReason; + fIsConfigError = exc.fIsConfigError; } //___________________________________________________________________________ void NievesQELException::Print(ostream & stream) const { - stream << "**EXCEPTION Reason: " << this->ShowReason() << endl; + stream << "**NievesQELException"; + + if (fIsConfigError) + { + stream << " [CONFIG ERROR]"; + } + else + { + stream << " [KINEMATICS]"; + } + + stream << ": " << this->ShowReason() << endl; } //___________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELException.h b/src/Physics/QuasiElastic/XSection/NievesQELException.h index 2bf43e1a4d..ba4fd1ebe5 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELException.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELException.h @@ -3,13 +3,15 @@ \class genie::exceptions::NievesQELException -\brief An exception thrown by NievesQELCCPXSec for kinematics problems. - When failure occurs, set xsec = 0. +\brief An exception thrown by NievesQELCCPXSec for kinematics problems + or invalid model configurations (e.g. incompatible nuclear model). + In case of kinematic failure, xsec is set to 0. Configuration errors + may prevent further calculation. \author Steve Dytman Univ. of Pittsburgh - Joe Johnston + Joe Johnston Univ. of Pittsburgh \created June 2015 @@ -25,8 +27,6 @@ #include #include -#include - using std::string; using std::ostream; @@ -40,9 +40,11 @@ public : NievesQELException(const NievesQELException & exception); ~NievesQELException(); - void SetReason(string reason) { fReason = reason; } + void SetReason(const string & reason) { fReason = reason; } string ShowReason(void) const { return fReason; } + void SetIsConfigError(bool v = true) { fIsConfigError = v; } + bool IsConfigError() const { return fIsConfigError; } void Init (void); void Copy (const NievesQELException & exception); @@ -54,6 +56,7 @@ public : private: string fReason; + bool fIsConfigError = false; }; } // exceptions namespace diff --git a/src/Physics/QuasiElastic/XSection/libGPhQELXS682a3e2da9_dictContent.h b/src/Physics/QuasiElastic/XSection/libGPhQELXS682a3e2da9_dictContent.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Physics/QuasiElastic/XSection/libGPhQELXS6a99ba76fa_dictUmbrella.h b/src/Physics/QuasiElastic/XSection/libGPhQELXS6a99ba76fa_dictUmbrella.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Physics/QuasiElastic/XSection/libGPhQELXSb26666628a_dictUmbrella.h b/src/Physics/QuasiElastic/XSection/libGPhQELXSb26666628a_dictUmbrella.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Physics/QuasiElastic/XSection/libGPhQELXScacac3b134_dictContent.h b/src/Physics/QuasiElastic/XSection/libGPhQELXScacac3b134_dictContent.h new file mode 100644 index 0000000000..e69de29bb2 From f79d0b3b444b6103ce23bb8ee9693c5e92938f74 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 19 Mar 2026 20:43:50 +0300 Subject: [PATCH 74/78] Refactor and optimize radial integration (Gauss-Legendre) --- config/NievesQELCCXSec.xml | 9 - .../XSection/NievesQELCCPXSec.cxx | 540 ++---------------- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 87 +-- .../QuasiElastic/XSection/NievesQELCCXSec.cxx | 7 +- .../QuasiElastic/XSection/NievesQELCCXSec.h | 21 - .../libGPhQELXS682a3e2da9_dictContent.h | 0 .../libGPhQELXS6a99ba76fa_dictUmbrella.h | 0 .../libGPhQELXSb26666628a_dictUmbrella.h | 0 .../libGPhQELXScacac3b134_dictContent.h | 0 9 files changed, 49 insertions(+), 615 deletions(-) delete mode 100644 src/Physics/QuasiElastic/XSection/libGPhQELXS682a3e2da9_dictContent.h delete mode 100644 src/Physics/QuasiElastic/XSection/libGPhQELXS6a99ba76fa_dictUmbrella.h delete mode 100644 src/Physics/QuasiElastic/XSection/libGPhQELXSb26666628a_dictUmbrella.h delete mode 100644 src/Physics/QuasiElastic/XSection/libGPhQELXScacac3b134_dictContent.h diff --git a/config/NievesQELCCXSec.xml b/config/NievesQELCCXSec.xml index 64157bc8f2..8574e4f662 100644 --- a/config/NievesQELCCXSec.xml +++ b/config/NievesQELCCXSec.xml @@ -14,10 +14,6 @@ gsl-integration-type string Yes name of GSL numerical integrat gsl-max-eval int Yes GSL maximal number of function calls 1000000 gsl-min-eval int Yes GSL minimal number of function calls 7500 gsl-relative-tolerance double Yes relative tolerance of integration 1e-4 - -gsl-1dim-integration-type string Yes name of GSL numerical integrator adaptive -gsl-1dim-max-eval int Yes GSL maximal number of function calls 1000000 -gsl-1dim-relative-tolerance double Yes relative tolerance of integration 1e-4 ..................................................................................................... --> @@ -26,11 +22,6 @@ gsl-1dim-relative-tolerance double Yes relative tolerance of integrat 1e-4 7500 1000000 - - adaptive - 1e-4 - 1000000 - diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 831e555b7c..e2ed858c6e 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include "Framework/Algorithm/AlgConfigPool.h" #include "Physics/XSectionIntegration/XSecIntegratorI.h" @@ -459,15 +457,9 @@ void NievesQELCCPXSec::LoadConfig(void) // - LlewellynSmith (RFG-based) LOG("Nieves", pERROR) - << "NievesQELCCPXSec requires a Local Fermi Gas (LFG) nuclear model " - << "as defined in Nieves et al., PRC 70, 055503 (2004). " - << "The current configuration is incompatible. " - << "For RFG-based calculations, use SmithMoniz or LlewellynSmith models."; + << "NievesQELCCPXSec requires a Local Fermi Gas (LFG) nuclear model."; exceptions::NievesQELException e; - e.SetReason( - "NievesQELCCPXSec requires LFG (PRC 70, 055503 (2004)). " - "For RFG use SmithMonizQELCCPXSec or LlewellynSmithQELCCPXSec." - ); + e.SetReason("NievesQELCCPXSec requires LFG."); e.SetIsConfigError(true); throw e; @@ -535,13 +527,8 @@ void NievesQELCCPXSec::LoadConfig(void) GetParamDef( "CoulombScale", fCoulombScale, 1.0 ); GetParamDef("NumOfIntegPoints", fNumGLPoints, 96); - this->InitGaussLegendre(fNumGLPoints, fGLPoints, fGLWeights); - AlgFactory * algf = AlgFactory::Instance(); - NievesQELCCXSec* nvi = dynamic_cast(algf->AdoptAlgorithm("genie::NievesQELCCXSec", "Default")); - f1DimIntgType = nvi->Get1DimIntgType(); - f1DimRelTol = nvi->Get1DimRelTol(); - f1DimMaxEval = nvi->Get1DimMaxEval(); + } //___________________________________________________________________________ @@ -850,7 +837,7 @@ double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const if (Rmax == 0) return 0; if(Rcurr >= Rmax) { - LOG("Nieves",pNOTICE) << "Radius greater than maximum radius for coulomb corrections." + LOG("Nieves", pNOTICE) << "Radius greater than maximum radius for coulomb corrections." << " Integrating to max radius."; Rcurr = Rmax; } @@ -858,16 +845,37 @@ double NievesQELCCPXSec::vcr(const Target * target, double Rcurr) const int A = target->A(); int Z = target->Z(); - ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELvcrIntegrand(Rcurr,A,Z); - ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( f1DimIntgType ); - ROOT::Math::Integrator ig(*func, ig_type, 0, f1DimRelTol, f1DimMaxEval); - double result = ig.Integral(0, Rmax); - delete func; - - // Multiply by Z to normalize densities to number of protons - // Multiply by hbarc to put result in GeV instead of fm - // Multiply by an extra configurable scaling factor that defaults to unity - return -kAem*4*kPi*result*fhbarc*fCoulombScale; + double Irhop = 0; + for (int i = 0; i < fNumGLPoints/2; ++i) + { + double xi = fGLPoints[i]; + double wi = fGLWeights[i]; + double weight = 0.5 * Rmax * wi; + // --- x = -xi --- + double r = 0.5 * Rmax * (1.0 - xi); + double rhop = Z*nuclear::Density(r, A); + if(r < Rcurr) + { + Irhop += weight * rhop*r*r/Rcurr; + } + else + { + Irhop += weight * rhop*r; + } + // --- x = +xi --- + r = 0.5 * Rmax * (1.0 + xi); + rhop = Z*nuclear::Density(r, A); + if(r < Rcurr) + { + Irhop += weight * rhop*r*r/Rcurr; + } + else + { + Irhop += weight * rhop*r; + } + } + + return -kAem*4*kPi*Irhop*fhbarc*fCoulombScale; } //____________________________________________________________________________ @@ -1078,76 +1086,6 @@ const Target& target, bool assumeFreeNucleon) const return real(sum); } - -//___________________________________________________________________________ -// Auxiliary scalar function for internal integration -//____________________________________________________________________________ -utils::gsl::wrap::NievesQELvcrIntegrand::NievesQELvcrIntegrand( - double Rcurr, int A, int Z): -ROOT::Math::IBaseFunctionOneDim() -{ - fRcurr = Rcurr; - fA = A; - fZ = Z; -} -//____________________________________________________________________________ -utils::gsl::wrap::NievesQELvcrIntegrand::~NievesQELvcrIntegrand() -{ - -} -//____________________________________________________________________________ -unsigned int utils::gsl::wrap::NievesQELvcrIntegrand::NDim(void) const -{ - return 1; -} -//____________________________________________________________________________ -double utils::gsl::wrap::NievesQELvcrIntegrand::DoEval(double rin) const -{ - double rhop = fZ*nuclear::Density(rin,fA); - if(rinIntegratedOverMomentum(interaction, rin, mod); -} -//____________________________________________________________________________ -ROOT::Math::IBaseFunctionOneDim * - utils::gsl::wrap::NievesQELSmithMonizIntegrand::Clone(void) const -{ - return new utils::gsl::wrap::NievesQELSmithMonizIntegrand(alg, interaction, mod); -} //____________________________________________________________________________ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { @@ -1161,51 +1099,7 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i double Rmax = MaximalRadius(&target); if (Rmax <= 0) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - double t_root = 0.0; - double t_gauss = 0.0; - double t0 = Now(); - ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( f1DimIntgType ); - ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 1); - ROOT::Math::Integrator ig(*func, ig_type, 0, f1DimRelTol, f1DimMaxEval); - double R = ig.Integral(0, Rmax); - delete func; - if (R == 0) - { - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; - } - - func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 2); - ig.SetFunction(*func); - double PLR = ig.Integral(0, Rmax); - delete func; - - func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 3); - ig.SetFunction(*func); - double PPR = ig.Integral(0, Rmax); - delete func; - - double PL = PLR/R; - double PP = PPR/R; - double t1 = Now(); - t_root += (t1 - t0); - - t0 = Now(); - -/* - double IRPL = 0, IRPP = 0, IR = 0; - for (int i = 0; i < fNumGLPoints; ++i) - { - double r = 0.5*Rmax*(1. + fGLPoints[i]); - double weight = 0.5*Rmax*fGLWeights[i]; - double RPL, RPP, R; - IntegratedOverMomentumAll(interaction, r, &RPL, &RPP, &R); - IRPL += weight * RPL; - IRPP += weight * RPP; - IR += weight * R; - } -*/ - double RPL, RPP; + double RPL, RPP, R; double IRPL = 0, IRPP = 0, IR = 0; for (int i = 0; i < fNumGLPoints/2; ++i) { @@ -1225,23 +1119,13 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i IRPP += weight * RPP; IR += weight * R; } - PL = IRPL/IR; - PP = IRPP/IR; - t1 = Now(); - t_gauss += (t1 - t0); - //---------------------------------------- - //запись в файл - //---------------------------------------- - std::ofstream out("integration_benchmark.txt", std::ios::app); - out << std::setprecision(15) << std::scientific; - out << "ROOT_time = " << t_root << " s\n"; - out << "GAUSS_time = " << t_gauss << " s\n"; - out << "ROOT_result = " << PL << " " << PP << "\n"; - out << "GAUSS_result= " << IRPL/IR << " " << IRPP/IR << "\n"; - out << "ROOT_time/GAUSS_time = " << t_root/t_gauss << " s\n"; - out << "ROOT_result - GAUSS_result = " << PL - IRPL/IR << " " << PP - IRPP/IR << "\n"; - out << "----------------------------------------\n"; - out.close(); + if (IR == 0) + { + fFinalLeptonPolarization.SetBit(kPolarizationUndef); + return fFinalLeptonPolarization; + } + double PL = IRPL/IR; + double PP = IRPP/IR; TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); TLorentzVector neutrinoMom = *tempNeutrino; @@ -1254,254 +1138,9 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); TVector3 Py = Pz.Cross(Px); fFinalLeptonPolarization = PP*Py + PL*Pz; - - //if (fFinalLeptonPolarization.Mag2()>1) return XSecAlgorithmI::FinalLeptonPolarization(interaction); return fFinalLeptonPolarization; -} -//___________________________________________________________________________________ -double NievesQELCCPXSec::IntegratedOverMomentum (const Interaction* interaction, double r, int mod) const -{ - // Get kinematics and init-state parameters - const Kinematics & kinematics = interaction -> Kine(); - const InitialState & init_state = interaction -> InitState(); - const Target & target = init_state.Tgt(); - - // HitNucMass() looks up the PDGLibrary (on-shell) value for the initial - // struck nucleon - double Mi_onshell = target.HitNucMass(); - - // On-shell mass of final nucleon (from PDGLibrary) - double Mf = interaction->RecoilNucleon()->Mass(); - - // Isoscalar mass of nucleon - double M = (Mi_onshell + Mf)/2; - - // Note that GetProbeP4 defaults to returning the probe 4-momentum in the - // struck nucleon rest frame, so we have to explicitly ask for the lab frame - // here - TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); - TLorentzVector neutrinoMom = *tempNeutrino; - delete tempNeutrino; - TLorentzVector leptonMom = kinematics.FSLeptonP4(); - double ml = interaction->FSPrimLepton()->Mass(); - double ml2 = ml*ml; - - - // Calculate Coulomb corrections - double PlLocal = leptonMom.P(); - - bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); - int sign = is_neutrino ? -1 : 1; - - double ElLocal = leptonMom.E(); - if ( fCoulomb ) - { - // Coulomb potential - double Vc = vcr(&target, r); - - // Outgoing lepton energy and momentum including Coulomb potential - double El = ElLocal; - ElLocal = El + sign*Vc; - - if ( ElLocal - ml <= 0 ) return 0; - - // The Coulomb correction factor blows up as pl -> 0. To guard against - // unphysically huge corrections here, require that the lepton kinetic energy - // (at infinity) is larger than the magnitude of the Coulomb potential - // (should be around a few MeV) - double KEl = El - ml; - if ( KEl <= TMath::Abs(Vc) ) return 0; - - // Local value of the lepton 3-momentum magnitude for the Coulomb correction - PlLocal = TMath::Sqrt(ElLocal*ElLocal - ml2); - - } - - double q0Tilde = neutrinoMom.E() - leptonMom.E(); - - - double kFi, kFf; - ModelNuclParams(interaction, r, kFi, kFf); - - - double EFi = TMath::Hypot(M, kFi); - double EFf = TMath::Hypot(M, kFf); - - int nucl_pdg_ini = target.HitNucPdg(); - bool tgtIsNucleus = target.IsNucleus(); - int A = target.A(); - int Z = target.Z(); - int N = target.N(); - bool hitNucIsProton = pdg::IsProton( nucl_pdg_ini ); - - - // This part of the code is strictly in accordance with the original Nieves' paper - double Mi = target.Mass(); - int Zf = (hitNucIsProton) ? Z - 1 : Z + 1; - PDGLibrary * pdglib = PDGLibrary::Instance(); - TParticlePDG * nucl_f = pdglib->Find( pdg::IonPdgCode(A, Zf) ); - double Q = 0; - if(nucl_f) Q = nucl_f -> Mass() - Mi; - double Q_LFG = EFf - EFi; - q0Tilde -= (Q - Q_LFG); - - // Shift the q0Tilde if required: - if( fQvalueShifter ) q0Tilde += q0Tilde * fQvalueShifter->Shift(*interaction) ; - - // If binding energy effects pull us into an unphysical region, return - // zero - if ( q0Tilde <= 0 ) return 0; - - // Note that we're working in the lab frame (i.e., the rest frame - // of the target nucleus). We can therefore use Nieves' explicit - // form of the Amunu tensor if we rotate the 3-momenta so that - // qTilde is in the +z direction - TVector3 neutrinoMom3 = neutrinoMom.Vect(); - TVector3 leptonMom3 = leptonMom.Vect(); - - // If Coulomb corrections are being used, adjust the lepton 3-momentum used - // to get q3VecTilde so that its magnitude matches the local - // Coulomb-corrected value calculated earlier. Note that, although the - // treatment of Coulomb corrections by Nieves et al. doesn't change the - // direction of the lepton 3-momentum, it *does* change the direction of the - // 3-momentum transfer, and so the correction should be applied *before* - // rotating coordinates into a frame where q3VecTilde lies along the positive - // z axis. - TVector3 leptonMomCoulomb3 = !fCoulomb ? leptonMom3: PlLocal*leptonMom3*(1/leptonMom3.Mag()); - TVector3 q3VecTilde = neutrinoMom3 - leptonMomCoulomb3; - // Calculate qTilde - TLorentzVector qTildeP4(0., 0., q3VecTilde.Mag(), q0Tilde); - double Q2tilde = -qTildeP4.Mag2(); - - // Check that Q2tilde > 0 (accounting for rounding errors) - if (Q2tilde < 0) return 0; - - // Store Q2tilde in the kinematic variable representing Q2. - // This will ensure that the form factors are calculated correctly - // using the de Forest prescription (Q2tilde instead of Q2). - interaction->KinePtr()->SetQ2(Q2tilde); - // Calculate form factors - fFormFactors.Calculate( interaction ); - - // Get the QEL form factors (were calculated before this method was called) - double F1V = 0.5*fFormFactors.F1V(); - double xiF2V = 0.5*fFormFactors.xiF2V(); - double FA = fFormFactors.FA(); - // According to Nieves' paper, Fp = 2.0*M*FA/(kPionMass2-q2), but Llewelyn- - // Smith uses Fp = 2.0*M^2*FA/(kPionMass2-q2), so I divide by M - // This gives units of GeV^-1 - double Fp = fFormFactors.Fp()/M; - - double CN(1), CT(1), CL(1); - if (fRPA) - { - CNCTCLimUcalc(qTildeP4, M, r, tgtIsNucleus, A, Z, N, - CN, CT, CL, interaction->TestBit(kIAssumeFreeNucleon) ); - } - - // Calculate auxiliary parameters - // Off shell mass of initial nucleon - double M2 = M*M; - double FA2 = FA*FA; - double F1V2 = F1V*F1V; - double xiF2V2 = xiF2V*xiF2V; - double q0 = qTildeP4.E(); - double dq = qTildeP4.Pz(); - double dq2 = dq*dq; - double q02 = q0*q0; - double q2 = q02 - dq2; - - double factor = PlLocal*ElLocal*r*r/dq; - - double c = q0/dq; - double d = q2/2/M/dq; - - double Elow = TMath::Max( EFf - q0, M*(c*d + TMath::Sqrt(1- c*c + d*d))/(1 - c*c) ); - double Eup = EFi; - - if (Elow >= Eup) return 0; - - double Elow2 = Elow*Elow; - double Elow3 = Elow*Elow2; - double Eup2 = Eup*Eup; - double Eup3 = Eup*Eup2; - - double b0 = factor*(Eup - Elow); - double b1 = factor/M/2*(Eup2 - Elow2); - double b2 = factor/M2/3*(Eup3 - Elow3); - - double a1 = b0; - double a2 = b2 - b0; - double a3 = c*c*b2 + 2*c*d*b1 + d*d*b0; - double a4 = b2; - double a5 = c*b2 + d*b1; - double a6 = c*b1 + d*b0; - double a7 = b1; - - double Ep = M*a7; - double Ep2 = M2*a4; - double px2 = 0.5*M2*(a2 - a3); //py2=px2 - double pz = M*a6; - double Eppz = M2*a5; - double pz2 = M2*a3; - - double aux = 2*CL*Fp*(Fp*q2 + 4*FA*M); - double W00 = 32*F1V2*(Ep2*CN + Ep*q0 + a1*q2/4)+ - 8*q2*xiF2V2*(a1*(1 - q02*(1/q2 + 1/M2/4)) - Ep2/M2 - Ep*q0/M2) + - 8*FA2*(Ep2 + Ep*q0 + a1*(q2/4 - M2)) - a1*(aux*q02 + 16*F1V*xiF2V*(q02 - q2)*CN); - double Wxx = 32*F1V2*(px2 - a1*q2/4) - 8*q2*xiF2V2*(a1*CT + px2/M2) + - 8*FA2*(px2 + a1*(CT*M2 - q2/4)) - 16*a1*F1V*xiF2V*CT*q2; - double Wzz = 32*F1V2*(pz2 + pz*dq - a1*q2/4)- - 8*q2*xiF2V2*(a1 + pz2/M2 + pz*dq/M2 + a1*dq2*(1/q2 + 1/M2/4))+ - 8*FA2*(pz2 + pz*dq + a1*(CL*M2 - q2/4)) - a1*(aux*dq2 + 16*F1V*xiF2V*q02); - double ReW0z = 16*F1V2*((2*Eppz + Ep*dq)*CN + pz*q0) - -4*q2*xiF2V2*(2*Eppz/M2 + (Ep*dq + pz*q0)/M2 + a1*dq*q0*(2/q2 + 1/M2/2))+ - 4*FA2*((2*Eppz + Ep*dq)*CL + pz*q0) - a1*dq*q0*(aux + 16*F1V*xiF2V); - double ImWxy = -16*FA*(xiF2V+F1V)*(pz*q0 - Ep*dq*CT); - - - TLorentzVector q4 = neutrinoMom - leptonMom; - double v = q4.E(); - double v2 = v*v; - double qv2 = q4.Vect().Mag2(); - double qv = TMath::Sqrt(qv2); - - // Naumov definitions - double W1 = Wxx; - double W2 = W00 + Wxx + v2/qv2*(Wzz - Wxx) - 2*v/qv*ReW0z; - double W3 = -2*ImWxy/qv; - double W4 = (Wzz - Wxx)/qv2; - double W5 = 2*(ReW0z - v/qv*(Wzz - Wxx))/qv; - - double Ev = neutrinoMom.E(); - double El = leptonMom.E(); - double Pl = leptonMom.P(); - double cost = TMath::Cos( neutrinoMom.Angle(leptonMom.Vect()) ); - double sint = TMath::Sqrt(1 - cost*cost); - - double auxm = (El - Pl*cost)/2; - double auxp = (El + Pl*cost)/2; - double aux1m = (Pl - El*cost)/2; - double aux1p = (Pl + El*cost)/2; - double aux1 = ml2/2; - double aux2 = (Ev + El); - - if (mod == 2) return sign*(2*aux1m*(W1 - aux1*W4) + aux1p*W2 - sign*(aux2*aux1m + aux1*cost)*W3 - aux1*cost*W5); //PL*R - if (mod == 3) return sign*ml*sint*(2*W1 - W2 -sign*Ev*W3 - ml2*W4 + El*W5)/2; //PP*R - double R = 2*auxm*(W1 + aux1*W4) + auxp*W2 - sign*(aux2*auxm - aux1)*W3 - aux1*W5; - if (mod == 1) return R; - - // factor kPi2 comes from above definition of b; coloumb corrections factor also is taken into account - double extrafactor = kGF2*fCos8c2*TMath::Sq(kMw2/(kMw2 - q4.Mag2() ) )/El/4/kPi2; - - // Calculate d3XSec/dEldCosThetadR - double xsec = extrafactor*R; - xsec *= fXSecCCScale ; - - return xsec; - } //___________________________________________________________________________________ double NievesQELCCPXSec::IntegratedOverMomentumAll(const Interaction* interaction, double r, @@ -1762,28 +1401,6 @@ double NievesQELCCPXSec::d2XSec_dEldCosTheta(const Interaction* interaction) con double Rmax = MaximalRadius(&target); if (Rmax <= 0) return 0; -/* - double t_root = 0.0; - double t_gauss = 0.0; - double t0 = Now(); - ROOT::Math::IntegrationOneDim::Type ig_type = utils::gsl::Integration1DimTypeFromString( f1DimIntgType ); - ROOT::Math::IBaseFunctionOneDim * func = new utils::gsl::wrap::NievesQELSmithMonizIntegrand(this, interaction, 0); - ROOT::Math::Integrator ig(*func, ig_type, 0, f1DimRelTol, f1DimMaxEval); - double xsec = ig.Integral(0, Rmax); - delete func; - double t1 = Now(); - t_root += (t1 - t0); - t0 = Now(); - double Ixsec = 0; - //double RPL, RPP, R; - //for (int i = 0; i < fNumGLPoints; ++i) - //{ - //double r = 0.5*Rmax*(1. + fGLPoints[i]); - //double weight = 0.5*Rmax*fGLWeights[i]; - //double xsec = IntegratedOverMomentumAll(interaction, r, RPL, RPP, R); - //Ixsec += weight * xsec; - //} -*/ double Ixsec = 0; for (int i = 0; i < fNumGLPoints/2; ++i) { @@ -1799,34 +1416,6 @@ double NievesQELCCPXSec::d2XSec_dEldCosTheta(const Interaction* interaction) con xsec = IntegratedOverMomentumAll(interaction, r); Ixsec += weight * xsec; } -/* - t1 = Now(); - t_gauss += (t1 - t0); - - // ---------------------------------------- - // запись в файл - // ---------------------------------------- - double rel; - if (xsec > 0) - rel = TMath::Abs(Ixsec/xsec - 1); - else - rel = -1.; - if (rel > 5e-3) - { - std::ofstream out("integration_benchmark.txt", std::ios::app); - out << std::setprecision(15) << std::scientific; - out << "ROOT_time = " << t_root << " s\n"; - out << "GAUSS_time = " << t_gauss << " s\n"; - out << "ROOT_result = " << xsec*units::fm3/(1E-38*units::cm2) << "\n"; - out << "GAUSS_result= " << Ixsec*units::fm3/(1E-38*units::cm2) << "\n"; - out << "ROOT_time/GAUSS_time = " << t_root/t_gauss << " s\n"; - out << "abs = " << TMath::Abs(xsec - Ixsec)*units::fm3/(1E-38*units::cm2) << "\n"; - out << "rel = " << rel << "\n"; - out << "----------------------------------------\n"; - out.close(); - } - -*/ return Ixsec*units::fm3; } //___________________________________________________________________________________ @@ -1839,49 +1428,6 @@ void NievesQELCCPXSec::ModelNuclParams(const Interaction* interaction, double r, kFf = fPauliBlocker->GetFermiMomentum(target, interaction->RecoilNucleonPdg(), r); } //___________________________________________________________________________________ -//void NievesQELCCPXSec::InitGaussLegendre(int n, std::vector& x, std::vector& w) -//{ - //// calculation of Gauss-Legendre nodes and weights - //x.resize(n); - //w.resize(n); - - //int m = (n + 1) / 2; - //const double eps = 1e-14; - - //for (int i = 0; i < m; ++i) - //{ - //double z = TMath::Cos(kPi * (i + 0.75) / (n + 0.5)); - //double z1; - - //do - //{ - //double p1 = 1.0, p2 = 0.0; - //for (int j = 1; j <= n; ++j) { - //double p3 = p2; - //p2 = p1; - //p1 = ((2*j-1)*z*p2 - (j-1)*p3)/j; - //} - //double pp = n * (z*p1 - p2) / (z*z - 1); - //z1 = z; - //z = z1 - p1/pp; - //} while (TMath::Abs(z - z1) > eps); - - //x[i] = -z; - //x[n-1-i] = z; - - //double p1 = 1.0, p2 = 0.0; - //for (int j = 1; j <= n; ++j) - //{ - //double p3 = p2; - //p2 = p1; - //p1 = ((2*j-1)*z*p2 - (j-1)*p3)/j; - //} - //double pp = n * (z*p1 - p2) / (z*z - 1); - - //w[i] = 2 / ((1 - z*z) * pp * pp); - //w[n-1-i] = w[i]; - //} -//} void NievesQELCCPXSec::InitGaussLegendre(int n, std::vector& x, std::vector& w) { // assume: n is even diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index f2186cb1b4..0f7a696b19 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -32,7 +32,6 @@ #include "Framework/EventGen/XSecAlgorithmI.h" #include "Physics/QuasiElastic/XSection/QELFormFactors.h" #include "Physics/NuclearState/FermiMomentumTable.h" -#include #include "Physics/NuclearState/NuclearModelI.h" #include "Physics/NuclearState/PauliBlocker.h" #include "Physics/QuasiElastic/XSection/QELUtils.h" @@ -41,11 +40,6 @@ #include #include - -#include -#include -#include - namespace genie { typedef enum EQELRmax { @@ -72,12 +66,15 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + double IntegratedOverMomentumAll(const Interaction*, double, + double* RPL = nullptr, + double* RPP = nullptr, + double* R = nullptr) const; void ModelNuclParams(const Interaction* interaction, double r, double & kFi, double & kFf) const; // Override the Algorithm::Configure methods to load configuration // data to private data members void Configure (const Registry & config); void Configure (string param_set); - double IntegratedOverMomentum (const Interaction* i, double r, int mod) const; private: void LoadConfig (void); @@ -87,10 +84,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { const XSecIntegratorI * fXSecIntegrator; ///< double fCos8c2; ///< cos^2(cabibbo angle) - string f1DimIntgType; ///< Type of 1D integrator from NievesQELCCXSec config - double f1DimRelTol; ///< Relative tolerance for 1D integrator from NievesQELCCXSec config - unsigned int f1DimMaxEval; ///< Number of max evaluations for 1D integrator from NievesQELCCXSec config - + double fXSecCCScale; ///< external xsec scaling factor for CC double fXSecNCScale; ///< external xsec scaling factor for NC double fXSecEMScale; ///< external xsec scaling factor for EM @@ -135,10 +129,6 @@ class NievesQELCCPXSec : public XSecAlgorithmI { //Functions needed to calculate XSec: void InitGaussLegendre(int n, std::vector& x, std::vector& w); - double IntegratedOverMomentumAll(const Interaction*, double, - double* RPL = nullptr, - double* RPP = nullptr, - double* R = nullptr) const; // Calculates values of CN, CT, CL, and imU, and stores them in the provided // variables. If target is not a nucleus, then CN, CN, and CL are all 1.0. @@ -174,74 +164,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { const TLorentzVector inNucleonMom, const TLorentzVector leptonMom, const TLorentzVector outNucleonMom, double M, bool is_neutrino, const Target& target, bool assumeFreeNucleon) const; - - - // ---------------------------------------- - // вспомогательная функция времени - // ---------------------------------------- - double Now() const - { - using namespace std::chrono; - return duration(high_resolution_clock::now().time_since_epoch()).count(); - } - - }; } // genie namespace -//____________________________________________________________________________ -/*! -\class genie::utils::gsl::wrap::NievesQELIntegrand - -\brief Auxiliary scalar function for integration over the nuclear density - when calculaing the Coulomb correction in the Nieves QEL xsec model - -\author Joe Johnston, University of Pittsburgh - Steven Dytman, University of Pittsburgh - -\created June 03, 2016 -*/ -//____________________________________________________________________________ - -namespace genie { - namespace utils { - namespace gsl { - namespace wrap { - - class NievesQELvcrIntegrand : public ROOT::Math::IBaseFunctionOneDim - { - public: - NievesQELvcrIntegrand(double Rcurr, int A, int Z); - ~NievesQELvcrIntegrand(); - // ROOT::Math::IBaseFunctionOneDim interface - unsigned int NDim (void) const; - double DoEval (double rin) const; - ROOT::Math::IBaseFunctionOneDim * Clone (void) const; - private: - double fRcurr; - double fA; - double fZ; - }; - - class NievesQELSmithMonizIntegrand : public ROOT::Math::IBaseFunctionOneDim - { - public: - NievesQELSmithMonizIntegrand(const NievesQELCCPXSec* alg_, const Interaction* interaction_, int mod_); - ~NievesQELSmithMonizIntegrand(); - // ROOT::Math::IBaseFunctionOneDim interface - unsigned int NDim (void) const; - double DoEval (double rin) const; - ROOT::Math::IBaseFunctionOneDim * Clone (void) const; - private: - const NievesQELCCPXSec* alg; - const Interaction* interaction; - int mod; - }; - - } // wrap namespace - } // gsl namespace - } // utils namespace -} // genie namespace - - #endif diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx index d26169de16..8f708af991 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.cxx @@ -84,11 +84,6 @@ void NievesQELCCXSec::LoadConfig(void) int min; GetParamDef( "gsl-min-eval", min, 7500 ) ; fGSLMinEval = static_cast( min ); - - GetParamDef( "gsl-1dim-integration-type", fGSL1DimIntgType, std::string("adaptive") ); - GetParamDef( "gsl-1dim-relative-tolerance", fGSL1DimRelTol, 1e-4 ); - GetParamDef( "gsl-1dim-max-eval", max, 1000000 ); - fGSL1DimMaxEval = static_cast( max ); } //____________________________________________________________________________ // GSL wrappers @@ -150,7 +145,7 @@ double genie::utils::gsl::d3XSec_dQ2dvdR_E::DoEval(const double * xin) const double sinTl = TMath::Sqrt(1 - cosTl*cosTl); fKinematics->SetFSLeptonP4(Pl*sinTl, 0, Pl*cosTl, El); - double xsec = fXsec_model->IntegratedOverMomentum(fInteraction, R, 0); + double xsec = fXsec_model->IntegratedOverMomentumAll(fInteraction, R); // Jacobian for transformation d/dEldcosT->d/dQ2dv double J = (rQ2.max - rQ2.min)*(rv.max - rv.min)*fRmax/2/fEnu/Pl; diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h index cc22391a40..4e76dcfc48 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCXSec.h @@ -24,7 +24,6 @@ #include "Physics/QuasiElastic/XSection/SmithMonizUtils.h" #include "Physics/QuasiElastic/XSection/NievesQELCCPXSec.h" -#include #include #include @@ -39,21 +38,6 @@ class NievesQELCCXSec : public XSecIntegratorI { /// XSecIntegratorI interface implementation double Integrate(const XSecAlgorithmI* model, const Interaction* i) const; - std::string Get1DimIntgType() const - { - return fGSL1DimIntgType; - } - - unsigned int Get1DimMaxEval() const - { - return fGSL1DimMaxEval; - } - - double Get1DimRelTol() const - { - return fGSL1DimRelTol; - } - /// Overload the Algorithm::Configure() methods to load private data /// members from configuration options void Configure(const Registry& config); @@ -67,11 +51,6 @@ class NievesQELCCXSec : public XSecIntegratorI { std::string fGSLIntgType; double fGSLRelTol; unsigned int fGSLMaxEval; - - std::string fGSL1DimIntgType; - double fGSL1DimRelTol; - unsigned int fGSL1DimMaxEval; - }; class XSecAlgorithmI; diff --git a/src/Physics/QuasiElastic/XSection/libGPhQELXS682a3e2da9_dictContent.h b/src/Physics/QuasiElastic/XSection/libGPhQELXS682a3e2da9_dictContent.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Physics/QuasiElastic/XSection/libGPhQELXS6a99ba76fa_dictUmbrella.h b/src/Physics/QuasiElastic/XSection/libGPhQELXS6a99ba76fa_dictUmbrella.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Physics/QuasiElastic/XSection/libGPhQELXSb26666628a_dictUmbrella.h b/src/Physics/QuasiElastic/XSection/libGPhQELXSb26666628a_dictUmbrella.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/Physics/QuasiElastic/XSection/libGPhQELXScacac3b134_dictContent.h b/src/Physics/QuasiElastic/XSection/libGPhQELXScacac3b134_dictContent.h deleted file mode 100644 index e69de29bb2..0000000000 From f9ba4284a5ab5479352cf260dced9bb90912e688 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Fri, 20 Mar 2026 01:41:23 +0300 Subject: [PATCH 75/78] remove remarks --- src/Physics/Common/PrimaryLeptonUtils.cxx | 6 ------ .../Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx | 5 ----- src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx | 5 ----- src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx | 5 ----- src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx | 5 ----- src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 5 ----- src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx | 4 ---- 7 files changed, 35 deletions(-) diff --git a/src/Physics/Common/PrimaryLeptonUtils.cxx b/src/Physics/Common/PrimaryLeptonUtils.cxx index ccbc1279db..9828f4da47 100644 --- a/src/Physics/Common/PrimaryLeptonUtils.cxx +++ b/src/Physics/Common/PrimaryLeptonUtils.cxx @@ -173,9 +173,6 @@ void genie::utils::CalculatePolarizationVectorWithNuclearTensor( TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); TVector3 Py = Pz.Cross(Px); polarization = PT*Px + PP*Py + PL*Pz; - //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - //std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << "\n"; - //std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; } //____________________________________________________________________________ void genie::utils::CalculatePolarizationVectorWithStructureFunctions( @@ -289,9 +286,6 @@ void genie::utils::CalculatePolarizationVectorInTargetRestFrame( TVector3 Px = neutrinoMomTRF3.Cross(leptonMomTRF3).Unit(); TVector3 Py = Pz.Cross(Px); polarization = PT*Px + PP*Py + PL*Pz; - //std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; - //std::cout << "PL = " << PL << ", PP = " << PP << ", PT = " << PT << ", R = " << R << "\n"; - //std::cout << "UT@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; } //____________________________________________________________________________ diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index b998eb342b..075e825fa1 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -755,10 +755,5 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int is_neutrino, M, W1,W2,W3,W4,W5,0); - -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// std::cout << fFinalLeptonPolarization.Mag() << "\n"; -// std::cout << "NVMEC@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - return fFinalLeptonPolarization; } diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index af0d5d3696..d907129b8f 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -597,10 +597,5 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int is_neutrino, M, W1,W2,W3,W4,W5,0); - -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// std::cout << fFinalLeptonPolarization.Mag() << "\n"; -// std::cout << "SU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - return fFinalLeptonPolarization; } diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index bc94002e20..0fc9ec5839 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -630,10 +630,5 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio is_neutrino, W1,W2,W3,W4,W5,0); -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// fFinalLeptonPolarization.Print(); -// std::cout << fFinalLeptonPolarization.Mag() << "\n"; -// std::cout << "LW@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - return fFinalLeptonPolarization; } diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index 2855158f79..bf9e17571a 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -669,11 +669,6 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio leptonMom, is_neutrino, m_tar, T1,T2,T3,T4,T5,0); - - -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// std::cout << fFinalLeptonPolarization.Mag() << "\n"; -// std::cout << "SM@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; return fFinalLeptonPolarization; } diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 5d3ad5ec3e..1d5722cc1a 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -1209,10 +1209,5 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int is_neutrino, M, W1,W2,W3,W4,W5,0); - -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// std::cout << fFinalLeptonPolarization.Mag() << "\n"; -// std::cout << "SU@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - return fFinalLeptonPolarization; } diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx index cb5d5dd6b2..9de2ea6f94 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx @@ -308,9 +308,5 @@ const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* W1,W2,W3,0,0,0); -// std::cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"; -// std::cout << fFinalLeptonPolarization.Mag() << "\n"; -// std::cout << "PL@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" << std::endl; - return fFinalLeptonPolarization; } From c4f31311c95bcb688fc652f73fc3035fb30aaabb Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Tue, 31 Mar 2026 02:21:07 +0300 Subject: [PATCH 76/78] fix memory leak --- src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index e2ed858c6e..2b9959f316 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1170,7 +1170,9 @@ double NievesQELCCPXSec::IntegratedOverMomentumAll(const Interaction* interactio // Note that GetProbeP4 defaults to returning the probe 4-momentum in the // struck nucleon rest frame, so we have to explicitly ask for the lab frame // here - TLorentzVector neutrinoMom = *init_state.GetProbeP4(kRfLab); + TLorentzVector* tempNeutrino = init_state.GetProbeP4(kRfLab); + TLorentzVector neutrinoMom = *tempNeutrino; + delete tempNeutrino; TLorentzVector leptonMom = kinematics.FSLeptonP4(); double ml = interaction->FSPrimLepton()->Mass(); double ml2 = ml*ml; From 5627e9efc46ca81ba0ff69a83622bfc040f73b73 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 9 Apr 2026 03:26:53 +0300 Subject: [PATCH 77/78] return polarization by value instead of reference; remove internal storage and simplify interface --- .../EventGen/HybridXSecAlgorithm.cxx | 9 ++-- src/Framework/EventGen/HybridXSecAlgorithm.h | 2 +- src/Framework/EventGen/XSecAlgorithmI.cxx | 23 +++++---- src/Framework/EventGen/XSecAlgorithmI.h | 10 +++- .../XSection/NievesSimoVacasMECPXSec2016.cxx | 43 ++++++++-------- .../XSection/NievesSimoVacasMECPXSec2016.h | 2 +- .../Multinucleon/XSection/SuSAv2MECPXSec.cxx | 31 +++++------ .../Multinucleon/XSection/SuSAv2MECPXSec.h | 2 +- .../XSection/LwlynSmithQELCCPXSec.cxx | 23 +++++---- .../XSection/LwlynSmithQELCCPXSec.h | 2 +- .../XSection/NievesQELCCPXSec.cxx | 18 ++++--- .../QuasiElastic/XSection/NievesQELCCPXSec.h | 2 +- .../QuasiElastic/XSection/RosenbluthPXSec.cxx | 7 +-- .../QuasiElastic/XSection/RosenbluthPXSec.h | 2 +- .../XSection/SmithMonizQELCCPXSec.cxx | 15 +++--- .../XSection/SmithMonizQELCCPXSec.h | 2 +- .../QuasiElastic/XSection/SuSAv2QELPXSec.cxx | 51 ++++++++++--------- .../QuasiElastic/XSection/SuSAv2QELPXSec.h | 2 +- .../Strange/XSection/PaisQELLambdaPXSec.cxx | 11 ++-- .../Strange/XSection/PaisQELLambdaPXSec.h | 2 +- 20 files changed, 138 insertions(+), 121 deletions(-) diff --git a/src/Framework/EventGen/HybridXSecAlgorithm.cxx b/src/Framework/EventGen/HybridXSecAlgorithm.cxx index d117528e02..5eb6222ca5 100644 --- a/src/Framework/EventGen/HybridXSecAlgorithm.cxx +++ b/src/Framework/EventGen/HybridXSecAlgorithm.cxx @@ -139,12 +139,11 @@ void HybridXSecAlgorithm::LoadConfig(void) } } //____________________________________________________________________________ -const TVector3 & HybridXSecAlgorithm::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 HybridXSecAlgorithm::FinalLeptonPolarization (const Interaction* interaction) const { const XSecAlgorithmI* alg_to_use = this->ChooseXSecAlg( *interaction ); - - if ( !alg_to_use ) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - - return alg_to_use->FinalLeptonPolarization( interaction ); + return alg_to_use + ? alg_to_use->FinalLeptonPolarization(interaction) + : XSecAlgorithmI::FinalLeptonPolarization(interaction); } //____________________________________________________________________________ diff --git a/src/Framework/EventGen/HybridXSecAlgorithm.h b/src/Framework/EventGen/HybridXSecAlgorithm.h index 9416c7397b..a58f8b17b2 100644 --- a/src/Framework/EventGen/HybridXSecAlgorithm.h +++ b/src/Framework/EventGen/HybridXSecAlgorithm.h @@ -44,7 +44,7 @@ class HybridXSecAlgorithm : public XSecAlgorithmI { double XSec(const Interaction* i, KinePhaseSpace_t k) const; double Integral(const Interaction* i) const; bool ValidProcess(const Interaction* i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; // override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Framework/EventGen/XSecAlgorithmI.cxx b/src/Framework/EventGen/XSecAlgorithmI.cxx index c36322682f..def2fb1e62 100644 --- a/src/Framework/EventGen/XSecAlgorithmI.cxx +++ b/src/Framework/EventGen/XSecAlgorithmI.cxx @@ -18,21 +18,18 @@ using namespace genie; XSecAlgorithmI::XSecAlgorithmI() : Algorithm() { - fFinalLeptonPolarization = TVector3(0, 0, 0); fIsPreciseLeptonPolarization = false; } //___________________________________________________________________________ XSecAlgorithmI::XSecAlgorithmI(string name) : Algorithm(name) { - fFinalLeptonPolarization = TVector3(0, 0, 0); fIsPreciseLeptonPolarization = false; } //___________________________________________________________________________ XSecAlgorithmI::XSecAlgorithmI(string name, string config) : Algorithm(name, config) { - fFinalLeptonPolarization = TVector3(0, 0, 0); fIsPreciseLeptonPolarization = false; } //___________________________________________________________________________ @@ -61,24 +58,30 @@ bool XSecAlgorithmI::ValidKinematics(const Interaction* interaction) const return true; } //___________________________________________________________________________ -const TVector3 & XSecAlgorithmI::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 XSecAlgorithmI::FinalLeptonPolarization (const Interaction* interaction) const { + TVector3 pol(0, 0, 0); if ( interaction->ProcInfo().IsEM() ) { LOG("XSecBase", pWARN) << "For EM processes doesn't work yet."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } - fFinalLeptonPolarization.ResetBit(kPolarizationUndef); const Kinematics & kinematics = interaction -> Kine(); TLorentzVector leptonMom = kinematics.FSLeptonP4(); int pdg = interaction->FSPrimLeptonPdg(); - fFinalLeptonPolarization = leptonMom.Vect().Unit(); + TVector3 leptonMom3 = leptonMom.Vect(); + if (leptonMom3.Mag2() <= 0) + { + pol.SetBit(kPolarizationUndef); + return pol; + } + pol = leptonMom3.Unit(); if ( pdg::IsNeutrino(pdg) || pdg::IsElectron(pdg) || pdg::IsMuon(pdg) || pdg::IsTau(pdg) ) { - fFinalLeptonPolarization = -1.*fFinalLeptonPolarization; + pol *= -1.; } - return fFinalLeptonPolarization; + return pol; } //___________________________________________________________________________ diff --git a/src/Framework/EventGen/XSecAlgorithmI.h b/src/Framework/EventGen/XSecAlgorithmI.h index 9d9f3fc3f6..0870584a72 100644 --- a/src/Framework/EventGen/XSecAlgorithmI.h +++ b/src/Framework/EventGen/XSecAlgorithmI.h @@ -35,7 +35,14 @@ class XSecAlgorithmI : public Algorithm { //! Compute the cross section for the input interaction virtual double XSec (const Interaction* i, KinePhaseSpace_t k=kPSfE) const = 0; - virtual const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + /** + * Returns final lepton polarization. + * + * NOTE: + * The returned vector may have the kPolarizationUndef bit set. + * The caller MUST check this flag before using the value. + */ + virtual TVector3 FinalLeptonPolarization (const Interaction* i) const; //! Integrate the model over the kinematic phase space available to the //! input interaction (kinematical cuts can be included) @@ -52,7 +59,6 @@ class XSecAlgorithmI : public Algorithm { XSecAlgorithmI(string name); XSecAlgorithmI(string name, string config); - mutable TVector3 fFinalLeptonPolarization; bool fIsPreciseLeptonPolarization; }; diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx index 075e825fa1..9939afd621 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.cxx @@ -414,10 +414,11 @@ void NievesSimoVacasMECPXSec2016::LoadConfig(void) } //_________________________________________________________________________ -const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Interaction* interaction) const { - if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - fFinalLeptonPolarization.ResetBit(kPolarizationUndef); + if (!fIsPreciseLeptonPolarization) + return XSecAlgorithmI::FinalLeptonPolarization(interaction); + TVector3 pol(0, 0, 0); const Kinematics& kinematics = interaction -> Kine(); const InitialState& init_state = interaction -> InitState(); const Target& tgt = init_state.Tgt(); @@ -486,8 +487,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int MAXLOG("NievesSimoVacasMEC", pWARN, 10) << "Asked to scale to deuterium through boron " << target_pdg << " nope, lets not do that."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } else if (A_request >= 9 && A_request < 15) { @@ -529,8 +530,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int else { MAXLOG("NievesSimoVacasMEC", pWARN, 10) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } @@ -543,8 +544,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a" " hadronic tensor for the nuclide " << tensor_pdg; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } // Assume for now that the range of validity for the "FullAll" hadron @@ -557,8 +558,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int double Q3max = tensor->qMagMax(); if (Q0 < Q0min || Q0 > Q0max || Q3 < Q3min || Q3 > Q3max) { - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } // Get the Q-value needed to calculate the cross sections using the @@ -592,8 +593,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"DeltaAll\"" << " hadronic tensor for nuclide " << tensor_pdg; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } const LabFrameHadronTensorI* tensor_delta_pn @@ -604,8 +605,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"Deltapn\"" << " hadronic tensor for nuclide " << tensor_pdg; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } W1_all = tensor_delta_all->W1(Q0 - Q_value, Q3, M); @@ -629,8 +630,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"FullAll\"" << " hadronic tensor for nuclide " << tensor_pdg; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } const LabFrameHadronTensorI* tensor_full_pn @@ -641,8 +642,8 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int { LOG("NievesSimoVacasMEC", pWARN) << "Failed to load a \"Fullpn\"" << " hadronic tensor for nuclide " << tensor_pdg; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } W1_all = tensor_full_all->W1(Q0 - Q_value, Q3, M); @@ -749,11 +750,11 @@ const TVector3 & NievesSimoVacasMECPXSec2016::FinalLeptonPolarization (const Int bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); genie::utils::CalculatePolarizationVectorInTargetRestFrame( - fFinalLeptonPolarization, + pol, neutrinoMom, leptonMom, is_neutrino, M, W1,W2,W3,W4,W5,0); - return fFinalLeptonPolarization; + return pol; } diff --git a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h index 74104b4dcf..0af7ac5c46 100644 --- a/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h +++ b/src/Physics/Multinucleon/XSection/NievesSimoVacasMECPXSec2016.h @@ -49,7 +49,7 @@ class NievesSimoVacasMECPXSec2016 : public XSecAlgorithmI { double XSec (const Interaction * i, KinePhaseSpace_t k) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; // override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx index d907129b8f..ddc71ffd7c 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.cxx @@ -475,17 +475,18 @@ void SuSAv2MECPXSec::LoadConfig(void) } //_________________________________________________________________________ -const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* interaction) const { + TVector3 pol(0, 0, 0); const ProcessInfo& proc_info = interaction->ProcInfo(); if ( proc_info.IsEM() ) { LOG("SuSAv2MECPXSec", pWARN) << "For EM processes doesn't work yet."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } - if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - fFinalLeptonPolarization.ResetBit(kPolarizationUndef); + if (!fIsPreciseLeptonPolarization) + return XSecAlgorithmI::FinalLeptonPolarization(interaction); // Get the hadron tensor for the selected nuclide. Check the probe PDG code // to know whether to use the tensor for CC neutrino scattering or for // electron scattering @@ -502,8 +503,8 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int else { LOG("SuSAv2MECPXSec", pWARN) << "Doesn't work for processes other than weak ones."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } //else //{ @@ -526,8 +527,8 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int if ( !tensor ) { LOG("SuSAv2MEC", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } TLorentzVector * tempNeutrino = init_state.GetProbeP4(kRfLab); @@ -561,8 +562,8 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int double Q3max = tensor->qMagMax(); if (Q0-Delta_Q_value < Q0min || Q0-Delta_Q_value > Q0max || Q3 < Q3min || Q3 > Q3max) { - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } // *** Enforce the global Q^2 cut (important for EM scattering) *** @@ -578,8 +579,8 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int double Q2 = Q3*Q3 - Q0*Q0; if ( Q2 < Q2min ) { - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } @@ -591,11 +592,11 @@ const TVector3 & SuSAv2MECPXSec::FinalLeptonPolarization (const Interaction* int bool is_neutrino = pdg::IsNeutrino(init_state.ProbePdg()); genie::utils::CalculatePolarizationVectorInTargetRestFrame( - fFinalLeptonPolarization, + pol, neutrinoMom, leptonMom, is_neutrino, M, W1,W2,W3,W4,W5,0); - return fFinalLeptonPolarization; + return pol; } diff --git a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.h b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.h index a33d3e2398..dac8a6975a 100644 --- a/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.h +++ b/src/Physics/Multinucleon/XSection/SuSAv2MECPXSec.h @@ -49,7 +49,7 @@ class SuSAv2MECPXSec : public XSecAlgorithmI { double XSec(const Interaction* i, KinePhaseSpace_t k) const; double Integral(const Interaction* i) const; bool ValidProcess(const Interaction* i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; // override the Algorithm::Configure methods to load configuration diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx index 0fc9ec5839..2ba3e57682 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.cxx @@ -479,10 +479,11 @@ void LwlynSmithQELCCPXSec::LoadConfig(void) GetParamDef( "DoPauliBlocking", fDoPauliBlocking, true ); } //____________________________________________________________________________ -const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { - if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - fFinalLeptonPolarization.ResetBit(kPolarizationUndef); + if (!fIsPreciseLeptonPolarization) + return XSecAlgorithmI::FinalLeptonPolarization(interaction); + TVector3 pol(0, 0, 0); const QELFormFactorsModelI* qel_ff_mod = dynamic_cast (this->SubAlg("FormFactorsAlg")); const AlgId & qel_ff_mod_id = qel_ff_mod->Id(); std::string qel_ff_mod_name = qel_ff_mod_id.Name(); @@ -529,8 +530,8 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio if ( pNf < kF ) { LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } @@ -559,15 +560,15 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio if ( qTildeP4.E() < 0 && init_state.Tgt().IsNucleus() && !interaction->TestBit(kIAssumeFreeNucleon) ) { LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } double Q2tilde = -qTildeP4.Mag2(); if ( Q2tilde < 0 ) { LOG("LwlynSmith", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } // Store Q2tilde in the kinematic variable representing Q2. @@ -622,7 +623,7 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio double W5 = w05 + w15*r + w25*r2; CalculatePolarizationVectorWithStructureFunctions( - fFinalLeptonPolarization, + pol, neutrinoMom, leptonMom, inNucleonMom, @@ -630,5 +631,5 @@ const TVector3 & LwlynSmithQELCCPXSec::FinalLeptonPolarization (const Interactio is_neutrino, W1,W2,W3,W4,W5,0); - return fFinalLeptonPolarization; + return pol; } diff --git a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h index 5db08e9b75..93b77054b0 100644 --- a/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/LwlynSmithQELCCPXSec.h @@ -46,7 +46,7 @@ class LwlynSmithQELCCPXSec : public XSecAlgorithmI { double XSec (const Interaction * i, KinePhaseSpace_t k) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; // Override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx index 2b9959f316..e1914ec562 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.cxx @@ -1087,17 +1087,19 @@ const Target& target, bool assumeFreeNucleon) const return real(sum); } //____________________________________________________________________________ -const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { - if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - fFinalLeptonPolarization.ResetBit(kPolarizationUndef); + if (!fIsPreciseLeptonPolarization) + return XSecAlgorithmI::FinalLeptonPolarization(interaction); + TVector3 pol(0, 0, 0); // Get kinematics and init-state parameters const Kinematics & kinematics = interaction -> Kine(); const InitialState & init_state = interaction -> InitState(); const Target & target = init_state.Tgt(); double Rmax = MaximalRadius(&target); - if (Rmax <= 0) return XSecAlgorithmI::FinalLeptonPolarization(interaction); + if (Rmax <= 0) + return XSecAlgorithmI::FinalLeptonPolarization(interaction); double RPL, RPP, R; double IRPL = 0, IRPP = 0, IR = 0; @@ -1121,8 +1123,8 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i } if (IR == 0) { - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } double PL = IRPL/IR; double PP = IRPP/IR; @@ -1137,9 +1139,9 @@ const TVector3 & NievesQELCCPXSec::FinalLeptonPolarization (const Interaction* i TVector3 Pz = leptonMom3.Unit(); TVector3 Px = neutrinoMom3.Cross(leptonMom3).Unit(); TVector3 Py = Pz.Cross(Px); - fFinalLeptonPolarization = PP*Py + PL*Pz; + pol = PP*Py + PL*Pz; - return fFinalLeptonPolarization; + return pol; } //___________________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h index 0f7a696b19..4986d85655 100644 --- a/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/NievesQELCCPXSec.h @@ -65,7 +65,7 @@ class NievesQELCCPXSec : public XSecAlgorithmI { double d2XSec_dEldCosTheta (const Interaction * i) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; double IntegratedOverMomentumAll(const Interaction*, double, double* RPL = nullptr, double* RPP = nullptr, diff --git a/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.cxx b/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.cxx index aed4ed41f2..ea6721cfed 100644 --- a/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.cxx @@ -202,9 +202,10 @@ void RosenbluthPXSec::LoadConfig(void) assert(fXSecIntegrator); } //____________________________________________________________________________ -const TVector3 & RosenbluthPXSec::FinalLeptonPolarization (const Interaction* /*interaction*/) const +TVector3 RosenbluthPXSec::FinalLeptonPolarization (const Interaction* /*interaction*/) const { LOG("Rosenbluth", pWARN) << "For EM processes doesn't work yet."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + TVector3 pol(0, 0, 0); + pol.SetBit(kPolarizationUndef); + return pol; } diff --git a/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.h b/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.h index 62c4e6ba73..17ef3e422d 100644 --- a/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.h +++ b/src/Physics/QuasiElastic/XSection/RosenbluthPXSec.h @@ -40,7 +40,7 @@ class RosenbluthPXSec : public XSecAlgorithmI { double XSec (const Interaction * i, KinePhaseSpace_t k) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; // override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx index bf9e17571a..a83ad409ca 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.cxx @@ -523,10 +523,11 @@ double SmithMonizQELCCPXSec::dsQES_dQ2_SM(const Interaction * interaction) const 0.32516118713868835987e-1,0.32550614492363166242e-1}; } //____________________________________________________________________________ -const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interaction* interaction) const { - if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - fFinalLeptonPolarization.ResetBit(kPolarizationUndef); + if (!fIsPreciseLeptonPolarization) + return XSecAlgorithmI::FinalLeptonPolarization(interaction); + TVector3 pol(0, 0, 0); // Get kinematics & init-state parameters const Kinematics & kinematics = interaction -> Kine(); sm_utils->SetInteraction(interaction); @@ -566,8 +567,8 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio if (cosT_k < -1.0 || cosT_k > 1.0 ) { LOG("SmithMoniz", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } double P_Fermi = sm_utils->GetInitialFermiMomentum(); @@ -664,12 +665,12 @@ const TVector3 & SmithMonizQELCCPXSec::FinalLeptonPolarization (const Interactio double T5 = m_tar*(a5/qv - v*k4)*W2 + k5*W5; CalculatePolarizationVectorInTargetRestFrame( - fFinalLeptonPolarization, + pol, neutrinoMom, leptonMom, is_neutrino, m_tar, T1,T2,T3,T4,T5,0); - return fFinalLeptonPolarization; + return pol; } //____________________________________________________________________________ diff --git a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h index f9d7dc04cc..aeaa87ab85 100644 --- a/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h +++ b/src/Physics/QuasiElastic/XSection/SmithMonizQELCCPXSec.h @@ -62,7 +62,7 @@ class SmithMonizQELCCPXSec : public XSecAlgorithmI { double XSec (const Interaction * i, KinePhaseSpace_t kps) const; double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; // Override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx index 1d5722cc1a..f077abb589 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.cxx @@ -668,17 +668,18 @@ void SuSAv2QELPXSec::LoadConfig(void) } //_________________________________________________________________________ -const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* interaction) const { + TVector3 pol(0, 0, 0); const ProcessInfo& proc_info = interaction->ProcInfo(); if ( proc_info.IsEM() ) { LOG("SuSAv2QE", pWARN) << "For EM processes doesn't work yet."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } - if (!fIsPreciseLeptonPolarization || proc_info.IsWeakNC()) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - fFinalLeptonPolarization.ResetBit(kPolarizationUndef); + if (!fIsPreciseLeptonPolarization || proc_info.IsWeakNC()) + return XSecAlgorithmI::FinalLeptonPolarization(interaction); const Kinematics& kinematics = interaction -> Kine(); const InitialState& init_state = interaction -> InitState(); const Target& tgt = init_state.Tgt(); @@ -719,8 +720,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if ( Q2 < Q2min ) { LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } @@ -831,8 +832,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int else { LOG("SuSAv2QE", pWARN) << "Doesn't work for processes other than weak ones."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } double Eb_tgt=0; @@ -937,8 +938,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if ( !tensor_susa ) { LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } @@ -952,8 +953,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if ( !tensor_blen ) { LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } @@ -965,8 +966,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if ( !tensor_crpa ) { LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } @@ -1014,8 +1015,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if (Q0-Delta_Q_value_susa < Q0min || Q0-Delta_Q_value_susa > Q0max || Q3 < Q3min || Q3 > Q3max) { LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } else if ( modelConfig == kMd_CRPA || modelConfig == kMd_HF || @@ -1028,8 +1029,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if (Q0-Delta_Q_value_crpa < Q0min || Q0-Delta_Q_value_crpa > Q0max || Q3 < Q3min || Q3 > Q3max) { LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } else if ( modelConfig == kMd_SuSAv2Blend) @@ -1041,8 +1042,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if (Q0-Delta_Q_value_blen < Q0min || Q0-Delta_Q_value_blen > Q0max || Q3 < Q3min || Q3 > Q3max) { LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } else @@ -1054,8 +1055,8 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int if (Q0-Delta_Q_value_crpa < Q0min || Q0-Delta_Q_value_blen > Q0max || Q3 < Q3min || Q3 > Q3max) { LOG("SuSAv2QE", pWARN) << "Can't calculate final lepton polarization."; - fFinalLeptonPolarization.SetBit(kPolarizationUndef); - return fFinalLeptonPolarization; + pol.SetBit(kPolarizationUndef); + return pol; } } @@ -1203,11 +1204,11 @@ const TVector3 & SuSAv2QELPXSec::FinalLeptonPolarization (const Interaction* int } genie::utils::CalculatePolarizationVectorInTargetRestFrame( - fFinalLeptonPolarization, + pol, neutrinoMom, leptonMom, is_neutrino, M, W1,W2,W3,W4,W5,0); - return fFinalLeptonPolarization; + return pol; } diff --git a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.h b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.h index 7a20d6ff42..cdbb7f8478 100644 --- a/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.h +++ b/src/Physics/QuasiElastic/XSection/SuSAv2QELPXSec.h @@ -49,7 +49,7 @@ class SuSAv2QELPXSec : public XSecAlgorithmI { double XSec(const Interaction* i, KinePhaseSpace_t k) const; double Integral(const Interaction* i) const; bool ValidProcess(const Interaction* i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; // override the Algorithm::Configure methods to load configuration // data to private data members diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx index 9de2ea6f94..34d45fa7e2 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.cxx @@ -239,10 +239,11 @@ void PaisQELLambdaPXSec::LoadConfig(void) assert(fXSecIntegrator); } //____________________________________________________________________________ -const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* interaction) const +TVector3 PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* interaction) const { - if (!fIsPreciseLeptonPolarization) return XSecAlgorithmI::FinalLeptonPolarization(interaction); - fFinalLeptonPolarization.ResetBit(kPolarizationUndef); + if (!fIsPreciseLeptonPolarization) + return XSecAlgorithmI::FinalLeptonPolarization(interaction); + TVector3 pol(0, 0, 0); // First we need access to all of the particles in the interaction // The particles were stored in the lab frame //----- get kinematics & init state - compute auxiliary vars @@ -299,7 +300,7 @@ const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* double W3 = 2*FA*(F1V + xiF2V); CalculatePolarizationVectorWithStructureFunctions( - fFinalLeptonPolarization, + pol, neutrinoMom, leptonMom, inNucleonMom, @@ -308,5 +309,5 @@ const TVector3 & PaisQELLambdaPXSec::FinalLeptonPolarization (const Interaction* W1,W2,W3,0,0,0); - return fFinalLeptonPolarization; + return pol; } diff --git a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h index fd9d9a7a36..681a5434f8 100644 --- a/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h +++ b/src/Physics/Strange/XSection/PaisQELLambdaPXSec.h @@ -48,7 +48,7 @@ class PaisQELLambdaPXSec : public XSecAlgorithmI { double Integral (const Interaction * i) const; bool ValidProcess (const Interaction * i) const; bool ValidKinematics (const Interaction * i) const; - const TVector3 & FinalLeptonPolarization (const Interaction* i) const; + TVector3 FinalLeptonPolarization (const Interaction* i) const; //-- override the Algorithm::Configure methods to load configuration // data to private data members From c7fa0cd01016d7894fac2e29e726b96b3781ec50 Mon Sep 17 00:00:00 2001 From: Igor Kakorin Date: Thu, 9 Apr 2026 09:03:15 +0300 Subject: [PATCH 78/78] a minor fix --- src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx index 2e3d4dfa72..b283c396c7 100644 --- a/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx +++ b/src/Physics/QuasiElastic/EventGen/QELEventGeneratorSM.cxx @@ -462,7 +462,7 @@ double QELEventGeneratorSM::ComputeMaxXSec(const Interaction * interaction) cons { double xsec_max = -1; double tmp_xsec_max = -1; - double Q20, v0; + double Q20(0), v0(0); bool initialized = false; const int N_Q2 = 32; const InitialState & init_state = interaction -> InitState(); @@ -550,7 +550,7 @@ double QELEventGeneratorSM::ComputeMaxXSec(const Interaction * interaction, cons } double xsec_max = -1; double tmp_xsec_max = -1; - double Q20, v0; + double Q20(0), v0(0); bool initialized = false; const int N_Q2 = 32; const InitialState & init_state = interaction -> InitState();