diff --git a/config/EventGenerator.xml b/config/EventGenerator.xml
index d1a418a16..fed181a64 100644
--- a/config/EventGenerator.xml
+++ b/config/EventGenerator.xml
@@ -830,5 +830,15 @@ XSecModel alg Yes Cross section model used at the thread
+
+
+ 3
+ genie::InitialStateAppender/Default
+ genie::VertexGenerator/Default
+ genie::NormGenerator/Default
+ genie::NormInteractionListGenerator/Default
+ genie::NormXSec/Default
+
+
diff --git a/config/EventGeneratorListAssembler.xml b/config/EventGeneratorListAssembler.xml
index 30a19530f..b8704ac71 100644
--- a/config/EventGeneratorListAssembler.xml
+++ b/config/EventGeneratorListAssembler.xml
@@ -562,5 +562,16 @@ Generator-%d alg No
genie::EventGenerator/PhotonCOH
+
+ 1
+ genie::EventGenerator/NORM
+
+
+
+ 2
+ genie::EventGenerator/QEL-CC
+ genie::EventGenerator/NORM
+
+
diff --git a/config/NormGenerator.xml b/config/NormGenerator.xml
new file mode 100644
index 000000000..04bf65e21
--- /dev/null
+++ b/config/NormGenerator.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/NormInteractionListGenerator.xml b/config/NormInteractionListGenerator.xml
new file mode 100644
index 000000000..cc322ae6d
--- /dev/null
+++ b/config/NormInteractionListGenerator.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/NormXSec.xml b/config/NormXSec.xml
new file mode 100644
index 000000000..f18e0bcbc
--- /dev/null
+++ b/config/NormXSec.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/QELEventGeneratorSM.xml b/config/QELEventGeneratorSM.xml
index f60bfb170..0eadb84e1 100644
--- a/config/QELEventGeneratorSM.xml
+++ b/config/QELEventGeneratorSM.xml
@@ -4,28 +4,28 @@
Configuration for the QELEventGeneratorSM EventRecordVisitorI
Configurable Parameters:
-.............................................................................................................
-Name Type Optional Comment Default
-.............................................................................................................
-MaxXSec-SafetyFactor double Yes Safety factor for the maximum 1.2
- differential cross section
-MaxDiffv-SafetyFactor double Yes Safety factor for the maximum 1.2
- vmax(Q2)-vmin(Q2)
-MaxXSec-DiffTolerance double Yes Max allowed 200*(xsec-xsecmax)/(xsec+xsecmax) 999999.0
- if xsec>xsecmax
-UniformOverPhaseSpace bool Yes Kinematics uniformly over allowed phase space false
- wgt = (phase_space_volume)*(diff_xsec)/(xsec)
-IsNucleonInNucleus bool Yes Generate struck nucleon in nucleus true
-Threshold-Q2 double Yes Q2-threshold for seeking the second maximum 2.00
-Cache-MinEnergy double Yes min E for which maxxsec is cached - 1.00
- forcing explicit calc
+................................................................................................................................
+Name Type Optional Comment Default
+................................................................................................................................
+MaxXSec-SafetyFactor double Yes Safety factor: ComputeMaxXSec -> ComputeMaxXSec * MaxXSec-SafetyFactor 1.0
+Safety-Factors vec-double Yes Safety factors: MaxXSec[nkey] -> MaxXSec[nkey] * Safety-Factors[nkey] all 1.0
+Interpolator-Types vec-string Yes Type of interpolator for each key in a branch all ""
+MaxXSec-DiffTolerance double Yes Max allowed 200*(xsec-xsecmax)/(xsec+xsecmax) 999999.0
+ if xsec>xsecmax
+UniformOverPhaseSpace bool Yes Kinematics uniformly over allowed phase space false
+ wgt = (phase_space_volume)*(diff_xsec)/(xsec)
+IsNucleonInNucleus bool Yes Generate struck nucleon in nucleus true
+Threshold-Q2 double Yes Q2-threshold for seeking the second maximum 2.00
+Cache-MinEnergy double Yes min E for which maxxsec is cached - 1.00
+ forcing explicit calc
-->
-
+ 1.06; 1.06; 1.06
+ AKIMA; AKIMA; LINEAR
diff --git a/config/master_config.xml b/config/master_config.xml
index 4ff4ad940..048508c3f 100644
--- a/config/master_config.xml
+++ b/config/master_config.xml
@@ -264,4 +264,8 @@
EventLibraryInterface.xml
EvtLibInteractionListGenerator.xml
EvtLibPXSec.xml
+
+ NormGenerator.xml
+ NormXSec.xml
+ NormInteractionListGenerator.xml
diff --git a/src/Apps/gNtpConv.cxx b/src/Apps/gNtpConv.cxx
index b9443ca00..54ed2a16a 100644
--- a/src/Apps/gNtpConv.cxx
+++ b/src/Apps/gNtpConv.cxx
@@ -324,6 +324,7 @@ void ConvertToGST(void)
bool brIsMec = false; // Is MEC?
bool brIsDfr = false; // Is Diffractive?
bool brIsImd = false; // Is IMD?
+ bool brIsNrm = false; // Is Norm?
bool brIsSingleK = false; // Is single kaon?
bool brIsImdAnh = false; // Is IMD annihilation?
bool brIsNuEL = false; // Is ve elastic?
@@ -438,6 +439,7 @@ void ConvertToGST(void)
s_tree->Branch("coh", &brIsCoh, "coh/O" );
s_tree->Branch("dfr", &brIsDfr, "dfr/O" );
s_tree->Branch("imd", &brIsImd, "imd/O" );
+ s_tree->Branch("norm", &brIsNrm, "norm/O" );
s_tree->Branch("imdanh", &brIsImdAnh, "imdanh/O" );
s_tree->Branch("singlek", &brIsSingleK, "singlek/O" );
s_tree->Branch("nuel", &brIsNuEL, "nuel/O" );
@@ -657,9 +659,10 @@ void ConvertToGST(void)
bool is_mec = proc_info.IsMEC();
bool is_amnugamma = proc_info.IsAMNuGamma();
bool is_hnl = proc_info.IsHNLDecay();
-
+ bool is_norm = proc_info.IsNorm();
+
if (!hitnucl && neutrino) {
- assert(is_coh || is_imd || is_imdanh || is_nuel | is_amnugamma || is_coh_el || is_hnl);
+ assert(is_coh || is_imd || is_imdanh || is_nuel | is_amnugamma || is_coh_el || is_hnl || is_norm);
}
// Hit quark - set only for DIS events
@@ -954,6 +957,7 @@ void ConvertToGST(void)
brIsCoh = is_coh;
brIsDfr = is_dfr;
brIsImd = is_imd;
+ brIsNrm = is_norm;
brIsSingleK = is_singlek;
brIsNuEL = is_nuel;
brIsEM = is_em;
diff --git a/src/Framework/Conventions/KinePhaseSpace.h b/src/Framework/Conventions/KinePhaseSpace.h
index 59ad95638..c7806955e 100644
--- a/src/Framework/Conventions/KinePhaseSpace.h
+++ b/src/Framework/Conventions/KinePhaseSpace.h
@@ -24,7 +24,7 @@
using std::string;
namespace genie {
-
+// Note: please attach new phase space enum element to the end of the list .
typedef enum EKinePhaseSpace {
kPSNull = 0,
kPSfE,
@@ -72,7 +72,8 @@ typedef enum EKinePhaseSpace {
kPSlog10xlog10Q2fE,
kPSEDNufE, // Used for Dark Neutrinos, two body final state
kPSn1n2fE,
- kPSn1n2n3fE
+ kPSn1n2n3fE,
+ kPSQ2vpfE
} KinePhaseSpace_t;
class KinePhaseSpace
@@ -124,6 +125,7 @@ class KinePhaseSpace
case(kPSElOlTpifE) : return "<{El,Omega_l,Theta_pi}|E>"; break;
case(kPSTkTlctl) : return "<{Tk,Tl,cos(theta_l)}|E>"; break;
case(kPSQ2vfE) : return "<{Q2,v}|E>"; break;
+ case(kPSQ2vpfE) : return "<{Q2,v,p}|E>"; break;
// TODO: update this string when the appropriate kinematic variables are known
case(kPSQELEvGen) : return ""; break;
case(kPSDMELEvGen) : return ""; break;
diff --git a/src/Framework/EventGen/GMCJDriver.cxx b/src/Framework/EventGen/GMCJDriver.cxx
index f78fb91e8..2793f0625 100644
--- a/src/Framework/EventGen/GMCJDriver.cxx
+++ b/src/Framework/EventGen/GMCJDriver.cxx
@@ -652,9 +652,12 @@ void GMCJDriver::BootstrapXSecSplineSummation(void)
// bit above the maximum beam energy (but below the maximum valid energy)
// to avoid the evaluation of the cubic spline around the viscinity of
// knots with zero y values (although the GENIE Spline object handles it)
- double dE = fEmax/10.;
double min = rE.min;
- double max = (fEmax+dE < rE.max) ? fEmax+dE : rE.max;
+ double max = rE.max;
+
+ // Because of edge issue (see GENIE docdb 297) these lines are commented out
+ // double dE = fEmax/10.;
+ // double max = (fEmax+dE < rE.max) ? fEmax+dE : rE.max;
// in the logaritmic binning is important to have a narrow binning to
// describe better the glashow resonance peak.
diff --git a/src/Framework/GHEP/GHepRecord.cxx b/src/Framework/GHEP/GHepRecord.cxx
index 19f7ba2a0..3306cc170 100644
--- a/src/Framework/GHEP/GHepRecord.cxx
+++ b/src/Framework/GHEP/GHepRecord.cxx
@@ -1183,8 +1183,8 @@ void GHepRecord::Print(ostream & stream) const
case ( kPSQ2fE ) :
stream << " dsig(Q2;E)/dQ2 = " << setfill(' ') << setw(13) << fDiffXSec/units::cm2 << " cm^2/GeV^2 |";
break;
- case ( kPSQ2vfE ) :
- stream << " dsig(Q2,v;E)/dQ2dv = " << setfill(' ') << setw(13) << fDiffXSec/units::cm2 << " cm^2/GeV^3 |";
+ case ( kPSQ2vpfE ) :
+ stream << " dsig(Q2,v,p;E)/dQ2dvdp =" << setfill(' ') << setw(13) << fDiffXSec/units::cm2 << " cm^2/GeV^4 |";
break;
case ( kPSWQ2fE ) :
stream << " d2sig(W,Q2;E)/dWdQ2 = " << setfill(' ') << setw(13) << fDiffXSec/units::cm2 << " cm^2/GeV^3 |";
diff --git a/src/Framework/Interaction/KPhaseSpace.cxx b/src/Framework/Interaction/KPhaseSpace.cxx
index 2b8a75185..f5945f193 100644
--- a/src/Framework/Interaction/KPhaseSpace.cxx
+++ b/src/Framework/Interaction/KPhaseSpace.cxx
@@ -88,6 +88,8 @@ double KPhaseSpace::Threshold(void) const
if( ! pi.IsKnown() ) return 0;
+ if (pi.IsNorm() ) return 0;
+
if (pi.IsSingleKaon()) {
int kaon_pdgc = xcls.StrangeHadronPdg();
double Mi = tgt.HitNucP4Ptr()->M(); // initial nucleon mass
diff --git a/src/Framework/Interaction/ProcessInfo.cxx b/src/Framework/Interaction/ProcessInfo.cxx
index 633faf295..297607d5a 100644
--- a/src/Framework/Interaction/ProcessInfo.cxx
+++ b/src/Framework/Interaction/ProcessInfo.cxx
@@ -128,6 +128,11 @@ bool ProcessInfo::IsIMDAnnihilation(void) const
return (fScatteringType == kScIMDAnnihilation);
}
//____________________________________________________________________________
+bool ProcessInfo::IsNorm(void) const
+{
+ return (fScatteringType == kScNorm);
+}
+//____________________________________________________________________________
bool ProcessInfo::IsDarkMatterElectronElastic(void) const
{
return (fScatteringType == kScDarkMatterElectron);
diff --git a/src/Framework/Interaction/ProcessInfo.h b/src/Framework/Interaction/ProcessInfo.h
index ccbf5e6a7..48dcbe62d 100644
--- a/src/Framework/Interaction/ProcessInfo.h
+++ b/src/Framework/Interaction/ProcessInfo.h
@@ -71,6 +71,7 @@ class ProcessInfo : public TObject {
bool IsNuElectronElastic (void) const;
bool IsInverseMuDecay (void) const;
bool IsIMDAnnihilation (void) const;
+ bool IsNorm (void) const;
bool IsDarkMatterElectronElastic (void) const;
bool IsInverseBetaDecay (void) const;
bool IsGlashowResonance (void) const;
diff --git a/src/Framework/Interaction/ScatteringType.h b/src/Framework/Interaction/ScatteringType.h
index a51781d2d..ed421f467 100644
--- a/src/Framework/Interaction/ScatteringType.h
+++ b/src/Framework/Interaction/ScatteringType.h
@@ -54,7 +54,8 @@ typedef enum EScatteringType {
kScPhotonResonance,
kScDarkMatterElastic = 101,
kScDarkMatterDeepInelastic,
- kScDarkMatterElectron
+ kScDarkMatterElectron,
+ kScNorm
} ScatteringType_t;
class ScatteringType
@@ -80,6 +81,7 @@ class ScatteringType
case(kScInverseBetaDecay) : return "IBD"; break;
case(kScGlashowResonance) : return "GLR"; break;
case(kScIMDAnnihilation) : return "IMDAnh"; break;
+ case(kScNorm) : return "Norm"; break;
case(kScPhotonCoherent) : return "PhotonCOH"; break;
case(kScPhotonResonance) : return "PhotonRES"; break;
case(kScDarkMatterElastic) : return "DMEL"; break;
diff --git a/src/Framework/Numerical/Spline.cxx b/src/Framework/Numerical/Spline.cxx
index 778a93c06..09db045a4 100644
--- a/src/Framework/Numerical/Spline.cxx
+++ b/src/Framework/Numerical/Spline.cxx
@@ -132,7 +132,7 @@ Spline::Spline(const Spline & spline) :
TObject(), fInterpolator(0)
{
LOG("Spline", pDEBUG) << "Spline copy constructor";
-
+ this->InitSpline();
this->LoadFromTSpline3( *spline.GetAsTSpline(), spline.NKnots() );
}
//___________________________________________________________________________
@@ -141,13 +141,15 @@ Spline::Spline(const TSpline3 & spline, int nknots) :
{
LOG("Spline", pDEBUG)
<< "Constructing spline from the input TSpline3 object";
-
+ this->InitSpline();
this->LoadFromTSpline3( spline, nknots );
}
//___________________________________________________________________________
Spline::~Spline()
{
if(fInterpolator) delete fInterpolator;
+ if(fInterpolator5) delete fInterpolator5;
+ if(fGSLInterpolator) delete fGSLInterpolator;
}
//___________________________________________________________________________
bool Spline::LoadFromXmlFile(string filename, string xtag, string ytag)
@@ -374,7 +376,12 @@ double Spline::Evaluate(double x) const
if(!is0p && !is0n) {
// both knots (on the left and right are non-zero) - just interpolate
LOG("Spline", pDEBUG) << "Point is between non-zero knots";
- y = fInterpolator->Eval(x);
+ if (fInterpolatorType == "TSpline3")
+ y = fInterpolator->Eval(x);
+ else if (fInterpolatorType == "TSpline5")
+ y = fInterpolator5->Eval(x);
+ else
+ y = fGSLInterpolator->Eval(x);
} else {
// at least one of the neighboring knots has y=0
if(is0p && is0n) {
@@ -721,8 +728,11 @@ void Spline::InitSpline(void)
fXMin = 0.0;
fXMax = 0.0;
fYMax = 0.0;
-
+
fInterpolator = 0;
+ fInterpolator5 = 0;
+ fGSLInterpolator = 0;
+ fInterpolatorType = "TSpline3";
fYCanBeNegative = false;
@@ -732,6 +742,8 @@ void Spline::InitSpline(void)
void Spline::ResetSpline(void)
{
if(fInterpolator) delete fInterpolator;
+ if(fInterpolator5) delete fInterpolator5;
+ if(fGSLInterpolator) delete fGSLInterpolator;
this->InitSpline();
}
//___________________________________________________________________________
@@ -750,7 +762,76 @@ void Spline::BuildSpline(int nentries, double x[], double y[])
if(fInterpolator) delete fInterpolator;
fInterpolator = new TSpline3("spl3", x, y, nentries, "0");
-
+
LOG("Spline", pDEBUG) << "...done building spline";
}
//___________________________________________________________________________
+void Spline::SetType(string type)
+{
+ if(!fInterpolator) return;
+
+ fInterpolatorType = genie::utils::str::ToUpper(type);
+
+ ROOT::Math::Interpolation::Type gsltype;
+
+ if ( fInterpolatorType == "TSPLINE3" || fInterpolatorType == "" )
+ {
+ fInterpolatorType == "TSpline3";
+ return;
+ }
+ else if ( fInterpolatorType == "TSPLINE5" )
+ {
+ fInterpolatorType = "TSpline5";
+ if(fInterpolator5) delete fInterpolator5;
+ double x[fNKnots], y[fNKnots];
+ for (int i=0; iGetKnot(i, x[i], y[i]);
+ }
+ fInterpolator5 = new TSpline5("spl5", x, y, fNKnots, "0");
+ return;
+ }
+ else if ( fInterpolatorType == "LINEAR" )
+ {
+ gsltype = ROOT::Math::Interpolation::kLINEAR;
+ }
+ else if ( fInterpolatorType == "POLYNOMIAL" )
+ {
+ gsltype = ROOT::Math::Interpolation::kPOLYNOMIAL;
+ }
+ else if ( fInterpolatorType == "CSPLINE" )
+ {
+ gsltype = ROOT::Math::Interpolation::kCSPLINE;
+ }
+ else if ( fInterpolatorType == "CSPLINE_PERIODIC" )
+ {
+ gsltype = ROOT::Math::Interpolation::kCSPLINE_PERIODIC;
+ }
+ else if ( fInterpolatorType == "AKIMA" )
+ {
+ gsltype = ROOT::Math::Interpolation::kAKIMA;
+ }
+ else if ( fInterpolatorType == "AKIMA_PERIODIC" )
+ {
+ gsltype = ROOT::Math::Interpolation::kAKIMA_PERIODIC;
+ }
+ else
+ {
+ fInterpolatorType = "TSpline3";
+ LOG("Spline", pWARN)
+ << "Unknown interpolator type. Setting it to default [TSpline3].";
+ return;
+ }
+
+ if(fGSLInterpolator) delete fGSLInterpolator;
+ vector x(fNKnots);
+ vector y(fNKnots);
+ for (int i=0; iGetKnot(i, x[i], y[i]);
+ }
+ fGSLInterpolator = new ROOT::Math::Interpolator(x, y, gsltype);
+
+
+}
+//___________________________________________________________________________
diff --git a/src/Framework/Numerical/Spline.h b/src/Framework/Numerical/Spline.h
index 7533d3ea0..daf3a3ab3 100644
--- a/src/Framework/Numerical/Spline.h
+++ b/src/Framework/Numerical/Spline.h
@@ -7,10 +7,20 @@
Uses ROOT's TSpline3 for the actual interpolation and can retrieve
function (x,y(x)) pairs from an XML file, a flat ascii file, a
- TNtuple, a TTree or an SQL database.
+ TNtuple, a TTree or an SQL database.\n
+
+ Update May 15, 2022 IK:
+ Adding as extra interpolators TSpline5 and
+ ROOT::Math::GSLInterpolator (LINEAR, POLYNOMIAL, CSPLINE, CSPLINE_PERIODIC,
+ AKIMA, AKIMA_PERIODIC)
+
+
+\ref [1] GENIE docdb 297
\author Costas Andreopoulos
- University of Liverpool & STFC Rutherford Appleton Laboratory
+ University of Liverpool & STFC Rutherford Appleton Laboratory \n
+ Igor Kakorin
+ Joint Institute for Nuclear Research
\created May 04, 2004
@@ -22,12 +32,14 @@
#ifndef _SPLINE_H_
#define _SPLINE_H_
+#include
#include
#include
#include
#include
#include
+#include