GENIEGenerator
Loading...
Searching...
No Matches
DISKinematicsGenerator.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 <cfloat>
12
13#include <TMath.h>
14
16#include "Framework/Conventions/GBuild.h"
31
32using namespace genie;
33using namespace genie::controls;
34using namespace genie::utils;
35
36//___________________________________________________________________________
38KineGeneratorWithCache("genie::DISKinematicsGenerator")
39{
40
41}
42//___________________________________________________________________________
44KineGeneratorWithCache("genie::DISKinematicsGenerator", config)
45{
46
47}
48//___________________________________________________________________________
53//___________________________________________________________________________
55{
57 LOG("DISKinematics", pNOTICE)
58 << "Generating kinematics uniformly over the allowed phase space";
59 }
60
61 //-- Get the random number generators
63
64 //-- Access cross section algorithm for running thread
66 const EventGeneratorI * evg = rtinfo->RunningThread();
68
69 //-- Get the interaction
70 Interaction * interaction = evrec->Summary();
71 interaction->SetBit(kISkipProcessChk);
72
73 //-- Get neutrino energy and hit 'nucleon mass'
74 const InitialState & init_state = interaction->InitState();
75 double Ev = init_state.ProbeE(kRfHitNucRest);
76 double M = init_state.Tgt().HitNucP4().M(); // can be off m-shell
77
78 //-- Get the physical W range
79 const KPhaseSpace & kps = interaction->PhaseSpace();
80 Range1D_t W = kps.Limits(kKVW);
81 if(W.max <=0 || W.min>=W.max) {
82 LOG("DISKinematics", pWARN) << "No available phase space";
83 evrec->EventFlags()->SetBitNumber(kKineGenErr, true);
85 exception.SetReason("No available phase space");
86 exception.SwitchOnFastForward();
87 throw exception;
88 }
89
90 Range1D_t xl = kps.Limits(kKVx);
91 Range1D_t yl = kps.Limits(kKVy);
92
93 LOG("DISKinematics", pNOTICE) << "x: [" << xl.min << ", " << xl.max << "]";
94 LOG("DISKinematics", pNOTICE) << "y: [" << yl.min << ", " << yl.max << "]";
95
96 assert(xl.min>0 && yl.min>0);
97
98 //-- For the subsequent kinematic selection with the rejection method:
99 // Calculate the max differential cross section or retrieve it from the
100 // cache. Throw an exception and quit the evg thread if a non-positive
101 // value is found.
102 // If the kinematics are generated uniformly over the allowed phase
103 // space the max xsec is irrelevant
104 double xsec_max = (fGenerateUniformly) ? -1 : this->MaxXSec(evrec);
105
106 //-- Try to select a valid (x,y) pair using the rejection method
107
108 double dx = xl.max - xl.min;
109 double dy = yl.max - yl.min;
110 double gx=-1, gy=-1, gW=-1, gQ2=-1, xsec=-1;
111
112 unsigned int iter = 0;
113 bool accept = false;
114 while(1) {
115 iter++;
116 if(iter > kRjMaxIterations) {
117 LOG("DISKinematics", pWARN)
118 << " Couldn't select kinematics after " << iter << " iterations";
119 evrec->EventFlags()->SetBitNumber(kKineGenErr, true);
121 exception.SetReason("Couldn't select kinematics");
122 exception.SwitchOnFastForward();
123 throw exception;
124 }
125
126 //-- random x,y
127 gx = xl.min + dx * rnd->RndKine().Rndm();
128 gy = yl.min + dy * rnd->RndKine().Rndm();
129 interaction->KinePtr()->Setx(gx);
130 interaction->KinePtr()->Sety(gy);
131 kinematics::UpdateWQ2FromXY(interaction);
132
133 LOG("DISKinematics", pNOTICE)
134 << "Trying: x = " << gx << ", y = " << gy
135 << " (W = " << interaction->KinePtr()->W() << ","
136 << " (Q2 = " << interaction->KinePtr()->Q2() << ")";
137
138 //-- compute the cross section for current kinematics
139 xsec = fXSecModel->XSec(interaction, kPSxyfE);
140
141 //-- decide whether to accept the current kinematics
142 if(!fGenerateUniformly) {
143 this->AssertXSecLimits(interaction, xsec, xsec_max);
144 double t = xsec_max * rnd->RndKine().Rndm();
145 double J = 1;
146
147#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
148 LOG("DISKinematics", pDEBUG)
149 << "xsec= " << xsec << ", J= " << J << ", Rnd= " << t;
150#endif
151 accept = (t < J*xsec);
152 }
153 else {
154 accept = (xsec>0);
155 }
156
157 //-- If the generated kinematics are accepted, finish-up module's job
158 if(accept) {
159 LOG("DISKinematics", pNOTICE)
160 << "Selected: x = " << gx << ", y = " << gy
161 << " (W = " << interaction->KinePtr()->W() << ","
162 << " (Q2 = " << interaction->KinePtr()->Q2() << ")";
163
164 // reset trust bits
165 interaction->ResetBit(kISkipProcessChk);
166 interaction->ResetBit(kISkipKinematicChk);
167
168 // set the cross section for the selected kinematics
169 evrec->SetDiffXSec(xsec,kPSxyfE);
170
171 // for uniform kinematics, compute an event weight as
172 // wght = (phase space volume)*(differential xsec)/(event total xsec)
174 double vol = kinematics::PhaseSpaceVolume(interaction,kPSxyfE);
175 double totxsec = evrec->XSec();
176 double wght = (vol/totxsec)*xsec;
177 LOG("DISKinematics", pNOTICE) << "Kinematics wght = "<< wght;
178
179 // apply computed weight to the current event weight
180 wght *= evrec->Weight();
181 LOG("DISKinematics", pNOTICE) << "Current event wght = " << wght;
182 evrec->SetWeight(wght);
183 }
184
185 // compute W,Q2 for selected x,y
186 //bool is_em = interaction->ProcInfo().IsEM();
187 kinematics::XYtoWQ2(Ev,M,gW,gQ2,gx,gy);
188
189 LOG("DISKinematics", pNOTICE)
190 << "Selected x,y => W = " << gW << ", Q2 = " << gQ2;
191
192 // lock selected kinematics & clear running values
193 interaction->KinePtr()->SetW (gW, true);
194 interaction->KinePtr()->SetQ2(gQ2, true);
195 interaction->KinePtr()->Setx (gx, true);
196 interaction->KinePtr()->Sety (gy, true);
197 interaction->KinePtr()->ClearRunningValues();
198 return;
199 }
200 } // iterations
201}
202//___________________________________________________________________________
208//____________________________________________________________________________
214//____________________________________________________________________________
216{
217// Reads its configuration data from its configuration Registry and loads them
218// in private data members to avoid looking up at the Registry all the time.
219
220 //-- Safety factor for the maximum differential cross section
221 GetParamDef( "MaxXSec-SafetyFactor", fSafetyFactor, 1.25 ) ;
222
223 //-- Minimum energy for which max xsec would be cached, forcing explicit
224 // calculation for lower eneries
225 GetParamDef( "Cache-MinEnergy", fEMin, 0.8 ) ;
226
227 //-- Maximum allowed fractional cross section deviation from maxim cross
228 // section used in rejection method
229 GetParamDef( "MaxXSec-DiffTolerance", fMaxXSecDiffTolerance, 999999. ) ;
230 assert(fMaxXSecDiffTolerance>=0);
231
232 //-- Generate kinematics uniformly over allowed phase space and compute
233 // an event weight?
234 GetParamDef( "UniformOverPhaseSpace", fGenerateUniformly, false ) ;
235
236}
237//____________________________________________________________________________
239 const Interaction * interaction) const
240{
241// Computes the maximum differential cross section in the requested phase
242// space. This method overloads KineGeneratorWithCache::ComputeMaxXSec
243// method and the value is cached at a circular cache branch for retrieval
244// during subsequent event generation.
245// The computed max differential cross section does not need to be the exact
246// maximum. The number used in the rejection method will be scaled up by a
247// safety factor. But this needs to be fast - do not use a very fine grid.
248
249#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
250 LOG("DISKinematics", pDEBUG)<< "Computing max xsec in allowed phase space";
251#endif
252 double max_xsec = 0.0;
253
254 const InitialState & init_state = interaction->InitState();
255 //double Ev = init_state.ProbeE(kRfHitNucRest);
256 //const ProcessInfo & proc = interaction->ProcInfo();
257 const Target & tgt = init_state.Tgt();
258
259 int Ny = 20;
260 int Nx = 40;
261 int Nxb = 3;
262
263 double xpeak = .2;
264 double xwindow = .2;
265 double ypeak = .5;
266 double ywindow = .5;
267
268 if(tgt.HitQrkIsSet()) {
269 if(tgt.HitSeaQrk()) {
270 xpeak = .1;
271 xwindow = .1;
272 ypeak = .7;
273 ywindow = .3;
274 } else {
275 xpeak = .2;
276 xwindow = .2;
277 ypeak = .7;
278 ywindow = .3;
279 }
280 }
281
282 const KPhaseSpace & kps = interaction->PhaseSpace();
283 Range1D_t xl = kps.Limits(kKVx);
284 Range1D_t yl = kps.Limits(kKVy);
285
286 double xmin = TMath::Max(xpeak-xwindow, TMath::Max(xl.min, 5E-3));
287 double xmax = TMath::Min(xpeak+xwindow, xl.max);
288 double ymin = TMath::Max(ypeak-ywindow, TMath::Max(yl.min, 2E-3));
289 double ymax = TMath::Min(ypeak+ywindow, yl.max);
290 double dx = (xmax-xmin)/(Nx-1);
291 double dy = (ymax-ymin)/(Ny-1);
292
293#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
294 LOG("DISKinematics", pDEBUG)
295 << "Searching max. in x [" << xmin << ", " << xmax << "], y [" << ymin << ", " << ymax << "]";
296#endif
297 double xseclast_y = -1;
298 bool increasing_y;
299
300 for(int i=0; i<Ny; i++) {
301 double gy = ymin + i*dy;
302 //double gy = TMath::Power(10., logymin + i*dlogy);
303 interaction->KinePtr()->Sety(gy);
304
305#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
306 LOG("DISKinematics", pDEBUG) << "y = " << gy;
307#endif
308 double xseclast_x = -1;
309 bool increasing_x;
310
311 for(int j=0; j<Nx; j++) {
312 double gx = xmin + j*dx;
313 //double gx = TMath::Power(10., logxmin + j*dlogx);
314 interaction->KinePtr()->Setx(gx);
315 kinematics::UpdateWQ2FromXY(interaction);
316
317 double xsec = fXSecModel->XSec(interaction, kPSxyfE);
318#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
319 LOG("DISKinematics", pINFO)
320 << "xsec(y=" << gy << ", x=" << gx << ") = " << xsec;
321#endif
322 // update maximum xsec
323 max_xsec = TMath::Max(xsec, max_xsec);
324
325 increasing_x = xsec-xseclast_x>=0;
326 xseclast_x = xsec;
327
328 // once the cross section stops increasing, I reduce the step size and
329 // step backwards a little bit to handle cases that the max cross section
330 // is grossly underestimated (very peaky distribution & large step)
331 if(!increasing_x) {
332#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
333 LOG("DISKinematics", pDEBUG)
334 << "d2xsec/dxdy|x stopped increasing. Stepping back & exiting x loop";
335#endif
336 //double dlogxn = dlogx/(Nxb+1);
337 double dxn = dx/(Nxb+1);
338 for(int ik=0; ik<Nxb; ik++) {
339 //gx = TMath::Exp(TMath::Log(gx) - dlogxn);
340 gx = gx - dxn;
341 interaction->KinePtr()->Setx(gx);
342 kinematics::UpdateWQ2FromXY(interaction);
343 xsec = fXSecModel->XSec(interaction, kPSxyfE);
344#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
345 LOG("DISKinematics", pINFO)
346 << "xsec(y=" << gy << ", x=" << gx << ") = " << xsec;
347#endif
348 }
349 break;
350 } // stepping back within last bin
351 } // x
352 increasing_y = max_xsec-xseclast_y>=0;
353 xseclast_y = max_xsec;
354 if(!increasing_y) {
355#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
356 LOG("DISKinematics", pDEBUG)
357 << "d2xsec/dxdy stopped increasing. Exiting y loop";
358#endif
359 break;
360 }
361 }// y
362
363 // Apply safety factor, since value retrieved from the cache might
364 // correspond to a slightly different energy
365 // max_xsec *= fSafetyFactor;
366 //max_xsec *= ( (Ev<3.0) ? 2.5 : fSafetyFactor);
367 max_xsec *= 3;
368
369#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
370 SLOG("DISKinematics", pDEBUG) << interaction->AsString();
371 SLOG("DISKinematics", pDEBUG) << "Max xsec in phase space = " << max_xsec;
372 SLOG("DISKinematics", pDEBUG) << "Computed using alg = " << *fXSecModel;
373#endif
374
375 return max_xsec;
376}
377//___________________________________________________________________________
#define pNOTICE
Definition Messenger.h:61
#define pINFO
Definition Messenger.h:62
#define pDEBUG
Definition Messenger.h:63
#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
#define SLOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a short string (using the FUNCTION and...
Definition Messenger.h:84
virtual void Configure(const Registry &config)
Definition Algorithm.cxx:62
bool GetParamDef(const RgKey &name, T &p, const T &def) const
void ProcessEventRecord(GHepRecord *event_rec) const
void Configure(const Registry &config)
double ComputeMaxXSec(const Interaction *interaction) const
Defines the EventGeneratorI interface.
virtual const XSecAlgorithmI * CrossSectionAlg(void) const =0
GENIE's GHEP MC event record.
Definition GHepRecord.h:45
virtual double Weight(void) const
Definition GHepRecord.h:124
virtual void SetDiffXSec(double xsec, KinePhaseSpace_t ps)
Definition GHepRecord.h:133
virtual double XSec(void) const
Definition GHepRecord.h:126
virtual Interaction * Summary(void) const
virtual TBits * EventFlags(void) const
Definition GHepRecord.h:117
virtual void SetWeight(double wght)
Definition GHepRecord.h:130
Initial State information.
const Target & Tgt(void) const
double ProbeE(RefFrame_t rf) const
Summary information for an interaction.
Definition Interaction.h:56
string AsString(void) const
const KPhaseSpace & PhaseSpace(void) const
Definition Interaction.h:73
const InitialState & InitState(void) const
Definition Interaction.h:69
Kinematics * KinePtr(void) const
Definition Interaction.h:76
Kinematical phase space.
Definition KPhaseSpace.h:33
Range1D_t Limits(KineVar_t kvar) const
Return the kinematical variable limits.
virtual void AssertXSecLimits(const Interaction *in, double xsec, double xsec_max) const
bool fGenerateUniformly
uniform over allowed phase space + event weight?
double fMaxXSecDiffTolerance
max{100*(xsec-maxxsec)/.5*(xsec+maxxsec)} if xsec>maxxsec
double fEMin
min E for which maxxsec is cached - forcing explicit calc.
double fSafetyFactor
ComputeMaxXSec -> ComputeMaxXSec * fSafetyFactor.
virtual double MaxXSec(GHepRecord *evrec, const int nkey=0) const
void Setx(double x, bool selected=false)
void SetQ2(double Q2, bool selected=false)
double Q2(bool selected=false) const
double W(bool selected=false) const
void ClearRunningValues(void)
void Sety(double y, bool selected=false)
void SetW(double W, bool selected=false)
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition RandomGen.h:29
static RandomGen * Instance()
Access instance.
Definition RandomGen.cxx:74
TRandom3 & RndKine(void) const
rnd number generator used by kinematics generators
Definition RandomGen.h:50
A simple [min,max] interval for doubles.
Definition Range1.h:43
A registry. Provides the container for algorithm configuration parameters.
Definition Registry.h:65
Keep info on the event generation thread currently on charge. This is used so that event generation m...
static RunningThreadInfo * Instance(void)
const EventGeneratorI * RunningThread(void)
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
Definition Target.h:40
const TLorentzVector & HitNucP4(void) const
Definition Target.h:91
bool HitSeaQrk(void) const
Definition Target.cxx:299
bool HitQrkIsSet(void) const
Definition Target.cxx:292
An exception thrown by EventRecordVisitorI when the normal processing sequence has to be disrupted (f...
double gQ2
Misc GENIE control constants.
static const unsigned int kRjMaxIterations
Definition Controls.h:26
Simple functions for loading and reading nucleus dependent keys from config files.
void UpdateWQ2FromXY(const Interaction *in)
void XYtoWQ2(double Ev, double M, double &W, double &Q2, double x, double y)
double PhaseSpaceVolume(const Interaction *const i, KinePhaseSpace_t ps)
Definition KineUtils.cxx:36
Root of GENIE utility namespaces.
THE MAIN GENIE PROJECT NAMESPACE
Definition AlgCmp.h:25
@ kKVx
Definition KineVar.h:31
@ kKVy
Definition KineVar.h:32
@ kKVW
Definition KineVar.h:35
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