diff --git a/FixedOrderGen/src/main.cc b/FixedOrderGen/src/main.cc index 806d0d8..3be02f3 100644 --- a/FixedOrderGen/src/main.cc +++ b/FixedOrderGen/src/main.cc @@ -1,228 +1,233 @@ /** * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019 * \copyright GPLv2 or later */ #include <algorithm> #include <chrono> #include <fstream> #include <iostream> #include <map> #include <memory> #include "yaml-cpp/yaml.h" #include "LHEF/LHEF.h" #include "HEJ/CombinedEventWriter.hh" #include "HEJ/CrossSectionAccumulator.hh" #include "HEJ/get_analysis.hh" #include "HEJ/LesHouchesWriter.hh" #include "HEJ/make_RNG.hh" #include "HEJ/ProgressBar.hh" #include "HEJ/stream.hh" #include "config.hh" #include "EventGenerator.hh" #include "PhaseSpacePoint.hh" #include "Unweighter.hh" #include "Version.hh" namespace{ constexpr auto banner = - " __ ___ __ ______ __ __ \n" - " / / / (_)___ _/ /_ / ____/___ ___ _________ ___ __ / /__ / /______ \n" - " / /_/ / / __ `/ __ \\ / __/ / __ \\/ _ \\/ ___/ __ `/ / / / __ / / _ \\/ __/ ___/ \n" - " / __ / / /_/ / / / / / /___/ / / / __/ / / /_/ / /_/ / / /_/ / __/ /_(__ ) \n" - " /_/ /_/_/\\__, /_/ /_/ /_____/_/ /_/\\___/_/ \\__, /\\__, / \\____/\\___/\\__/____/ \n" - " ____///__/ __ ____ ///__//____/ ______ __ \n" - " / ____(_) _____ ____/ / / __ \\_________/ /__ _____ / ____/__ ____ ___ _________ _/ /_____ _____\n" - " / /_ / / |/_/ _ \\/ __ / / / / / ___/ __ / _ \\/ ___/ / / __/ _ \\/ __ \\/ _ \\/ ___/ __ `/ __/ __ \\/ ___/\n" - " / __/ / /> </ __/ /_/ / / /_/ / / / /_/ / __/ / / /_/ / __/ / / / __/ / / /_/ / /_/ /_/ / / \n" - " /_/ /_/_/|_|\\___/\\__,_/ \\____/_/ \\__,_/\\___/_/ \\____/\\___/_/ /_/\\___/_/ \\__,_/\\__/\\____/_/ \n" - ; + " __ ___ __ ______ __ " + " __ \n / / / (_)___ _/ /_ / ____/___ " + " ___ _________ ___ __ / /__ / /______ \n " + " / /_/ / / __ `/ __ \\ / __/ / __ \\/ _ \\/ ___/ __ `/ / / / __ / / _" + " \\/ __/ ___/ \n / __ / / /_/ / / / / / /___/ /" + " / / __/ / / /_/ / /_/ / / /_/ / __/ /_(__ ) " + " \n /_/ /_/_/\\__, /_/ /_/ /_____/_/ /_/\\___/_/ \\__, /\\__, / \\___" + "_/\\___/\\__/____/ \n ____///__/ " + "__ ____ ///__//____/ ______ __ " + " \n / ____(_) _____ ____/ / / __ \\_________/ /__ _____ / " + "____/__ ____ ___ _________ _/ /_____ _____\n / /_ / / |/_/ _ \\/ __" + " / / / / / ___/ __ / _ \\/ ___/ / / __/ _ \\/ __ \\/ _ \\/ ___/ __ `/ " + "__/ __ \\/ ___/\n / __/ / /> </ __/ /_/ / / /_/ / / / /_/ / __/ / " + " / /_/ / __/ / / / __/ / / /_/ / /_/ /_/ / / \n /_/ /_/_/|_|\\___" + "/\\__,_/ \\____/_/ \\__,_/\\___/_/ \\____/\\___/_/ /_/\\___/_/ " + "\\__,_/\\__/\\____/_/ \n"; constexpr double invGeV2_to_pb = 389379292.; constexpr long long max_warmup_events = 10000; } HEJFOG::Config load_config(char const * filename){ try{ return HEJFOG::load_config(filename); } catch(std::exception const & exc){ std::cerr << "Error: " << exc.what() << '\n'; std::exit(EXIT_FAILURE); } } std::unique_ptr<HEJ::Analysis> get_analysis( YAML::Node const & parameters ){ try{ return HEJ::get_analysis(parameters); } catch(std::exception const & exc){ std::cerr << "Failed to load analysis: " << exc.what() << '\n'; std::exit(EXIT_FAILURE); } } int main(int argn, char** argv) { using namespace std::string_literals; if (argn < 2) { std::cerr << "\n# Usage:\n." << argv[0] << " config_file\n"; return EXIT_FAILURE; } std::cout << banner; std::cout << "Version " << HEJFOG::Version::String() << ", revision " << HEJFOG::Version::revision() << std::endl; fastjet::ClusterSequence::print_banner(); using clock = std::chrono::system_clock; const auto start_time = clock::now(); // read configuration auto config = load_config(argv[1]); std::unique_ptr<HEJ::Analysis> analysis = get_analysis( config.analysis_parameters ); assert(analysis != nullptr); auto ran = HEJ::make_RNG(config.rng.name, config.rng.seed); assert(ran != nullptr); HEJ::ScaleGenerator scale_gen{ config.scales.base, config.scales.factors, config.scales.max_ratio }; HEJFOG::EventGenerator generator{ config.process, config.beam, std::move(scale_gen), config.jets, config.pdf_id, config.subleading_fraction, config.subleading_channels, config.particles_properties, config.Higgs_coupling, *ran }; LHEF::HEPRUP heprup; heprup.IDBMUP=std::pair<long,long>(config.beam.particles[0], config.beam.particles[1]); heprup.EBMUP=std::make_pair(config.beam.energy, config.beam.energy); heprup.PDFGUP=std::make_pair(0,0); heprup.PDFSUP=std::make_pair(config.pdf_id,config.pdf_id); heprup.NPRUP=1; heprup.XSECUP=std::vector<double>(1.); heprup.XERRUP=std::vector<double>(1.); heprup.LPRUP=std::vector<int>{1}; heprup.generators.emplace_back(LHEF::XMLTag{}); heprup.generators.back().name = HEJFOG::Version::package_name(); heprup.generators.back().version = HEJFOG::Version::String(); HEJ::CombinedEventWriter writer{config.output, heprup}; HEJ::optional<HEJFOG::Unweighter> unweighter{}; std::map<HEJFOG::Status, int> status_counter; std::vector<HEJ::Event> events; int trials = 0; // warm-up phase to train unweighter if(config.unweight) { std::cout << "Calibrating unweighting ...\n"; const auto warmup_start = clock::now(); const size_t warmup_events = config.unweight->sample_size; HEJ::ProgressBar<size_t> warmup_progress{std::cout, warmup_events}; for(; events.size() < warmup_events; ++trials){ auto ev = generator.gen_event(); ++status_counter[generator.status()]; assert( (generator.status() == HEJFOG::good) == bool(ev) ); if(generator.status() == HEJFOG::good && analysis->pass_cuts(*ev, *ev)) { events.emplace_back(std::move(*ev)); ++warmup_progress; } } std::cout << std::endl; unweighter = HEJFOG::Unweighter{ begin(events), end(events), config.unweight->max_dev, *ran, config.jets.peak_pt?(*config.jets.peak_pt):0. }; std::vector<HEJ::Event> unweighted_events; for(auto && ev: events) { auto unweighted = unweighter->unweight(std::move(ev)); if(unweighted) { unweighted_events.emplace_back(std::move(*unweighted)); } } events = std::move(unweighted_events); if(events.empty()) { std::cerr << "Failed to generate events. Please increase \"unweight: sample size\"" " or reduce \"unweight: max deviation\"\n"; return EXIT_FAILURE; } const auto warmup_end = clock::now(); const double completion = static_cast<double>(events.size())/config.events; const std::chrono::duration<double> remaining_time = (warmup_end- warmup_start)*(1./completion - 1); const auto finish = clock::to_time_t( std::chrono::time_point_cast<std::chrono::seconds>(warmup_end + remaining_time) ); std::cout << "Generated " << events.size() << "/" << config.events << " events (" << static_cast<int>(std::round(100*completion)) << "%)\n" << "Estimated remaining generation time: " << remaining_time.count() << " seconds (" << std::put_time(std::localtime(&finish), "%c") << ")\n\n"; } HEJ::ProgressBar<long long> progress{std::cout, config.events}; progress.increment(events.size()); events.reserve(config.events); for(; events.size() < static_cast<size_t>(config.events); ++trials){ auto ev = generator.gen_event(); ++status_counter[generator.status()]; assert( (generator.status() == HEJFOG::good) == bool(ev) ); if(generator.status() == HEJFOG::good && analysis->pass_cuts(*ev, *ev)) { if(unweighter) { auto unweighted = unweighter->unweight(std::move(*ev)); if(! unweighted) continue; ev = std::move(unweighted); } events.emplace_back(std::move(*ev)); ++progress; } } std::cout << std::endl; HEJ::CrossSectionAccumulator xs; for(auto & ev: events){ ev.parameters() *= invGeV2_to_pb/trials; analysis->fill(ev, ev); writer.write(ev); xs.fill(ev); } analysis->finalise(); const std::chrono::duration<double> run_time = (clock::now() - start_time); std::cout << "\nTask Runtime: " << run_time.count() << " seconds.\n\n"; std::cout << xs << '\n'; for(auto && entry: status_counter){ const double fraction = static_cast<double>(entry.second)/trials; const int percent = std::round(100*fraction); std::cout << "status " << std::left << std::setw(16) << (to_string(entry.first) + ":") << " ["; for(int i = 0; i < percent/2; ++i) std::cout << '#'; for(int i = percent/2; i < 50; ++i) std::cout << ' '; std::cout << "] " << percent << "%\n"; } }