GENIEGenerator
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HELeptonKinematicsGenerator.cxx
Go to the documentation of this file.
1 //____________________________________________________________________________
2 /*
3  Copyright (c) 2003-2024, The GENIE Collaboration
4  For the full text of the license visit http://copyright.genie-mc.org
5 
6  Alfonso Garcia <aagarciasoto \at km3net.de>
7  IFIC & Harvard University
8 */
9 //____________________________________________________________________________
10 
22 #include "Framework/Utils/Range1.h"
25 
26 #include "Math/Minimizer.h"
27 #include "Math/Factory.h"
28 
29 using namespace genie;
30 using namespace genie::controls;
31 using namespace genie::utils;
32 
33 //___________________________________________________________________________
35 KineGeneratorWithCache("genie::HELeptonKinematicsGenerator")
36 {
37 
38 }
39 //___________________________________________________________________________
41 KineGeneratorWithCache("genie::HELeptonKinematicsGenerator", config)
42 {
43 
44 }
45 //___________________________________________________________________________
47 {
48 
49 }
50 //___________________________________________________________________________
52 {
53  if(fGenerateUniformly) {
54  LOG("HELeptonKinematics", pNOTICE)
55  << "Generating kinematics uniformly over the allowed phase space";
56  }
57 
58  //-- Get the random number generators
60 
61  //-- Access cross section algorithm for running thread
63  const EventGeneratorI * evg = rtinfo->RunningThread();
64  fXSecModel = evg->CrossSectionAlg();
65 
66  Interaction * interaction = evrec->Summary();
67 
68  //-- For the subsequent kinematic selection with the rejection method:
69  // Calculate the max differential cross section or retrieve it from the
70  // cache. Throw an exception and quit the evg thread if a non-positive
71  // value is found.
72  // If the kinematics are generated uniformly over the allowed phase
73  // space the max xsec is irrelevant
74  double xsec_max = this->MaxXSec(evrec);
75 
76  const ProcessInfo & proc_info = interaction->ProcInfo();
77  if(proc_info.IsPhotonCoherent()) {
78 
79  double nupdg = interaction->InitState().ProbePdg();
80 
81  double n2min = 0.;
82  double n2max = 1.;
83  double n3min = 0.;
84  double n3max = 1.;
85  double dn2 = n2max-n2min;
86  double dn3 = n3max-n3min;
87 
88  double n1max = 0.;
89  double n1min = 0.;
90  if (pdg::IsNuE (TMath::Abs(nupdg))) { n1min = 1.-fDeltaN1NuE; n1max = 1.+fDeltaN1NuE; }
91  else if (pdg::IsNuMu (TMath::Abs(nupdg))) { n1min = 1.-fDeltaN1NuMu; n1max = 1.+fDeltaN1NuMu; }
92  else if (pdg::IsNuTau(TMath::Abs(nupdg))) { n1min = 1.-fDeltaN1NuTau; n1max = 1.+fDeltaN1NuTau; }
93  double dn1 = n1max-n1min;
94 
95 
96  //-- Try to select a valid inelastisity y
97  double xsec = -1;
98  unsigned int iter = 0;
99  bool accept = false;
100 
101  while(1) {
102  iter++;
103  if(iter > 1000000) {
104  LOG("HELeptonKinematics", pWARN)
105  << "*** Could not select a valid y after "
106  << iter << " iterations";
107  evrec->EventFlags()->SetBitNumber(kKineGenErr, true);
109  exception.SetReason("Couldn't select kinematics");
110  exception.SwitchOnFastForward();
111  throw exception;
112  }
113 
114  double n2 = n2min + dn2 * rnd->RndKine().Rndm();
115  double n3 = n3min + dn3 * rnd->RndKine().Rndm();
116  double n1 = n1min + dn1 * rnd->RndKine().Rndm();
117  n1 = (n1>1.) ? n1-2. : n1;
118 
119  interaction->KinePtr()->SetKV(kKVn1,n1);
120  interaction->KinePtr()->SetKV(kKVn2,n2);
121  interaction->KinePtr()->SetKV(kKVn3,n3);
122 
123  LOG("HELeptonKinematics", pDEBUG) << "Trying: n1 = " << n1 << ", n2 = " << n2 << ", n3 = " << n3;
124 
125  //-- computing cross section for the current kinematics
126  xsec = fXSecModel->XSec(interaction, kPSn1n2n3fE);
127 
128  this->AssertXSecLimits(interaction, xsec, xsec_max);
129 
130  double t = xsec_max * rnd->RndKine().Rndm();
131  LOG("HELeptonKinematics", pDEBUG) << "xsec= "<< xsec<< ", J= 1, Rnd= "<< t;
132 
133  accept = (t<xsec);
134 
135  //-- If the generated kinematics are accepted, finish-up module's job
136  if(accept) {
137  LOG("HELeptonKinematics", pINFO) << "Selected: n1 = " << n1 << ", n2 = " << n2 << ", n3 = " << n3;
138 
139  // set the cross section for the selected kinematics
140  evrec->SetDiffXSec(xsec,kPSn1n2n3fE);
141 
142  // lock selected kinematics & clear running values
143  interaction->KinePtr()->ClearRunningValues();
144 
145  return;
146  }
147  }// iterations
148 
149  }
150  else {
151  double n1min = -1.;
152  double n1max = 1.;
153  double n2min = 0.;
154  double n2max = 1.;
155  double dn1 = n1max-n1min;
156  double dn2 = n2max-n2min;
157 
158  //-- Try to select a valid inelastisity y
159  double xsec = -1;
160  unsigned int iter = 0;
161  bool accept = false;
162 
163  while(1) {
164  iter++;
165  if(iter > 1000000) {
166  LOG("HELeptonKinematics", pWARN)
167  << "*** Could not select a valid y after "
168  << iter << " iterations";
169  evrec->EventFlags()->SetBitNumber(kKineGenErr, true);
171  exception.SetReason("Couldn't select kinematics");
172  exception.SwitchOnFastForward();
173  throw exception;
174  }
175 
176  double n1 = n1min + dn1 * rnd->RndKine().Rndm();
177  double n2 = n2min + dn2 * rnd->RndKine().Rndm();
178  interaction->KinePtr()->SetKV(kKVn1,n1);
179  interaction->KinePtr()->SetKV(kKVn2,n2);
180 
181  LOG("HELeptonKinematics", pDEBUG) << "Trying: n1 = " << n1 << ", n2 = " << n2;
182 
183  //-- computing cross section for the current kinematics
184  xsec = fXSecModel->XSec(interaction, kPSn1n2fE);
185 
186  this->AssertXSecLimits(interaction, xsec, xsec_max);
187 
188  double t = xsec_max * rnd->RndKine().Rndm();
189  LOG("HELeptonKinematics", pDEBUG) << "xsec= "<< xsec<< ", J= 1, Rnd= "<< t;
190 
191  accept = (t<xsec);
192 
193  //-- If the generated kinematics are accepted, finish-up module's job
194  if(accept) {
195  LOG("HELeptonKinematics", pINFO) << "Selected: n1 = " << n1 << ", n2 = " << n2;
196 
197  // set the cross section for the selected kinematics
198  evrec->SetDiffXSec(xsec,kPSn1n2fE);
199 
200  // lock selected kinematics & clear running values
201  interaction->KinePtr()->ClearRunningValues();
202 
203  return;
204  }
205  }// iterations
206 
207  }
208 }
209 //___________________________________________________________________________
211  const Interaction * interaction) const
212 {
213 // Computes the maximum differential cross section in the requested phase
214 // space. This method overloads KineGeneratorWithCache::ComputeMaxXSec
215 // method and the value is cached at a circular cache branch for retrieval
216 // during subsequent event generation.
217 // The computed max differential cross section does not need to be the exact
218 // maximum. The number used in the rejection method will be scaled up by a
219 // safety factor. But it needs to be fast - do not use a very small y step.
220 
221  double max_xsec = -1.0;
222 
223  ROOT::Math::Minimizer * min = ROOT::Math::Factory::CreateMinimizer("Minuit");
224 
225  const ProcessInfo & proc_info = interaction->ProcInfo();
226  if(proc_info.IsPhotonCoherent()) {
227 
228  utils::gsl::d2Xsec_dn1dn2dn3_E f(fXSecModel,interaction,-1);
229  min->SetFunction( f );
230  min->SetMaxFunctionCalls(10000);
231  min->SetTolerance(0.05);
232 
233  min->SetFixedVariable ( 0, "n1", 1.);
234  min->SetLimitedVariable ( 1, "n2", 0., 0.01, 0., 1.);
235  min->SetLimitedVariable ( 2, "n3", 0., 0.01, 0., 1.);
236  min->Minimize();
237  min->SetFixedVariable ( 0, "n1", 1.);
238  min->SetLimitedVariable ( 1, "n2", min->X()[1], 0.01, TMath::Max(0.,min->X()[1]-0.1), TMath::Min(1.,min->X()[1]+0.1));
239  min->SetLimitedVariable ( 2, "n3", min->X()[2], 0.01, TMath::Max(0.,min->X()[2]-0.1), TMath::Min(1.,min->X()[2]+0.1));
240  min->Minimize();
241  interaction->KinePtr()->SetKV(kKVn1,min->X()[0]);
242  interaction->KinePtr()->SetKV(kKVn2,min->X()[1]);
243  interaction->KinePtr()->SetKV(kKVn3,min->X()[2]);
244  SLOG("HELeptonKinematics", pDEBUG) << "Minimum found -> n1: 1, n2: " << min->X()[1] << ", n3: " << min->X()[2] << ", xsec: " << fXSecModel->XSec(interaction, kPSn1n2n3fE);
245  max_xsec = TMath::Max(fXSecModel->XSec(interaction, kPSn1n2n3fE),max_xsec);
246 
247  min->SetFixedVariable ( 0, "n1", -1.);
248  min->SetLimitedVariable ( 1, "n2", 0., 0.01, 0., 1.);
249  min->SetLimitedVariable ( 2, "n3", 0., 0.01, 0., 1.);
250  min->Minimize();
251  min->SetFixedVariable ( 0, "n1", -1.);
252  min->SetLimitedVariable ( 1, "n2", min->X()[1], 0.01, TMath::Max(0.,min->X()[1]-0.1), TMath::Min(1.,min->X()[1]+0.1));
253  min->SetLimitedVariable ( 2, "n3", min->X()[2], 0.01, TMath::Max(0.,min->X()[2]-0.1), TMath::Min(1.,min->X()[2]+0.1));
254  interaction->KinePtr()->SetKV(kKVn1,min->X()[0]);
255  interaction->KinePtr()->SetKV(kKVn2,min->X()[1]);
256  interaction->KinePtr()->SetKV(kKVn3,min->X()[2]);
257  SLOG("HELeptonKinematics", pDEBUG) << "Minimum found -> n1: -1, n2: " << min->X()[1] << ", n3: " << min->X()[2] << ", xsec: " << fXSecModel->XSec(interaction, kPSn1n2n3fE);
258  max_xsec = TMath::Max(fXSecModel->XSec(interaction, kPSn1n2n3fE),max_xsec);
259 
260  }
261  else {
262 
263  const int Nscan = 100;
264  const int n1min = -1.;
265  const int n1max = 1.;
266  const int n2min = 0.;
267  const int n2max = 1.;
268  const double dn1 = (n1max-n1min)/(double)Nscan;
269  const double dn2 = (n2max-n2min)/(double)
270  Nscan;
271 
272  double scan_n1 = 0.;
273  double scan_n2 = 0.;
274  for (int i=0; i<Nscan; i++) {
275  double n1 = n1min + dn1*i;
276  for (int j=0; j<Nscan; j++) {
277  double n2 = n2min + dn2*j;
278  interaction->KinePtr()->SetKV(kKVn1,n1);
279  interaction->KinePtr()->SetKV(kKVn2,n2);
280  double dxsec = fXSecModel->XSec(interaction, kPSn1n2fE);
281  if ( dxsec > max_xsec ) {
282  scan_n1 = n1;
283  scan_n2 = n2;
284  max_xsec = dxsec;
285  }
286  }
287  }
288 
289  utils::gsl::d2Xsec_dn1dn2_E f(fXSecModel,interaction,-1);
290  min->SetFunction( f );
291  min->SetMaxFunctionCalls(10000);
292  min->SetTolerance(0.05);
293  min->SetLimitedVariable ( 0, "n1", scan_n1, 0.001, TMath::Max(-1.,scan_n1-0.1), TMath::Min(1.,scan_n1+0.1));
294  min->SetLimitedVariable ( 1, "n2", scan_n2, 0.1, TMath::Max(-0.,scan_n2-0.1), TMath::Min(1.,scan_n2+0.1));
295  min->Minimize();
296  interaction->KinePtr()->SetKV(kKVn1,min->X()[0]);
297  interaction->KinePtr()->SetKV(kKVn2,min->X()[1]);
298  max_xsec = fXSecModel->XSec(interaction, kPSn1n2fE);
299  SLOG("HELeptonKinematics", pDEBUG) << "Minimum found -> n1: " << min->X()[0] << ", n2: " << min->X()[1];
300 
301  }
302 
303  // Apply safety factor, since value retrieved from the cache might
304  // correspond to a slightly different energy.
305  max_xsec *= fSafetyFactor;
306 
307  SLOG("HELeptonKinematics", pDEBUG) << interaction->AsString();
308  SLOG("HELeptonKinematics", pDEBUG) << "Max xsec in phase space = " << max_xsec;
309  SLOG("HELeptonKinematics", pDEBUG) << "Computed using alg = " << *fXSecModel;
310 
311  return max_xsec;
312 }
313 //___________________________________________________________________________
314 double HELeptonKinematicsGenerator::Energy(const Interaction * interaction) const
315 {
316 // Override the base class Energy() method to cache the max xsec for the
317 // neutrino energy in the LAB rather than in the hit nucleon rest frame.
318 
319  const InitialState & init_state = interaction->InitState();
320  double E = init_state.ProbeE(kRfLab);
321  return E;
322 }
323 //___________________________________________________________________________
325 {
326  Algorithm::Configure(config);
327  this->LoadConfig();
328 }
329 //____________________________________________________________________________
331 {
332  Algorithm::Configure(config);
333  this->LoadConfig();
334 }
335 //____________________________________________________________________________
337 {
338 // Reads its configuration data from its configuration Registry and loads them
339 // in private data members to avoid looking up at the Registry all the time.
340 
341  //-- Safety factor for the maximum differential cross section
342  GetParamDef( "MaxXSec-SafetyFactor", fSafetyFactor, 2. ) ;
343 
344  //-- Maximum allowed fractional cross section deviation from maxim cross
345  // section used in rejection method
346  GetParamDef( "MaxXSec-DiffTolerance", fMaxXSecDiffTolerance, 999999. ) ;
347  assert(fMaxXSecDiffTolerance>=0);
348 
349  //-- Sampling range for n1 variable
350  GetParamDef( "Delta-N1-NuE", fDeltaN1NuE, 0. ) ;
351  GetParamDef( "Delta-N1-NuMu", fDeltaN1NuMu, 0. ) ;
352  GetParamDef( "Delta-N1-NuTau", fDeltaN1NuTau, 0. ) ;
353 
354 
355 }
356 //____________________________________________________________________________
bool IsNuTau(int pdgc)
Definition: PDGUtils.cxx:168
bool fGenerateUniformly
uniform over allowed phase space + event weight?
virtual Interaction * Summary(void) const
Definition: GHepRecord.cxx:91
static RandomGen * Instance()
Access instance.
Definition: RandomGen.cxx:71
Kinematics * KinePtr(void) const
Definition: Interaction.h:76
double fSafetyFactor
ComputeMaxXSec -&gt; ComputeMaxXSec * fSafetyFactor.
virtual void AssertXSecLimits(const Interaction *in, double xsec, double xsec_max) const
double fMaxXSecDiffTolerance
max{100*(xsec-maxxsec)/.5*(xsec+maxxsec)} if xsec&gt;maxxsec
Defines the EventGeneratorI interface.
virtual double MaxXSec(GHepRecord *evrec, const int nkey=0) const
bool IsNuE(int pdgc)
Definition: PDGUtils.cxx:158
Abstract class. Provides a data caching mechanism for for concrete implementations of the EventRecord...
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition: RandomGen.h:29
string AsString(void) const
bool IsNuMu(int pdgc)
Definition: PDGUtils.cxx:163
Summary information for an interaction.
Definition: Interaction.h:56
An exception thrown by EventRecordVisitorI when the normal processing sequence has to be disrupted (f...
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
Definition: Messenger.h:96
A class encapsulating an enumeration of interaction types (EM, Weak-CC, Weak-NC) and scattering types...
Definition: ProcessInfo.h:46
virtual void Configure(const Registry &config)
Definition: Algorithm.cxx:62
int ProbePdg(void) const
Definition: InitialState.h:64
#define pINFO
Definition: Messenger.h:62
TRandom3 & RndKine(void) const
rnd number generator used by kinematics generators
Definition: RandomGen.h:50
void ProcessEventRecord(GHepRecord *event_rec) const
bool IsPhotonCoherent(void) const
#define pWARN
Definition: Messenger.h:60
virtual double XSec(const Interaction *i, KinePhaseSpace_t k=kPSfE) const =0
Compute the cross section for the input interaction.
void SetKV(KineVar_t kv, double value)
Definition: Kinematics.cxx:335
static RunningThreadInfo * Instance(void)
double Energy(const Interaction *in) const
virtual TBits * EventFlags(void) const
Definition: GHepRecord.h:117
A registry. Provides the container for algorithm configuration parameters.
Definition: Registry.h:65
virtual const XSecAlgorithmI * CrossSectionAlg(void) const =0
double ComputeMaxXSec(const Interaction *in) const
const InitialState & InitState(void) const
Definition: Interaction.h:69
const ProcessInfo & ProcInfo(void) const
Definition: Interaction.h:70
#define pNOTICE
Definition: Messenger.h:61
void ClearRunningValues(void)
Definition: Kinematics.cxx:347
bool GetParamDef(const RgKey &name, T &p, const T &def) const
const EventGeneratorI * RunningThread(void)
#define SLOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a short string (using the FUNCTION and...
Definition: Messenger.h:84
double ProbeE(RefFrame_t rf) const
GENIE&#39;s GHEP MC event record.
Definition: GHepRecord.h:45
Keep info on the event generation thread currently on charge. This is used so that event generation m...
virtual void SetDiffXSec(double xsec, KinePhaseSpace_t ps)
Definition: GHepRecord.h:133
Initial State information.
Definition: InitialState.h:48
#define pDEBUG
Definition: Messenger.h:63