GENIEGenerator
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
KineGeneratorWithCache.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  Costas Andreopoulos <c.andreopoulos \at cern.ch>
7  University of Liverpool
8 */
9 //____________________________________________________________________________
10 
11 #include <sstream>
12 #include <cstdlib>
13 #include <map>
14 
15 //#include <TSQLResult.h>
16 //#include <TSQLRow.h>
17 #include <TMath.h>
18 
24 #include "Framework/Utils/Cache.h"
27 
28 using std::ostringstream;
29 using std::map;
30 
31 using namespace genie;
32 
33 //___________________________________________________________________________
35 EventRecordVisitorI(), fSafetyFactor(1.), fNumOfSafetyFactors(-1), fNumOfInterpolatorTypes(-1)
36 {
37 
38 }
39 //___________________________________________________________________________
41 EventRecordVisitorI(name), fSafetyFactor(1.), fNumOfSafetyFactors(-1), fNumOfInterpolatorTypes(-1)
42 {
43 
44 }
45 //___________________________________________________________________________
46 KineGeneratorWithCache::KineGeneratorWithCache(string name, string config) :
47 EventRecordVisitorI(name, config), fSafetyFactor(1.), fNumOfSafetyFactors(-1), fNumOfInterpolatorTypes(-1)
48 {
49 
50 }
51 //___________________________________________________________________________
53 {
54 
55 }
56 //___________________________________________________________________________
57 double KineGeneratorWithCache::MaxXSec(GHepRecord * event_rec, const int nkey) const
58 {
59  LOG("Kinematics", pINFO)
60  << "Getting max. for the rejection method";
61 
62  double xsec_max = -1;
63  Interaction * interaction = event_rec->Summary();
64 
65  LOG("Kinematics", pINFO)
66  << "Attempting to find a cached max value";
67  xsec_max = this->FindMaxXSec(interaction, nkey);
68  if(xsec_max>0) return nkey<=fNumOfSafetyFactors-1?vSafetyFactors[nkey]*xsec_max:xsec_max;
69 
70  LOG("Kinematics", pINFO)
71  << "Attempting to compute the max value";
72  if (nkey == 0)
73  {
74  xsec_max = this->ComputeMaxXSec(interaction);
75  }
76  else
77  {
78  xsec_max = this->ComputeMaxXSec(interaction, nkey);
79  }
80 
81  if(xsec_max>0) {
82  LOG("Kinematics", pINFO) << "max = " << xsec_max;
83  this->CacheMaxXSec(interaction, xsec_max, nkey);
84  return nkey<=fNumOfSafetyFactors-1?vSafetyFactors[nkey]*xsec_max:xsec_max;
85  }
86 
87  LOG("Kinematics", pNOTICE)
88  << "Can not generate event kinematics max_xsec<=0)";
89  // xsec for selected kinematics = 0
90  event_rec->SetDiffXSec(0,kPSNull);
91  // switch on error flag
92  event_rec->EventFlags()->SetBitNumber(kKineGenErr, true);
93  // reset 'trust' bits
94  interaction->ResetBit(kISkipProcessChk);
95  interaction->ResetBit(kISkipKinematicChk);
96  // throw exception
98  exception.SetReason("kinematics generation: max_xsec<=0");
99  exception.SwitchOnFastForward();
100  throw exception;
101 
102  return 0;
103 }
104 //___________________________________________________________________________
106  const Interaction * interaction, const int nkey) const
107 {
108 // Find a cached max xsec for the specified xsec algorithm & interaction and
109 // close to the specified energy
110 
111  // get neutrino energy
112  double E = this->Energy(interaction);
113  LOG("Kinematics", pINFO) << "E = " << E;
114 
115  if(E < fEMin) {
116  LOG("Kinematics", pINFO)
117  << "Below minimum energy - Forcing explicit calculation";
118  return -1.;
119  }
120 
121  // access the the cache branch
122  CacheBranchFx * cb = this->AccessCacheBranch(interaction, nkey);
123 
124  // if there are enough points stored in the cache buffer to build a
125  // spline, then intepolate
126  if( cb->Spl() ) {
127  if( E >= cb->Spl()->XMin() && E <= cb->Spl()->XMax()) {
128  double spl_max_xsec = cb->Spl()->Evaluate(E);
129  LOG("Kinematics", pINFO)
130  << "\nInterpolated: max (E=" << E << ") = " << spl_max_xsec;
131  return spl_max_xsec;
132  }
133  LOG("Kinematics", pINFO)
134  << "Outside spline boundaries - Forcing explicit calculation";
135  return -1.;
136  }
137 
138  // if there are not enough points at the cache buffer to have a spline,
139  // look whether there is another point that is sufficiently close
140  double dE = TMath::Min(0.25, 0.05*E);
141  const map<double,double> & fmap = cb->Map();
142  map<double,double>::const_iterator iter = fmap.lower_bound(E);
143  if(iter != fmap.end()) {
144  if(TMath::Abs(E - iter->first) < dE) return iter->second;
145  }
146 
147  return -1;
148 
149 /*
150  // build the search rule
151  double dE = TMath::Min(0.25, 0.05*E);
152  ostringstream search;
153  search << "(x-" << E << " < " << dE << ") && (x>=" << E << ")";
154 
155  // query for all the entries at a window around the current energy
156  TSQLResult * result = cb->Ntuple()->Query("x:y", search.str().c_str());
157  int nrows = result->GetRowCount();
158  LOG("Kinematics", pDEBUG)
159  << "Found " << nrows << " rows with " << search.str();
160  if(nrows <= 0) {
161  delete result;
162  return -1;
163  }
164 
165  // and now select the entry with the closest energy
166  double max_xsec = -1.0;
167  double Ep = 0;
168  double dEmin = 999;
169  TSQLRow * row = 0;
170  while( (row = result->Next()) ) {
171  double cE = atof( row->GetField(0) );
172  double cxsec = atof( row->GetField(1) );
173  double dE = TMath::Abs(E-cE);
174  if(dE < dEmin) {
175  max_xsec = cxsec;
176  Ep = cE;
177  dEmin = TMath::Min(dE,dEmin);
178  }
179  delete row;
180  }
181  delete result;
182 
183  LOG("Kinematics", pINFO)
184  << "\nRetrieved: max xsec = " << max_xsec << " cached at E = " << Ep;
185 
186  return max_xsec;
187 */
188 }
189 //___________________________________________________________________________
191  const Interaction * interaction, double max_xsec, const int nkey) const
192 {
193  LOG("Kinematics", pINFO)
194  << "Adding the computed max value to cache";
195  CacheBranchFx * cb = this->AccessCacheBranch(interaction, nkey);
196 
197  double E = this->Energy(interaction);
198  if (E<fEMin) return;
199  if(max_xsec>0) cb->AddValues(E,max_xsec);
200 
201  if(! cb->Spl() ) {
202  if( cb->Map().size() > 40 )
204  }
205 
206  if( cb->Spl() ) {
207  if( E < cb->Spl()->XMin() || E > cb->Spl()->XMax() ) {
209  }
210  }
211 }
212 //___________________________________________________________________________
213 double KineGeneratorWithCache::Energy(const Interaction * interaction) const
214 {
215 // Returns the neutrino energy at the struck nucleon rest frame. Kinematic
216 // generators should override this method if they need to cache the max-xsec
217 // values for another energy value (eg kinematic generators for IMD or COH)
218 
219  const InitialState & init_state = interaction->InitState();
220  double E = init_state.ProbeE(kRfHitNucRest);
221  return E;
222 }
223 //___________________________________________________________________________
225  const Interaction * interaction, const int nkey) const
226 {
227 // Returns the cache branch for this algorithm and this interaction. If no
228 // branch is found then one is created.
229 
230  Cache * cache = Cache::Instance();
231 
232  // build the cache branch key as: namespace::algorithm/config/interaction/nkey
233  string algkey = this->Id().Key();
234  string intkey = interaction->AsString();
235  string key = cache->CacheBranchKey(algkey, intkey, std::to_string(nkey));
236 
237  CacheBranchFx * cache_branch =
238  dynamic_cast<CacheBranchFx *> (cache->FindCacheBranch(key));
239  if(!cache_branch) {
240  //-- create the cache branch at the first pass
241  LOG("Kinematics", pINFO) << "No cache branch found";
242  LOG("Kinematics", pINFO) << "Creating cache branch - key = " << key;
243 
244  cache_branch = new CacheBranchFx("Max over phase space");
245  cache->AddCacheBranch(key, cache_branch);
246  }
247  assert(cache_branch);
248 
249  return cache_branch;
250 }
251 //___________________________________________________________________________
253  const Interaction * interaction, double xsec, double xsec_max) const
254 {
255  // check the computed cross section for the current kinematics against the
256  // maximum cross section used in the rejection MC method for the current
257  // interaction at the current energy.
258  if(xsec>xsec_max) {
259  double f = 200*(xsec-xsec_max)/(xsec_max+xsec);
260  if(f>fMaxXSecDiffTolerance) {
261  LOG("Kinematics", pFATAL)
262  << "xsec: (curr) = " << xsec
263  << " > (max) = " << xsec_max << "\n for " << *interaction;
264  LOG("Kinematics", pFATAL)
265  << "*** Exceeding estimated maximum differential cross section";
266  std::terminate();
267  } else {
268  LOG("Kinematics", pWARN)
269  << "xsec: (curr) = " << xsec
270  << " > (max) = " << xsec_max << "\n for " << *interaction;
271  LOG("Kinematics", pWARN)
272  << "*** The fractional deviation of " << f << " % was allowed";
273  }
274  }
275 
276  // this should never happen - print an error mesg just in case...
277  if(xsec<0) {
278  LOG("Kinematics", pERROR)
279  << "Negative cross section for current kinematics!! \n" << *interaction;
280  }
281 }
282 //___________________________________________________________________________
283 double KineGeneratorWithCache::ComputeMaxXSec (const Interaction * in, const int nkey) const
284 {
285  if (nkey == 0)
286  {
287  return this->ComputeMaxXSec(in);
288  }
289  else
290  {
291  return -1;
292  }
293 }
294 //___________________________________________________________________________
#define pERROR
Definition: Messenger.h:59
virtual Interaction * Summary(void) const
Definition: GHepRecord.cxx:91
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the &#39;Visito...
virtual void AssertXSecLimits(const Interaction *in, double xsec, double xsec_max) const
#define pFATAL
Definition: Messenger.h:56
double fMaxXSecDiffTolerance
max{100*(xsec-maxxsec)/.5*(xsec+maxxsec)} if xsec&gt;maxxsec
int fNumOfSafetyFactors
Number of given safety factors.
virtual double MaxXSec(GHepRecord *evrec, const int nkey=0) const
void CreateSpline(string type="TSpline3")
double Evaluate(double x) const
Definition: Spline.cxx:363
string AsString(void) const
void AddCacheBranch(string key, CacheBranchI *branch)
Definition: Cache.cxx:88
int fNumOfInterpolatorTypes
Number of given interpolators types.
virtual double ComputeMaxXSec(const Interaction *in) const =0
std::vector< double > vSafetyFactors
MaxXSec -&gt; MaxXSec * fSafetyFactors[nkey].
Summary information for an interaction.
Definition: Interaction.h:56
void AddValues(double x, double y)
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
Spline * Spl(void) const
Definition: CacheBranchFx.h:59
string CacheBranchKey(string k0, string k1="", string k2="") const
Definition: Cache.cxx:93
#define pINFO
Definition: Messenger.h:62
#define pWARN
Definition: Messenger.h:60
const UInt_t kISkipKinematicChk
if set, skip kinematic validity checks
Definition: Interaction.h:48
CacheBranchI * FindCacheBranch(string key)
finding/adding cache branches
Definition: Cache.cxx:80
GENIE Cache Memory.
Definition: Cache.h:38
double XMax(void) const
Definition: Spline.h:89
virtual const AlgId & Id(void) const
Get algorithm ID.
Definition: Algorithm.h:98
const map< double, double > & Map(void) const
Definition: CacheBranchFx.h:58
virtual TBits * EventFlags(void) const
Definition: GHepRecord.h:117
virtual CacheBranchFx * AccessCacheBranch(const Interaction *in, const int nkey=0) const
double fEMin
min E for which maxxsec is cached - forcing explicit calc.
virtual double Energy(const Interaction *in) const
virtual double FindMaxXSec(const Interaction *in, const int nkey=0) const
const InitialState & InitState(void) const
Definition: Interaction.h:69
#define pNOTICE
Definition: Messenger.h:61
static Cache * Instance(void)
Definition: Cache.cxx:67
A simple cache branch storing the cached data in a TNtuple.
Definition: CacheBranchFx.h:49
double XMin(void) const
Definition: Spline.h:88
double ProbeE(RefFrame_t rf) const
GENIE&#39;s GHEP MC event record.
Definition: GHepRecord.h:45
string Key(void) const
Definition: AlgId.h:46
const UInt_t kISkipProcessChk
if set, skip process validity checks
Definition: Interaction.h:47
virtual void SetDiffXSec(double xsec, KinePhaseSpace_t ps)
Definition: GHepRecord.h:133
Initial State information.
Definition: InitialState.h:48
std::vector< string > vInterpolatorTypes
Type of interpolator for each key in a branch.
virtual void CacheMaxXSec(const Interaction *in, double xsec, const int nkey=0) const