Skip to content

Commit

Permalink
Pythia8 seeding improvements
Browse files Browse the repository at this point in the history
This commit improves the seeding of Pythia8 in O2.
The seeding...

(a) ... is now done as part of the object's Init function automatically.
    Users are no longer required to provide own seeding logic,
    which can significantly simplify the setup.
    By default, Pythia8 will seed against ROOT TRandom::GetSeed,
    which is itself set to values of the command line option `--seed`,
    used in the o2-sim ... or o2-sim-dpl-eventgen execetuables (which
    are the 2 places undertaking event generation). This setup guarantees
    that

    ```
    o2-sim-dpl-eventgen --generator pythiapp --seed x
    ```
    will result in different event sequences when x changes.

(b) Users can simply set the seed via a `setInitialSeed` function
    on the GeneratorPythia8 object. The function must be called before
    GeneratorPythia8::Init is executed. So calling it right after the constructor
    is fine.

    Example code (e.g., inside user Generator macro) is:

    ```
    auto mygen = new o2::eventgen::GeneratorPythia8();
    long seed = atol(getenv(ALIEN_PROC_ID));
    if(!mygen->setInitialSeed(seed)) {
      std::cerr << "seeding failed";
    }
    ```

In result, the commit leads to a simplification of the Pythia8
setup also in GeneratorFactory.
  • Loading branch information
sawenzel committed Jul 8, 2024
1 parent a067a54 commit 75f9579
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 6 deletions.
15 changes: 15 additions & 0 deletions Generators/include/Generators/GeneratorPythia8.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ class GeneratorPythia8 : public Generator

typedef std::function<bool(const Pythia8::Particle&)> UserFilterFcn;

/// A function allowing to set the initial value used in seeding Pythia.
/// The function needs to be called before GeneratorPythia8::Init is invoked.
/// The function value will be true upon success, or false if either Init has already been called or if the see is smaller than 0.
/// For values of seed >= 0, a truncation to the range [0:90000000] will automatically take place via a modulus operation.
bool setInitialSeed(long seed);

protected:
/** copy constructor **/
GeneratorPythia8(const GeneratorPythia8&);
Expand Down Expand Up @@ -251,6 +257,9 @@ class GeneratorPythia8 : public Generator
void getNfreeSpec(const Pythia8::Info& info, int& nFreenProj, int& nFreepProj, int& nFreenTarg, int& nFreepTarg);
/** @} */

/// performs seeding of the random state of Pythia (called from Init)
void seedGenerator();

/** Pythia8 **/
Pythia8::Pythia mPythia; //!

Expand All @@ -269,6 +278,12 @@ class GeneratorPythia8 : public Generator
void initUserFilterCallback();

bool mApplyPruning = false;
bool mIsInitialized = false; // if Init function has been called
long mInitialRNGSeed = -1; // initial seed for Pythia random number state;
// will be transported to Pythia in the Init function through the Pythia::readString("Random:seed") mechanism.
// Value of -1 means unitialized; 0 will be time-dependent and values >1 <= MAX_SEED concrete reproducible seeding

constexpr static long MAX_SEED = 900000000;

ClassDefOverride(GeneratorPythia8, 1);

Expand Down
8 changes: 2 additions & 6 deletions Generators/src/GeneratorFactory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,9 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair
auto makePythia8Gen = [](std::string& config) {
auto gen = new o2::eventgen::GeneratorPythia8();
if (!config.empty()) {
LOG(info) << "Reading \'Pythia8\' base configuration: " << config << std::endl;
gen->readFile(config);
LOG(info) << "Setting \'Pythia8\' base configuration: " << config << std::endl;
gen->setConfig(config); // assign config; will be executed in Init function
}
auto seed = (gRandom->TRandom::GetSeed() % 900000000);
LOG(info) << "Using random seed from gRandom % 900000000: " << seed;
gen->readString("Random:setSeed on");
gen->readString("Random:seed " + std::to_string(seed));
return gen;
};
#endif
Expand Down
48 changes: 48 additions & 0 deletions Generators/src/GeneratorPythia8.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,46 @@ GeneratorPythia8::GeneratorPythia8(const Char_t* name, const Char_t* title) : Ge
mInterfaceName = "pythia8";
}

bool GeneratorPythia8::setInitialSeed(long seed)
{
// check first of all if Init not yet called and seed not <0
if (mIsInitialized) {
return false;
}
if (seed < 0) {
return false;
}
// sets the initial seed and applies the correct Pythia
// range
mInitialRNGSeed = seed % (MAX_SEED + 1);
LOG(info) << "GeneratorPythia8: Setting initial seed to " << mInitialRNGSeed;
return true;
}

/*****************************************************************/
void GeneratorPythia8::seedGenerator()
{
/// Function is seeding the Pythia random numbers.
/// In case a completely different logic is required by users,
/// we could make this function virtual or allow to set/execute
/// a user-given lambda function instead.

/// Note that this function is executed **before** the Pythia8
/// user config file is read. So the config file should either not contain seeding information ... or can be used to override seeding logic.

auto seed = mInitialRNGSeed;
if (seed == -1) {
// Will use the mInitialRNGSeed if it was set.
// Otherwise will seed the generator with the state of
// TRandom::GetSeed. This is the seed that is influenced from
// SimConfig --seed command line options options.
seed = (gRandom->TRandom::GetSeed() % (MAX_SEED + 1));
LOG(info) << "GeneratorPythia8: Using random seed from gRandom % 900000001: " << seed;
}
mPythia.readString("Random:setSeed on");
mPythia.readString("Random:seed " + std::to_string(seed));
}

/*****************************************************************/

Bool_t GeneratorPythia8::Init()
Expand All @@ -80,6 +120,12 @@ Bool_t GeneratorPythia8::Init()
/** init base class **/
Generator::Init();

/** Seed the Pythia random number state.
The user may override this seeding by providing separate
Random:setSeed configurations in the configuration file.
**/
seedGenerator();

/** read configuration **/
if (!mConfig.empty()) {
std::stringstream ss(mConfig);
Expand Down Expand Up @@ -147,6 +193,8 @@ Bool_t GeneratorPythia8::Init()

initUserFilterCallback();

mIsInitialized = true;

/** success **/
return true;
}
Expand Down

0 comments on commit 75f9579

Please sign in to comment.