GENIEGenerator
Loading...
Searching...
No Matches
DMDISKinematicsGenerator.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
7 Author: Joshua Berger
8 University of Wisconsin-Madison
9
10 Costas Andreopoulos <c.andreopoulos \at cern.ch>
11 University of Liverpool
12*/
13//____________________________________________________________________________
14
15#include <cfloat>
16
17#include <TMath.h>
18
20#include "Framework/Conventions/GBuild.h"
35
36using namespace genie;
37using namespace genie::controls;
38using namespace genie::utils;
39
40//___________________________________________________________________________
42KineGeneratorWithCache("genie::DMDISKinematicsGenerator")
43{
44
45}
46//___________________________________________________________________________
48KineGeneratorWithCache("genie::DMDISKinematicsGenerator", config)
49{
50
51}
52//___________________________________________________________________________
57//___________________________________________________________________________
59{
61 LOG("DMDISKinematics", pNOTICE)
62 << "Generating kinematics uniformly over the allowed phase space";
63 }
64
65 //-- Get the random number generators
67
68 //-- Access cross section algorithm for running thread
70 const EventGeneratorI * evg = rtinfo->RunningThread();
72
73 //-- Get the interaction
74 Interaction * interaction = evrec->Summary();
75 interaction->SetBit(kISkipProcessChk);
76
77 //-- Get dark matter energy and hit 'nucleon mass'
78 const InitialState & init_state = interaction->InitState();
79 double Ev = init_state.ProbeE(kRfHitNucRest);
80 double M = init_state.Tgt().HitNucP4().M(); // can be off m-shell
81
82 //-- Get the physical W range
83 const KPhaseSpace & kps = interaction->PhaseSpace();
84 Range1D_t W = kps.Limits(kKVW);
85 if(W.max <=0 || W.min>=W.max) {
86 LOG("DMDISKinematics", pWARN) << "No available phase space";
87 evrec->EventFlags()->SetBitNumber(kKineGenErr, true);
89 exception.SetReason("No available phase space");
90 exception.SwitchOnFastForward();
91 throw exception;
92 }
93
94 Range1D_t xl = kps.Limits(kKVx);
95 Range1D_t yl = kps.Limits(kKVy);
96
97 LOG("DMDISKinematics", pNOTICE) << "x: [" << xl.min << ", " << xl.max << "]";
98 LOG("DMDISKinematics", pNOTICE) << "y: [" << yl.min << ", " << yl.max << "]";
99
100 assert(xl.min>0 && yl.min>0);
101
102 //-- For the subsequent kinematic selection with the rejection method:
103 // Calculate the max differential cross section or retrieve it from the
104 // cache. Throw an exception and quit the evg thread if a non-positive
105 // value is found.
106 // If the kinematics are generated uniformly over the allowed phase
107 // space the max xsec is irrelevant
108 double xsec_max = (fGenerateUniformly) ? -1 : this->MaxXSec(evrec);
109
110 //-- Try to select a valid (x,y) pair using the rejection method
111
112 double dx = xl.max - xl.min;
113 double dy = yl.max - yl.min;
114 double gx=-1, gy=-1, gW=-1, gQ2=-1, xsec=-1;
115
116 unsigned int iter = 0;
117 bool accept = false;
118 while(1) {
119 iter++;
120 if(iter > kRjMaxIterations) {
121 LOG("DMDISKinematics", pWARN)
122 << " Couldn't select kinematics after " << iter << " iterations";
123 evrec->EventFlags()->SetBitNumber(kKineGenErr, true);
125 exception.SetReason("Couldn't select kinematics");
126 exception.SwitchOnFastForward();
127 throw exception;
128 }
129
130 //-- random x,y
131 gx = xl.min + dx * rnd->RndKine().Rndm();
132 gy = yl.min + dy * rnd->RndKine().Rndm();
133 interaction->KinePtr()->Setx(gx);
134 interaction->KinePtr()->Sety(gy);
135 kinematics::UpdateWQ2FromXY(interaction);
136
137 LOG("DMDISKinematics", pNOTICE)
138 << "Trying: x = " << gx << ", y = " << gy
139 << " (W = " << interaction->KinePtr()->W() << ","
140 << " (Q2 = " << interaction->KinePtr()->Q2() << ")";
141
142 //-- compute the cross section for current kinematics
143 xsec = fXSecModel->XSec(interaction, kPSxyfE);
144
145 //-- decide whether to accept the current kinematics
146 if(!fGenerateUniformly) {
147 this->AssertXSecLimits(interaction, xsec, xsec_max);
148 double t = xsec_max * rnd->RndKine().Rndm();
149 double J = 1;
150
151#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
152 LOG("DMDISKinematics", pDEBUG)
153 << "xsec= " << xsec << ", J= " << J << ", Rnd= " << t;
154#endif
155 accept = (t < J*xsec);
156 }
157 else {
158 accept = (xsec>0);
159 }
160
161 //-- If the generated kinematics are accepted, finish-up module's job
162 if(accept) {
163 LOG("DMDISKinematics", pNOTICE)
164 << "Selected: x = " << gx << ", y = " << gy
165 << " (W = " << interaction->KinePtr()->W() << ","
166 << " (Q2 = " << interaction->KinePtr()->Q2() << ")";
167
168 // reset trust bits
169 interaction->ResetBit(kISkipProcessChk);
170 interaction->ResetBit(kISkipKinematicChk);
171
172 // set the cross section for the selected kinematics
173 evrec->SetDiffXSec(xsec,kPSxyfE);
174
175 // for uniform kinematics, compute an event weight as
176 // wght = (phase space volume)*(differential xsec)/(event total xsec)
178 double vol = kinematics::PhaseSpaceVolume(interaction,kPSxyfE);
179 double totxsec = evrec->XSec();
180 double wght = (vol/totxsec)*xsec;
181 LOG("DMDISKinematics", pNOTICE) << "Kinematics wght = "<< wght;
182
183 // apply computed weight to the current event weight
184 wght *= evrec->Weight();
185 LOG("DMDISKinematics", pNOTICE) << "Current event wght = " << wght;
186 evrec->SetWeight(wght);
187 }
188
189 // compute W,Q2 for selected x,y
190 kinematics::XYtoWQ2(Ev,M,gW,gQ2,gx,gy);
191
192 LOG("DMDISKinematics", pNOTICE)
193 << "Selected x,y => W = " << gW << ", Q2 = " << gQ2;
194
195 // lock selected kinematics & clear running values
196 interaction->KinePtr()->SetW (gW, true);
197 interaction->KinePtr()->SetQ2(gQ2, true);
198 interaction->KinePtr()->Setx (gx, true);
199 interaction->KinePtr()->Sety (gy, true);
200 interaction->KinePtr()->ClearRunningValues();
201 return;
202 }
203 } // iterations
204}
205//___________________________________________________________________________
211//____________________________________________________________________________
217//____________________________________________________________________________
219{
220// Reads its configuration data from its configuration Registry and loads them
221// in private data members to avoid looking up at the Registry all the time.
222
223 //-- Safety factor for the maximum differential cross section
224 GetParamDef( "MaxXSec-SafetyFactor", fSafetyFactor, 1.25 ) ;
225
226 //-- Minimum energy for which max xsec would be cached, forcing explicit
227 // calculation for lower eneries
228 GetParamDef( "Cache-MinEnergy", fEMin, 0.8 ) ;
229
230 //-- Maximum allowed fractional cross section deviation from maxim cross
231 // section used in rejection method
232 GetParamDef( "MaxXSec-DiffTolerance", fMaxXSecDiffTolerance, 999999. ) ;
233 assert(fMaxXSecDiffTolerance>=0);
234
235 //-- Generate kinematics uniformly over allowed phase space and compute
236 // an event weight?
237 GetParamDef( "UniformOverPhaseSpace", fGenerateUniformly, false ) ;
238
239}
240//____________________________________________________________________________
242 const Interaction * interaction) const
243{
244// Computes the maximum differential cross section in the requested phase
245// space. This method overloads KineGeneratorWithCache::ComputeMaxXSec
246// method and the value is cached at a circular cache branch for retrieval
247// during subsequent event generation.
248// The computed max differential cross section does not need to be the exact
249// maximum. The number used in the rejection method will be scaled up by a
250// safety factor. But this needs to be fast - do not use a very fine grid.
251
252#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
253 LOG("DMDISKinematics", pDEBUG)<< "Computing max xsec in allowed phase space";
254#endif
255 double max_xsec = 0.0;
256
257 const InitialState & init_state = interaction->InitState();
258 //double Ev = init_state.ProbeE(kRfHitNucRest);
259 //const ProcessInfo & proc = interaction->ProcInfo();
260 const Target & tgt = init_state.Tgt();
261
262 int Ny = 20;
263 int Nx = 40;
264 int Nxb = 3;
265
266 const KPhaseSpace & kps = interaction->PhaseSpace();
267 Range1D_t xl = kps.Limits(kKVx);
268 Range1D_t yl = kps.Limits(kKVy);
269
270 // Look over full region or risk not finding valid phase space
271 double xmin = TMath::Max(xl.min, 5E-3);
272 double xmax = xl.max;
273 double ymin = TMath::Max(yl.min, 2E-3);
274 double ymax = yl.max;
275 double dx = (xmax-xmin)/(Nx-1);
276 double dy = (ymax-ymin)/(Ny-1);
277
278#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
279 LOG("DMDISKinematics", pDEBUG)
280 << "Searching max. in x [" << xmin << ", " << xmax << "], y [" << ymin << ", " << ymax << "]";
281#endif
282 double xseclast_y = -1;
283 bool increasing_y;
284
285 for(int i=0; i<Ny; i++) {
286 double gy = ymin + i*dy;
287 //double gy = TMath::Power(10., logymin + i*dlogy);
288 interaction->KinePtr()->Sety(gy);
289
290#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
291 LOG("DMDISKinematics", pDEBUG) << "y = " << gy;
292#endif
293 double xseclast_x = -1;
294 bool increasing_x;
295
296 for(int j=0; j<Nx; j++) {
297 double gx = xmin + j*dx;
298 //double gx = TMath::Power(10., logxmin + j*dlogx);
299 interaction->KinePtr()->Setx(gx);
300 kinematics::UpdateWQ2FromXY(interaction);
301
302 double xsec = fXSecModel->XSec(interaction, kPSxyfE);
303#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
304 LOG("DMDISKinematics", pINFO)
305 << "xsec(y=" << gy << ", x=" << gx << ") = " << xsec;
306#endif
307 // update maximum xsec
308 max_xsec = TMath::Max(xsec, max_xsec);
309
310 increasing_x = xsec-xseclast_x>=0;
311 xseclast_x = xsec;
312
313 // once the cross section stops increasing, I reduce the step size and
314 // step backwards a little bit to handle cases that the max cross section
315 // is grossly underestimated (very peaky distribution & large step)
316 if(!increasing_x) {
317#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
318 LOG("DMDISKinematics", pDEBUG)
319 << "d2xsec/dxdy|x stopped increasing. Stepping back & exiting x loop";
320#endif
321 //double dlogxn = dlogx/(Nxb+1);
322 double dxn = dx/(Nxb+1);
323 for(int ik=0; ik<Nxb; ik++) {
324 //gx = TMath::Exp(TMath::Log(gx) - dlogxn);
325 gx = gx - dxn;
326 interaction->KinePtr()->Setx(gx);
327 kinematics::UpdateWQ2FromXY(interaction);
328 xsec = fXSecModel->XSec(interaction, kPSxyfE);
329#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
330 LOG("DMDISKinematics", pINFO)
331 << "xsec(y=" << gy << ", x=" << gx << ") = " << xsec;
332#endif
333 }
334 break;
335 } // stepping back within last bin
336 } // x
337 increasing_y = max_xsec-xseclast_y>=0;
338 xseclast_y = max_xsec;
339 if(!increasing_y) {
340#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
341 LOG("DMDISKinematics", pDEBUG)
342 << "d2xsec/dxdy stopped increasing. Exiting y loop";
343#endif
344 break;
345 }
346 }// y
347
348 // Apply safety factor, since value retrieved from the cache might
349 // correspond to a slightly different energy
350 // max_xsec *= fSafetyFactor;
351 //max_xsec *= ( (Ev<3.0) ? 2.5 : fSafetyFactor);
352 max_xsec *= 3;
353
354#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
355 SLOG("DMDISKinematics", pDEBUG) << interaction->AsString();
356 SLOG("DMDISKinematics", pDEBUG) << "Max xsec in phase space = " << max_xsec;
357 SLOG("DMDISKinematics", pDEBUG) << "Computed using alg = " << *fXSecModel;
358#endif
359
360 return max_xsec;
361}
362//___________________________________________________________________________
363
#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
double ComputeMaxXSec(const Interaction *interaction) const
void ProcessEventRecord(GHepRecord *event_rec) 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
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