GENIEGenerator
Loading...
Searching...
No Matches
KineGeneratorWithCache.cxx
Go to the documentation of this file.
1//____________________________________________________________________________
2/*
3 Copyright (c) 2003-2025, 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
27
28using std::ostringstream;
29using std::map;
30
31using namespace genie;
32
33//___________________________________________________________________________
39//___________________________________________________________________________
45//___________________________________________________________________________
51//___________________________________________________________________________
56//___________________________________________________________________________
57double 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//___________________________________________________________________________
213double 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);
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//___________________________________________________________________________
283double 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 pNOTICE
Definition Messenger.h:61
#define pINFO
Definition Messenger.h:62
#define pERROR
Definition Messenger.h:59
#define pFATAL
Definition Messenger.h:56
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
Definition Messenger.h:96
#define pWARN
Definition Messenger.h:60
string Key(void) const
Definition AlgId.h:46
virtual const AlgId & Id(void) const
Get algorithm ID.
Definition Algorithm.h:98
A simple cache branch storing the cached data in a TNtuple.
void CreateSpline(string type="TSpline3")
Spline * Spl(void) const
void AddValues(double x, double y)
const map< double, double > & Map(void) const
GENIE Cache Memory.
Definition Cache.h:39
string CacheBranchKey(string k0, string k1="", string k2="") const
Definition Cache.cxx:93
void AddCacheBranch(string key, CacheBranchI *branch)
Definition Cache.cxx:88
static Cache * Instance(void)
Definition Cache.cxx:67
CacheBranchI * FindCacheBranch(string key)
finding/adding cache branches
Definition Cache.cxx:80
GENIE's GHEP MC event record.
Definition GHepRecord.h:45
virtual void SetDiffXSec(double xsec, KinePhaseSpace_t ps)
Definition GHepRecord.h:133
virtual Interaction * Summary(void) const
virtual TBits * EventFlags(void) const
Definition GHepRecord.h:117
Initial State information.
double ProbeE(RefFrame_t rf) const
Summary information for an interaction.
Definition Interaction.h:56
string AsString(void) const
const InitialState & InitState(void) const
Definition Interaction.h:69
virtual void AssertXSecLimits(const Interaction *in, double xsec, double xsec_max) const
std::vector< string > vInterpolatorTypes
Type of interpolator for each key in a branch.
std::vector< double > vSafetyFactors
MaxXSec -> MaxXSec * fSafetyFactors[nkey].
virtual double FindMaxXSec(const Interaction *in, const int nkey=0) const
virtual void CacheMaxXSec(const Interaction *in, double xsec, const int nkey=0) const
double fMaxXSecDiffTolerance
max{100*(xsec-maxxsec)/.5*(xsec+maxxsec)} if xsec>maxxsec
virtual double ComputeMaxXSec(const Interaction *in) const =0
double fEMin
min E for which maxxsec is cached - forcing explicit calc.
double fSafetyFactor
ComputeMaxXSec -> ComputeMaxXSec * fSafetyFactor.
int fNumOfInterpolatorTypes
Number of given interpolators types.
virtual double Energy(const Interaction *in) const
int fNumOfSafetyFactors
Number of given safety factors.
virtual double MaxXSec(GHepRecord *evrec, const int nkey=0) const
virtual CacheBranchFx * AccessCacheBranch(const Interaction *in, const int nkey=0) const
double Evaluate(double x) const
Definition Spline.cxx:363
double XMax(void) const
Definition Spline.h:89
double XMin(void) const
Definition Spline.h:88
An exception thrown by EventRecordVisitorI when the normal processing sequence has to be disrupted (f...
THE MAIN GENIE PROJECT NAMESPACE
Definition AlgCmp.h:25
const UInt_t kISkipKinematicChk
if set, skip kinematic validity checks
Definition Interaction.h:48
@ kRfHitNucRest
Definition RefFrame.h:30
const UInt_t kISkipProcessChk
if set, skip process validity checks
Definition Interaction.h:47
@ kKineGenErr
Definition GHepFlags.h:31