Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/src/Herwig.cc b/API/HerwigAPI.cc
rename from src/Herwig.cc
rename to API/HerwigAPI.cc
--- a/src/Herwig.cc
+++ b/API/HerwigAPI.cc
@@ -1,304 +1,317 @@
// -*- C++ -*-
//
-// Herwig.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2011 The Herwig Collaboration
+// HerwigAPI.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2016 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
-#include "Herwig.h"
+#include "HerwigAPI.h"
#include "HerwigUI.h"
-#include <ThePEG/Persistency/PersistentIStream.h>
-#include <ThePEG/Repository/EventGenerator.h>
+#include "ThePEG/Persistency/PersistentIStream.h"
-#include <ThePEG/Utilities/DynamicLoader.h>
-#include <ThePEG/Utilities/Debug.h>
-#include <ThePEG/Repository/Repository.h>
-#include <ThePEG/Handlers/SamplerBase.h>
+#include "ThePEG/Utilities/DynamicLoader.h"
+#include "ThePEG/Utilities/Debug.h"
+#include "ThePEG/Repository/Repository.h"
+#include "ThePEG/Handlers/SamplerBase.h"
-#include <ThePEG/Handlers/StandardEventHandler.h>
+#include "ThePEG/Handlers/StandardEventHandler.h"
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <sys/wait.h>
#include <boost/filesystem.hpp>
-#include "Herwig/Utilities/RunDirectories.h"
+#include "RunDirectories.h"
using namespace ThePEG;
namespace {
-/**
- * Search paths for Repository read
- *
- * You can pass two string vectors with directories which Herwig will use to look in for files.
- * A vector with directories which will be prepended and a vector with directories which will be appended.
- * Both vectors are optional.
- */
-void setSearchPaths(const Herwig::HerwigUI & ui,
- bool usePWD = true);
+ /**
+ * Search paths for Repository read
+ *
+ * You can pass two string vectors with directories which Herwig will use to look in for files.
+ * A vector with directories which will be prepended and a vector with directories which will be appended.
+ * Both vectors are optional.
+ */
+ void setSearchPaths(const Herwig::HerwigUI & ui,
+ bool usePWD = true);
-void HerwigGenericRead(const Herwig::HerwigUI & ui);
-void HerwigGenericRun(const Herwig::HerwigUI & ui);
+ void HerwigGenericRead(const Herwig::HerwigUI & ui);
+ ThePEG::EGPtr HerwigGenericRun(const Herwig::HerwigUI & ui,
+ bool prepareOnly = false);
}
namespace Herwig {
-namespace API {
+ namespace API {
-void init(const HerwigUI & ui) {
- setSearchPaths(ui, false);
- SamplerBase::setRunLevel(SamplerBase::InitMode);
+ void init(const HerwigUI & ui) {
+ setSearchPaths(ui, false);
+ SamplerBase::setRunLevel(SamplerBase::InitMode);
- string infile = ui.inputfile();
+ string infile = ui.inputfile();
- // If status is INIT, we need an infile name / runname
- if (infile.empty())
- infile = "HerwigDefaults.in";
+ // If status is INIT, we need an infile name / runname
+ if (infile.empty())
+ infile = "HerwigDefaults.in";
- breakThePEG();
- {
+ breakThePEG();
+ {
# ifdef HERWIG_PKGLIBDIR
- DynamicLoader::appendPath(HERWIG_PKGLIBDIR);
+ DynamicLoader::appendPath(HERWIG_PKGLIBDIR);
# endif
# ifdef THEPEG_PKGLIBDIR
- DynamicLoader::appendPath(THEPEG_PKGLIBDIR);
+ DynamicLoader::appendPath(THEPEG_PKGLIBDIR);
# endif
- HoldFlag<> setup(InterfaceBase::NoReadOnly);
- string msg = Repository::read(infile, cout);
- if ( ! msg.empty() ) cerr << msg << '\n';
- Repository::update();
- }
- Repository::save(ui.repository());
-}
+ HoldFlag<> setup(InterfaceBase::NoReadOnly);
+ string msg = Repository::read(infile, ui.outStream());
+ if ( ! msg.empty() ) ui.errStream() << msg << '\n';
+ Repository::update();
+ }
+ Repository::save(ui.repository());
+ }
-void read(const HerwigUI & ui) {
- setSearchPaths(ui);
- SamplerBase::setRunLevel(SamplerBase::ReadMode);
- HerwigGenericRead(ui);
-}
+ void read(const HerwigUI & ui) {
+ setSearchPaths(ui);
+ SamplerBase::setRunLevel(SamplerBase::ReadMode);
+ HerwigGenericRead(ui);
+ }
-void build(const HerwigUI & ui) {
- setSearchPaths(ui);
- SamplerBase::setRunLevel(SamplerBase::BuildMode);
- HerwigGenericRead(ui);
-}
+ void build(const HerwigUI & ui) {
+ setSearchPaths(ui);
+ SamplerBase::setRunLevel(SamplerBase::BuildMode);
+ HerwigGenericRead(ui);
+ }
-void integrate(const HerwigUI & ui) {
- setSearchPaths(ui);
- SamplerBase::setRunLevel(SamplerBase::IntegrationMode);
- HerwigGenericRun(ui);
-}
+ void integrate(const HerwigUI & ui) {
+ setSearchPaths(ui);
+ SamplerBase::setRunLevel(SamplerBase::IntegrationMode);
+ HerwigGenericRun(ui);
+ }
-void mergegrids(const HerwigUI & ui) {
- setSearchPaths(ui);
- SamplerBase::setRunLevel(SamplerBase::RunMode);
- HerwigGenericRun(ui);
-}
+ void mergegrids(const HerwigUI & ui) {
+ setSearchPaths(ui);
+ SamplerBase::setRunLevel(SamplerBase::RunMode);
+ HerwigGenericRun(ui);
+ }
-void run(const HerwigUI & ui) {
- setSearchPaths(ui);
- SamplerBase::setRunLevel(SamplerBase::RunMode);
- HerwigGenericRun(ui);
-}
+ ThePEG::EGPtr prepareRun(const HerwigUI & ui) {
+ setSearchPaths(ui);
+ SamplerBase::setRunLevel(SamplerBase::RunMode);
+ return HerwigGenericRun(ui,true);
+ }
-}
-}
+ void run(const HerwigUI & ui) {
+ setSearchPaths(ui);
+ SamplerBase::setRunLevel(SamplerBase::RunMode);
+ HerwigGenericRun(ui);
+ }
-
-namespace {
-void setSearchPaths(const Herwig::HerwigUI & ui,
- bool usePWD) {
- // Search path for read command uses CWD first
- if ( usePWD ) {
- string cwd = boost::filesystem::current_path().string();
- Repository::prependReadDir( cwd );
- }
- // append command line choices for directories from which Herwig will read.
- Repository::appendReadDir(ui.appendReadDirectories());
- Repository::prependReadDir(ui.prependReadDirectories());
-}
-
-//void HerwigGenericRead(string reponame, string runname, const gengetopt_args_info & args_info)
-void HerwigGenericRead(const Herwig::HerwigUI & ui) {
- string reponame = ui.repository();
-#ifdef HERWIG_PKGDATADIR
- ifstream test(reponame.c_str());
- if ( !test ) {
- reponame = string(HERWIG_PKGDATADIR) + '/' + reponame;
- }
- test.close();
-#endif
- string msg = Repository::load(reponame);
- if ( ! msg.empty() ) cerr << msg << '\n';
-
- // Repeated invocation of setSearchPaths is necessary since Repository::load revokes all setted paths.
- setSearchPaths(ui);
-
- breakThePEG();
- if ( !ui.inputfile().empty() && ui.inputfile() != "-" ) {
- string msg = Repository::read(ui.inputfile(), std::cout);
- if ( ! msg.empty() ) cerr << msg << '\n';
- }
- else {
- Repository::exitOnError() = 0;
- Repository::read(std::cin, std::cout, "Herwig> ");
}
}
-void HerwigGenericRun(const Herwig::HerwigUI & ui) {
- // If runMode is integration or run, we need a runname
- const string runname = ui.inputfile();
- if (runname.empty() ) {
- std::cerr << "Error: You need to supply a runfile name.\n";
- ui.quitWithHelp();
+
+namespace {
+ void setSearchPaths(const Herwig::HerwigUI & ui,
+ bool usePWD) {
+ // Search path for read command uses CWD first
+ if ( usePWD ) {
+ string cwd = boost::filesystem::current_path().string();
+ Repository::prependReadDir( cwd );
+ }
+ // append command line choices for directories from which Herwig will read.
+ Repository::appendReadDir(ui.appendReadDirectories());
+ Repository::prependReadDir(ui.prependReadDirectories());
}
- if ( ui.integrationJob() && ui.jobs() > 1 ) {
- std::cerr << "parallel event generation is not applicable to integrate\n";
- ui.quit();
- }
-
- PersistentIStream is(runname);
- ThePEG::EGPtr eg;
- is >> eg;
-
- // debugging breakpoint
- breakThePEG();
-
- if ( !eg ) {
- std::cerr << "Herwig: EventGenerator not available.\n"
- << "Check if '" << runname << "' is a valid run file.\n";
- ui.quit();
- }
-
- Herwig::RunDirectories::pushRunId(eg->runName());
- if ( !ui.setupfile().empty() )
- Herwig::RunDirectories::pushRunId(ui.setupfile());
- if ( !ui.tag().empty() )
- Herwig::RunDirectories::pushRunId(ui.tag());
-
- if ( ui.seed() > 0 ) {
- ostringstream sseed;
- sseed << ui.seed();
- eg->addTag("-S" + sseed.str());
- Herwig::RunDirectories::pushRunId(sseed.str());
- }
-
- if ( !ui.integrationList().empty() )
- Herwig::RunDirectories::pushRunId(ui.integrationList());
-
- if ( ui.seed() > 0 ) eg->setSeed(ui.seed());
- if ( !ui.setupfile().empty() ) eg->addTag("-" + ui.setupfile());
- if ( !ui.tag().empty() ) eg->addTag("-" + ui.tag());
-
- if ( ui.integrationJob() || ui.runMode() == Herwig::RunMode::MERGEGRIDS ) {
- Ptr<StandardEventHandler>::tptr eh =
- dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(eg->eventHandler());
- if ( !eh ) {
- std::cerr << "Herwig: Cannot enter sampler modes for a non-standard EventHandler.\n";
- ui.quit();
+ //void HerwigGenericRead(string reponame, string runname, const gengetopt_args_info & args_info)
+ void HerwigGenericRead(const Herwig::HerwigUI & ui) {
+ string reponame = ui.repository();
+#ifdef HERWIG_PKGDATADIR
+ ifstream test(reponame.c_str());
+ if ( !test ) {
+ reponame = string(HERWIG_PKGDATADIR) + '/' + reponame;
}
- if ( ui.integrationJob() && !ui.integrationList().empty() )
- eh->sampler()->integrationList(ui.integrationList());
- if ( ui.runMode() == Herwig::RunMode::MERGEGRIDS ) {
- eh->sampler()->prepare();
- return;
+ test.close();
+#endif
+ string msg = Repository::load(reponame);
+ if ( ! msg.empty() ) ui.errStream() << msg << '\n';
+
+ // Repeated invocation of setSearchPaths is necessary since Repository::load revokes all setted paths.
+ setSearchPaths(ui);
+
+ breakThePEG();
+ if ( !ui.inputfile().empty() && ui.inputfile() != "-" ) {
+ string msg = Repository::read(ui.inputfile(), ui.outStream());
+ if ( ! msg.empty() ) ui.errStream() << msg << '\n';
+ }
+ else {
+ Repository::exitOnError() = 0;
+ Repository::read(ui.inStream(), ui.outStream(), "Herwig> ");
}
}
- if ( ! ui.setupfile().empty() ) {
- SamplerBase::setupFileUsed();
- string msg = Repository::modifyEventGenerator(*eg, ui.setupfile(), cout, true);
- if ( ! msg.empty() ) cerr << msg << '\n';
- if ( ui.integrationJob() )
- return;
- }
-
- if ( ui.integrationJob() ) {
- Repository::resetEventGenerator(*eg);
- return;
- }
-
- if (ui.jobs() <= 1) {
-
- eg->go( ui.resume() ? -1 : 1, ui.N(), ui.tics() );
- if ( ui.tics() ) std::cout << '\n';
-
- }
- else { // forked jobs
- pid_t pid = 0;
-
- const int maxlen = log10(ui.jobs()) + 1;
-
- // make sure the parent got initialized once so e.g. grid combination is
- // working
- eg->initialize(true);
-
- for (int n=0; n<ui.jobs(); n++) {
- ostringstream tmp;
- tmp << std::setfill('0') << std::setw(maxlen) << n+1;
- const string nstr = tmp.str();
-
- pid = fork();
- if (pid == -1) { // fork failed
- std::perror("Herwig: fork");
- ui.quit();
- }
- else if ( pid == 0 ) { // we're the child
- if ( ui.tics() ) std::cout << "Forked child " << n << ", PID " << getpid() << std::endl;
- eg->setSeed( ui.seed() + n );
- eg->addTag( "-" + nstr );
- Herwig::RunDirectories::pushRunId( nstr );
- eg->go( ui.resume() ? -1 : 1, ui.N() / ui.jobs(), ui.tics() );
- break; // avoid sub-forks
- }
- // nothing to do here if we're the parent
+ ThePEG::EGPtr HerwigGenericRun(const Herwig::HerwigUI & ui,
+ bool prepareOnly) {
+ // If runMode is integration or run, we need a runname
+ const string runname = ui.inputfile();
+ if (runname.empty() ) {
+ ui.errStream() << "Error: You need to supply a runfile name.\n";
+ ui.quitWithHelp();
}
- // children have nothing else to do
- if (pid == 0) return;
+ if ( ui.integrationJob() && ui.jobs() > 1 ) {
+ ui.errStream() << "parallel event generation is not applicable to integrate\n";
+ ui.quit();
+ }
- if ( ui.tics() ) std::cout << "Waiting for forked jobs." << std::endl;
- int status;
- pid_t child;
- bool cleanrun = true;
- while (true) {
+ PersistentIStream is(runname);
+ ThePEG::EGPtr eg;
+ is >> eg;
+
+ // debugging breakpoint
+ breakThePEG();
+
+ if ( !eg ) {
+ ui.errStream() << "Herwig: EventGenerator not available.\n"
+ << "Check if '" << runname << "' is a valid run file.\n";
+ ui.quit();
+ }
+
+ Herwig::RunDirectories::pushRunId(eg->runName());
+ if ( !ui.setupfile().empty() )
+ Herwig::RunDirectories::pushRunId(ui.setupfile());
+ if ( !ui.tag().empty() )
+ Herwig::RunDirectories::pushRunId(ui.tag());
+
+ if ( ui.seed() > 0 ) {
+ ostringstream sseed;
+ sseed << ui.seed();
+ eg->addTag("-S" + sseed.str());
+ Herwig::RunDirectories::pushRunId(sseed.str());
+ }
+
+ if ( !ui.integrationList().empty() )
+ Herwig::RunDirectories::pushRunId(ui.integrationList());
+
+ if ( ui.seed() > 0 ) eg->setSeed(ui.seed());
+ if ( !ui.setupfile().empty() ) eg->addTag("-" + ui.setupfile());
+ if ( !ui.tag().empty() ) eg->addTag("-" + ui.tag());
+
+ if ( ui.integrationJob() || ui.runMode() == Herwig::RunMode::MERGEGRIDS ) {
+ Ptr<StandardEventHandler>::tptr eh =
+ dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(eg->eventHandler());
+ if ( !eh ) {
+ ui.errStream() << "Herwig: Cannot enter sampler modes for a non-standard EventHandler.\n";
+ ui.quit();
+ }
+ if ( ui.integrationJob() && !ui.integrationList().empty() )
+ eh->sampler()->integrationList(ui.integrationList());
+ if ( ui.runMode() == Herwig::RunMode::MERGEGRIDS ) {
+ eh->sampler()->prepare();
+ return eg;
+ }
+ }
+
+ if ( ! ui.setupfile().empty() ) {
+ SamplerBase::setupFileUsed();
+ string msg = Repository::modifyEventGenerator(*eg, ui.setupfile(), ui.outStream(), true);
+ if ( ! msg.empty() ) ui.errStream() << msg << '\n';
+ if ( ui.integrationJob() )
+ return eg;
+ }
+
+ if ( ui.integrationJob() ) {
+ Repository::resetEventGenerator(*eg);
+ return eg;
+ }
+
+ if ( prepareOnly )
+ return eg;
+
+ if (ui.jobs() <= 1) {
+
+ eg->go( ui.resume() ? -1 : 1, ui.N(), ui.tics() );
+ if ( ui.tics() ) ui.outStream() << '\n';
+
+ }
+ else { // forked jobs
+ pid_t pid = 0;
+
+ const int maxlen = log10(ui.jobs()) + 1;
+
+ // make sure the parent got initialized once so e.g. grid combination is
+ // working
+ eg->initialize(true);
+
+ for (int n=0; n<ui.jobs(); n++) {
+ ostringstream tmp;
+ tmp << std::setfill('0') << std::setw(maxlen) << n+1;
+ const string nstr = tmp.str();
+
+ pid = fork();
+ if (pid == -1) { // fork failed
+ std::perror("Herwig: fork");
+ ui.quit();
+ }
+ else if ( pid == 0 ) { // we're the child
+ if ( ui.tics() ) ui.outStream() << "Forked child " << n << ", PID " << getpid() << std::endl;
+ eg->setSeed( ui.seed() + n );
+ eg->addTag( "-" + nstr );
+ Herwig::RunDirectories::pushRunId( nstr );
+ eg->go( ui.resume() ? -1 : 1, ui.N() / ui.jobs(), false );
+ break; // avoid sub-forks
+ }
+ // nothing to do here if we're the parent
+ }
+
+ // children have nothing else to do
+ if (pid == 0) return eg;
+
+ if ( ui.tics() ) ui.outStream() << "Waiting for forked jobs." << std::endl;
+ int status;
+ pid_t child;
+ bool cleanrun = true;
+ while (true) {
child = wait(&status);
if (child == -1) {
- if (errno == ECHILD) {
- if ( ui.tics() ) std::cout << "No more forked jobs." << std::endl;
- break;
- }
- else {
- std::perror("Herwig: waitpid");
- ui.quit();
- }
+ if (errno == ECHILD) {
+ if ( ui.tics() ) ui.outStream() << "No more forked jobs." << std::endl;
+ break;
+ }
+ else {
+ std::perror("Herwig: waitpid");
+ ui.quit();
+ }
}
if (WIFEXITED(status)) {
- if (WEXITSTATUS(status) != 0)
- cleanrun = false;
- if ( ui.tics() ) std::cout << "PID " << child
- << " exited, status=" << WEXITSTATUS(status)
- << std::endl;
+ if (WEXITSTATUS(status) != 0)
+ cleanrun = false;
+ if ( ui.tics() ) ui.outStream() << "PID " << child
+ << " exited, status=" << WEXITSTATUS(status)
+ << std::endl;
} else if (WIFSIGNALED(status)) {
- // a clean SIGTERM is handled in the child
- // and will count as exit above, so...
- cleanrun = false;
- if ( ui.tics() ) std::cout << "PID " << child
- << " killed by signal " << WTERMSIG(status)
- << std::endl;
+ // a clean SIGTERM is handled in the child
+ // and will count as exit above, so...
+ cleanrun = false;
+ if ( ui.tics() ) ui.outStream() << "PID " << child
+ << " killed by signal " << WTERMSIG(status)
+ << std::endl;
}
+ }
+ if (! cleanrun) {
+ ui.quit();
+ }
}
- if (! cleanrun) {
- ui.quit();
- }
+
+ return eg;
+
}
}
-}
diff --git a/src/Herwig.h b/API/HerwigAPI.h
rename from src/Herwig.h
rename to API/HerwigAPI.h
--- a/src/Herwig.h
+++ b/API/HerwigAPI.h
@@ -1,76 +1,77 @@
// -*- C++ -*-
//
-// Herwig.h is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2011 The Herwig Collaboration, 2015 Marco A. Harrendorf
+// HerwigAPI.h is a part of Herwig - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2016 The Herwig Collaboration, 2015 Marco A. Harrendorf
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef SRC_HERWIG_H
#define SRC_HERWIG_H
+#include "ThePEG/Repository/EventGenerator.fh"
+
namespace Herwig {
class HerwigUI;
/**
* A very high-level API for interacting with Herwig's different run modes.
*
* It's not very convenient (yet), since you'll have to provide your own
* HerwigUI-derived object with some fairly obscure settings.
*
* Much more fine-grained control is available through ThePEG::Repository.
*/
namespace API {
-/**
- * Herwig read mode. Prepares a generator .run file.
- */
-void read(const HerwigUI &);
+ /**
+ * Herwig read mode. Prepares a generator .run file. If an input file is not
+ * supplied through HerwigUI::inputfile() repository commands will be read
+ * from HerwigUI::inStream() instead.
+ */
+ void read(const HerwigUI &);
+ /**
+ * Herwig build mode. Prepares a generator .run file and integration jobs,
+ * if desired. If an input file is not supplied through
+ * HerwigUI::inputfile() repository commands will be read from
+ * HerwigUI::inStream() instead.
+ */
+ void build(const HerwigUI &);
-/**
- * Herwig build mode
- *
- *
- */
-void build(const HerwigUI &);
+ /**
+ * Herwig integrate mode
+ */
+ void integrate(const HerwigUI &);
+ /**
+ * Herwig mergegrids mode
+ */
+ void mergegrids(const HerwigUI &);
-/**
- * Herwig integrate mode
- *
- *
- */
-void integrate(const HerwigUI &);
+ /**
+ * Prepare Herwig run mode; prepare the event generator and return a pointer
+ * to it; it can then be used to generate single events.
+ */
+ ThePEG::EGPtr prepareRun(const HerwigUI &);
+ /**
+ * Herwig run mode; prepare the event generator and run a given number of
+ * events
+ */
+ void run(const HerwigUI &);
-/**
- * Herwig mergegrids mode
- *
- *
- */
-void mergegrids(const HerwigUI &);
-
-
-/**
- * Herwig run mode
- *
- *
- */
-void run(const HerwigUI &);
-
-
-/**
- * Herwig init mode. Creates a new default repository.
- *
- * Usually, the default repo created during the Herwig installation
- * is fine and external users will not need this mode.
- */
-void init(const HerwigUI &);
+ /**
+ * Herwig init mode. Creates a new default repository.
+ *
+ * Usually, the default repo created during the Herwig installation
+ * is fine and external users will not need this mode.
+ */
+ void init(const HerwigUI &);
}
}
#endif
diff --git a/src/HerwigUI.h b/API/HerwigUI.h
rename from src/HerwigUI.h
rename to API/HerwigUI.h
--- a/src/HerwigUI.h
+++ b/API/HerwigUI.h
@@ -1,82 +1,107 @@
// -*- C++ -*-
//
-// Herwig.h is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2015 The Herwig Collaboration
+// HerwigUI.h is a part of Herwig - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2016 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef SRC_HERWIG_UI_H
#define SRC_HERWIG_UI_H
#include <vector>
#include <string>
+#include <iosfwd>
namespace Herwig {
/**
* Definition of the possible run modes of Herwig
*/
namespace RunMode {
enum Mode { ERROR, INIT, READ, BUILD, INTEGRATE, MERGEGRIDS, RUN };
}
/**
* HerwigUI is an interface to abstract the command line parameters.
*
* This allows any inheriting class to configure Herwig wihtout actually
* having to interact via main()
*/
class HerwigUI {
- public:
- /// Requested Herwig run mode
- virtual RunMode::Mode runMode() const = 0;
+ public:
- /// Repository name to operate on
- virtual std::string repository() const = 0;
+ /// Requested Herwig run mode
+ virtual RunMode::Mode runMode() const = 0;
- /// Name of the file to be read
- virtual std::string inputfile() const = 0;
+ /// Repository name to operate on
+ virtual std::string repository() const = 0;
- /// Name of the setup file to be read, to modify the repository
- virtual std::string setupfile() const = 0;
+ /// Name of the file to be read
+ virtual std::string inputfile() const = 0;
- /// Try to resume execution from an earlier interrupted run.
- virtual bool resume() const = 0;
+ /// Name of the setup file to be read, to modify the repository
+ virtual std::string setupfile() const = 0;
- /// Require verbose progress markers
- virtual bool tics() const = 0;
+ /// Try to resume execution from an earlier interrupted run.
+ virtual bool resume() const = 0;
- /// A user-defined tag to append to the run name.
- virtual std::string tag() const = 0;
+ /// Require verbose progress markers
+ virtual bool tics() const = 0;
- virtual std::string integrationList() const = 0;
+ /// A user-defined tag to append to the run name.
+ virtual std::string tag() const = 0;
- /// Directories from which Herwig reads input files, will be prepended to the search path.
- virtual const std::vector<std::string> & prependReadDirectories() const = 0;
+ /// An identifier for the integration job to be handled
+ virtual std::string integrationList() const = 0;
- /// Directories from which Herwig reads input files, will be appended to the search path.
- virtual const std::vector<std::string> & appendReadDirectories() const = 0;
+ /// Directories from which Herwig reads input files, will be prepended to the search path.
+ virtual const std::vector<std::string> & prependReadDirectories() const = 0;
- virtual long N() const = 0;
- virtual int seed() const = 0;
- virtual int jobs() const = 0;
- virtual unsigned int jobSize() const = 0;
- virtual unsigned int maxJobs() const = 0;
+ /// Directories from which Herwig reads input files, will be appended to the search path.
+ virtual const std::vector<std::string> & appendReadDirectories() const = 0;
- virtual void quitWithHelp() const = 0;
+ /// The number of events to generate
+ virtual long N() const = 0;
- virtual void quit() const = 0;
+ /// The seed to use
+ virtual int seed() const = 0;
- virtual ~HerwigUI() {}
+ /// The number of jobs to fork
+ virtual int jobs() const = 0;
- bool integrationJob() const {
- return runMode() == RunMode::INTEGRATE;
- }
+ /// The number of subprocesses to integrate per integratoin job
+ virtual unsigned int jobSize() const = 0;
+
+ /// The maximum number of integration jobs
+ virtual unsigned int maxJobs() const = 0;
+
+ /// Bail out and print usage information
+ virtual void quitWithHelp() const = 0;
+
+ /// Bail out and be quiet
+ virtual void quit() const = 0;
+
+ /// Destructor
+ virtual ~HerwigUI() {}
+
+ /// Return true, if this is an integration job
+ bool integrationJob() const {
+ return runMode() == RunMode::INTEGRATE;
+ }
+
+ /// Return the standard out stream to be used
+ virtual std::ostream& outStream() const = 0;
+
+ /// Return the standard err stream to be used
+ virtual std::ostream& errStream() const = 0;
+
+ /// Return the standard in stream to be used
+ virtual std::istream& inStream() const = 0;
};
}
#endif
diff --git a/API/Makefile.am b/API/Makefile.am
new file mode 100644
--- /dev/null
+++ b/API/Makefile.am
@@ -0,0 +1,8 @@
+pkglib_LTLIBRARIES = libHerwigAPI.la
+
+
+libHerwigAPI_la_SOURCES = \
+RunDirectories.h RunDirectories.cc HerwigAPI.h HerwigAPI.cc \
+HerwigUI.h
+
+libHerwigAPI_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0
diff --git a/API/RunDirectories.cc b/API/RunDirectories.cc
new file mode 100644
--- /dev/null
+++ b/API/RunDirectories.cc
@@ -0,0 +1,114 @@
+// -*- C++ -*-
+//
+// RunDirectories.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2012 The Herwig Collaboration
+//
+// Herwig is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+
+#include "RunDirectories.h"
+
+#include "ThePEG/Utilities/Exception.h"
+#include "ThePEG/Handlers/SamplerBase.h"
+#include <boost/filesystem.hpp>
+
+using namespace ThePEG;
+using namespace Herwig;
+
+using std::string;
+using std::list;
+
+void RunDirectories::prefix(string p) {
+ if ( *p.rbegin() != '/' )
+ p += "/";
+ thePrefix() = p;
+}
+
+const string& RunDirectories::prefix() {
+ return thePrefix();
+}
+
+string& RunDirectories::thePrefix() {
+ static string p = "./Herwig-scratch/";
+ return p;
+}
+
+string& RunDirectories::theBuildStorage() {
+ static string builds = "";
+ return builds;
+}
+
+const string& RunDirectories::buildStorage() {
+ if ( !theBuildStorage().empty() )
+ return theBuildStorage();
+ theBuildStorage() = prefix();
+ if ( theBuildStorage().empty() )
+ theBuildStorage() = "./Herwig-scratch/";
+ else if ( *theBuildStorage().rbegin() != '/' )
+ theBuildStorage() += "/";
+ theBuildStorage() += "Build/";
+ if ( boost::filesystem::exists(theBuildStorage()) ) {
+ if ( !boost::filesystem::is_directory(theBuildStorage()) )
+ throw Exception() << "Herwig build storage '"
+ << theBuildStorage() << "' existing but not a directory."
+ << Exception::abortnow;
+ } else {
+ boost::filesystem::create_directories(theBuildStorage());
+ }
+ return theBuildStorage();
+}
+
+bool RunDirectories::empty() {
+ return theRunDirectories().empty();
+}
+
+list<string>& RunDirectories::theRunDirectories() {
+ static list<string> rundirs;
+ return rundirs;
+}
+
+const string& RunDirectories::runStorage() {
+ if ( theRunDirectories().empty() )
+ throw Exception() << "No run directory stack has been allocated."
+ << Exception::abortnow;
+ if ( boost::filesystem::exists(theRunDirectories().front()) ) {
+ if ( !boost::filesystem::is_directory(theRunDirectories().front()) )
+ throw Exception() << "Herwig run storage '"
+ << theRunDirectories().front() << "' existing but not a directory."
+ << Exception::abortnow;
+ } else {
+ boost::filesystem::create_directories(theRunDirectories().front());
+ }
+ return theRunDirectories().front();
+}
+
+const string& RunDirectories::interfaceStorage() {
+ if ( SamplerBase::runLevel() == SamplerBase::IntegrationMode ||
+ SamplerBase::runLevel() == SamplerBase::RunMode )
+ return runStorage();
+ return buildStorage();
+}
+
+void RunDirectories::pushRunId(string p) {
+ if ( *p.rbegin() != '/' )
+ p += "/";
+ if ( theRunDirectories().empty() ) {
+ theRunDirectories().push_front(prefix() + p);
+ return;
+ }
+ theRunDirectories().push_front(theRunDirectories().front() + p);
+}
+
+RunDirectories::RunDirectories()
+ : directoriesLeft(theRunDirectories()) {}
+
+string RunDirectories::nextRunStorage() {
+ if ( directoriesLeft.empty() )
+ throw Exception() << "No more run directories left to try."
+ << Exception::abortnow;
+ string res = directoriesLeft.front();
+ directoriesLeft.pop_front();
+ return res;
+}
+
diff --git a/API/RunDirectories.h b/API/RunDirectories.h
new file mode 100644
--- /dev/null
+++ b/API/RunDirectories.h
@@ -0,0 +1,115 @@
+// -*- C++ -*-
+//
+// RunDirectories.h is a part of Herwig - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2012 The Herwig Collaboration
+//
+// Herwig is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+#ifndef HERWIG_RunDirectories_H
+#define HERWIG_RunDirectories_H
+//
+// This is the declaration of the RunDirectories class.
+//
+
+#include <string>
+#include <list>
+
+namespace Herwig {
+
+/**
+ * \author Simon Platzer
+ *
+ * \brief Handle directories for external library and grid storage.
+ *
+ */
+class RunDirectories {
+
+public:
+
+ /**
+ * Set a prefix for storing details of this run.
+ */
+ static void prefix(std::string p);
+
+ /**
+ * Return the prefix for storing details of this run.
+ */
+ static const std::string& prefix();
+
+ /**
+ * Return the name (and possibly create) a storage for build data
+ */
+ static const std::string& buildStorage();
+
+ /**
+ * Return true, if no run directories have been pushed yet
+ */
+ static bool empty();
+
+ /**
+ * Push a run identifier onto the run directories stack.
+ */
+ static void pushRunId(std::string);
+
+ /**
+ * Return (and possibly create) the top of the run directory stack
+ * to be used for storage.
+ */
+ static const std::string& runStorage();
+
+ /**
+ * Return the storage to be used for interface order/contract files.
+ */
+ static const std::string& interfaceStorage();
+
+public:
+
+ /**
+ * Default constructor fills the directory list to test.
+ */
+ RunDirectories();
+
+ /**
+ * Return true, if there are run directories still to be considered.
+ */
+ operator bool() const { return !directoriesLeft.empty(); }
+
+ /**
+ * Return true, if there are no run directories still to be considered.
+ */
+ bool operator!() const { return directoriesLeft.empty(); }
+
+ /**
+ * Return the next run directory to be considered and pop it from
+ * the stack.
+ */
+ std::string nextRunStorage();
+
+private:
+
+ /**
+ * The prefix for storing details of this run.
+ */
+ static std::string& thePrefix();
+
+ /**
+ * The build storage.
+ */
+ static std::string& theBuildStorage();
+
+ /**
+ * The list of run storage directories to be considered.
+ */
+ static std::list<std::string>& theRunDirectories();
+
+ /**
+ * The current run directory stack under consideration
+ */
+ std::list<std::string> directoriesLeft;
+
+};
+
+}
+
+#endif /* HERWIG_RunDirectories_H */
diff --git a/Contrib/AlpGen/AlpGenHandler.cc b/Contrib/AlpGen/AlpGenHandler.cc
--- a/Contrib/AlpGen/AlpGenHandler.cc
+++ b/Contrib/AlpGen/AlpGenHandler.cc
@@ -1,1394 +1,1392 @@
#include "AlpGenHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Shower/QTilde/Base/PartnerFinder.h"
#include "Herwig/PDF/HwRemDecayer.h"
#include <queue>
#include "ThePEG/Utilities/Throw.h"
#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h"
#include "fastjet/PseudoJet.hh"
#include "fastjet/ClusterSequence.hh"
#include "gsl/gsl_rng.h"
#include "gsl/gsl_randist.h"
using namespace Herwig;
bool recordEntry(PPtr i,PPtr j) {
return (i->number()<j->number());
}
bool pTsortFunction(PPtr i,PPtr j) {
return (i->momentum().perp2()>j->momentum().perp2());
}
bool ETsortFunction(pair<Energy, Lorentz5Momentum> i,pair<Energy, Lorentz5Momentum> j) {
return (i.first>j.first);
}
bool isMomLessThanEpsilon(Lorentz5Momentum p,Energy epsilon) {
return (abs(p.x())<epsilon&&abs(p.y())<epsilon&&
abs(p.z())<epsilon&&abs(p.t())<epsilon);
}
AlpGenHandler::AlpGenHandler()
: ncy_(100),ncphi_(60),ihvy_(-999),nph_(-999),nh_(-999),
etclusmean_(20*GeV),rclus_(0.4),etaclmax_(5.0),rclusfactor_(1.5),
ihrd_(-999),njets_(-999),drjmin_(-999), highestMultiplicity_(false),
ycmax_(5.4),ycmin_(-5.4),jetAlgorithm_(2),vetoIsTurnedOff_(false),
inputIsNLO_(false),highestNLOMultiplicity_(false),etclusfixed_(true),epsetclus_(2.5*GeV)
{}
void AlpGenHandler::doinitrun() {
ShowerHandler::doinitrun();
// et_ holds the ET deposited in the (ncy_ x ncphi_) calorimeter cells.
et_.resize(ncy_);
for(unsigned int ixx=0; ixx<et_.size(); ixx++) et_[ixx].resize(ncphi_);
// jetIdx_ for a given calorimeter cell this holds the index of the jet
// that the cell was clustered into.
jetIdx_.resize(ncy_);
for(unsigned int ixx=0; ixx<jetIdx_.size(); ixx++) jetIdx_[ixx].resize(ncphi_);
}
IBPtr AlpGenHandler::clone() const {
return new_ptr(*this);
}
IBPtr AlpGenHandler::fullclone() const {
return new_ptr(*this);
}
void AlpGenHandler::persistentOutput(PersistentOStream & os) const {
os << alphaS_
<< ncy_ << ncphi_ << ihvy_ << nph_ << nh_
<< ounit(etclusmean_,GeV) << rclus_ << etaclmax_ << rclusfactor_
<< ihrd_ << njets_ << drjmin_ << highestMultiplicity_
<< ycmax_ << ycmin_ << jetAlgorithm_ << vetoIsTurnedOff_
<< inputIsNLO_ << highestNLOMultiplicity_ << etclusfixed_
<< cphcal_ << sphcal_ << cthcal_ << sthcal_ << ounit(epsetclus_,GeV);
}
void AlpGenHandler::persistentInput(PersistentIStream & is, int) {
is >> alphaS_
>> ncy_ >> ncphi_ >> ihvy_ >> nph_ >> nh_
>> iunit(etclusmean_,GeV) >> rclus_ >> etaclmax_ >> rclusfactor_
>> ihrd_ >> njets_ >> drjmin_ >> highestMultiplicity_
>> ycmax_ >> ycmin_ >> jetAlgorithm_ >> vetoIsTurnedOff_
>> inputIsNLO_ >> highestNLOMultiplicity_ >> etclusfixed_
>> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV);
}
ClassDescription<AlpGenHandler> AlpGenHandler::initAlpGenHandler;
// Definition of the static class description member.
void AlpGenHandler::Init() {
static ClassDocumentation<AlpGenHandler> documentation
("The AlpGenHandler class performs MEPS merging "
"using the MLM procedure.");
static Reference<AlpGenHandler,ShowerAlpha> interfaceShowerAlpha
("ShowerAlpha",
"The object calculating the strong coupling constant",
&AlpGenHandler::alphaS_, false, false, true, false, false);
static Parameter<AlpGenHandler,unsigned int> interfaceNoCellsInRapidity
("NoCellsInRapidity",
"The number of cells spanning the rapidity interval of "
"the calorimeter",
&AlpGenHandler::ncy_, 100, 1, 10000,
false, false, Interface::limited);
static Parameter<AlpGenHandler,unsigned int> interfaceNoCellsInPhi
("NoCellsInPhi",
"The number of cells spanning the phi interval of "
"the calorimeter",
&AlpGenHandler::ncphi_, 60, 1, 10000,
false, false, Interface::limited);
static Parameter<AlpGenHandler,int> interfaceihvy
("ihvy",
"heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t)",
&AlpGenHandler::ihvy_, -999, -999, 7,
false, false, Interface::limited);
static Parameter<AlpGenHandler,int> interfacenph
("nph",
"Number of photons in the AlpGen process",
&AlpGenHandler::nph_, -999, -999, 7,
false, false, Interface::limited);
static Parameter<AlpGenHandler,int> interfacenh
("nh",
"Number of higgses in the AlpGen process",
&AlpGenHandler::nph_, -999, -999, 7,
false, false, Interface::limited);
static Parameter<AlpGenHandler,Energy> interfaceETClus
("ETClus",
"The ET threshold defining a jet in the merging procedure",
&AlpGenHandler::etclusmean_, GeV, 20*GeV, 0*GeV, 14000*GeV,
false, false, Interface::limited);
static Parameter<AlpGenHandler,double> interfaceRClus
("RClus",
"The cone size used to define a jet in the merging procedure",
&AlpGenHandler::rclus_, 0.4, 0.0, 4.0,
false, false, Interface::limited);
static Parameter<AlpGenHandler,double> interfaceEtaClusMax
("EtaClusMax",
"The maximum |eta| used to define a jet in the merging procedure",
&AlpGenHandler::etaclmax_, 5.0, 0.0, 15.0,
false, false, Interface::limited);
static Parameter<AlpGenHandler,double> interfaceRClusFactor
("RClusFactor",
"The prefactor for RClus used to define the jet-parton matching "
"distance",
&AlpGenHandler::rclusfactor_, 1.5, 0.0, 4.0,
false, false, Interface::limited);
static Parameter<AlpGenHandler,int> interfaceihrd
("ihrd",
"The AlpGen hard process code",
&AlpGenHandler::ihrd_, -999, 0, 10000,
false, false, Interface::limited);
static Parameter<AlpGenHandler,int> interfacenjets
("njets",
"The number of light jets in the AlpGen process (i.e. the "
"extra ones)",
&AlpGenHandler::njets_, -999, 0, 10000,
false, false, Interface::limited);
static Parameter<AlpGenHandler,double> interfacedrjmin
("drjmin",
"Mimimum parton-parton R-sep used for generation.",
&AlpGenHandler::drjmin_, 0.7, 0.0, 4.0,
false, false, Interface::limited);
static Parameter<AlpGenHandler,bool> interfacehighestMultiplicity
("highestMultiplicity",
"If true it indicates that this is the highest multiplicity input "
"ME-level configuration to be processed.",
&AlpGenHandler::highestMultiplicity_, 0, 0, 1,
false, false, Interface::limited);
static Parameter<AlpGenHandler,bool> interfacehighestNLOMultiplicity
("highestNLOMultiplicity",
"If true it indicates that this is the highest NLO multiplicity input "
"ME-level configuration to be processed.",
&AlpGenHandler::highestNLOMultiplicity_, 0, 0, 1,
false, false, Interface::limited);
static Parameter<AlpGenHandler,bool> interfaceETClusFixed
("ETClusFixed",
"If false, indicates that the jet merging scale, etclus_ is allowed to vary"
"according to epsetclus_",
&AlpGenHandler::etclusfixed_, 1, 0, 1,
false, false, Interface::limited);
static Parameter<AlpGenHandler,Energy> interfaceEpsilonETClus
("EpsilonETClus",
"The ET threshold defining a jet in the merging procedure",
&AlpGenHandler::epsetclus_, GeV, 2.5*GeV, 0*GeV, 100.0*GeV,
false, false, Interface::limited);
static Switch<AlpGenHandler,int> interfaceJetAlgorithm
("JetAlgorithm",
"Determines the jet algorithm for finding jets in parton-jet "
"matching in the MLM procedure.",
&AlpGenHandler::jetAlgorithm_, 2, false, false);
static SwitchOption AntiKt
(interfaceJetAlgorithm,
"AntiKt",
"The anti-kt jet algorithm.",
-1);
static SwitchOption CambridgeAachen
(interfaceJetAlgorithm,
"CambridgeAachen",
"The Cambridge-Aachen jet algorithm.",
0);
static SwitchOption Kt
(interfaceJetAlgorithm,
"Kt",
"The Kt jet algorithm.",
1);
static SwitchOption GetJet
(interfaceJetAlgorithm,
"GetJet",
"Calorimeter-based GetJet algorithm (default).",
2);
static Switch<AlpGenHandler,bool> interfaceVetoIsTurnedOff
("VetoIsTurnedOff",
"Allows the vetoing mechanism to be switched off.",
&AlpGenHandler::vetoIsTurnedOff_, false, false, false);
static SwitchOption VetoingIsOn
(interfaceVetoIsTurnedOff,
"VetoingIsOn",
"The MLM merging veto mechanism is switched ON.",
false);
static SwitchOption VetoingIsOff
(interfaceVetoIsTurnedOff,
"VetoingIsOff",
"The MLM merging veto mechanism is switched OFF.",
true);
static Switch<AlpGenHandler,bool> interfaceInputIsNLO
("InputIsNLO",
"Signals whether the input LH file is tree-level accurate "
"or contains NLO (Powheg) events.",
&AlpGenHandler::inputIsNLO_, false, false, false);
static SwitchOption InputIsNotNLO
(interfaceInputIsNLO,
"InputIsNotNLO",
"The input LH events have tree-level accuracy.",
false);
static SwitchOption InputIsNLO
(interfaceInputIsNLO,
"InputIsNLO",
"The input LH events have NLO accuracy.",
true);
}
void AlpGenHandler::dofinish() {
ShowerHandler::dofinish();
}
void AlpGenHandler::doinit() {
//print error if HardProcID is not set in input file
if(ihrd_ == -999) { cout << "Error: AlpGenHandler:ihrd not set!" << endl; exit(1); }
ShowerHandler::doinit();
// Compute calorimeter edges in rapidity for GetJet algorithm.
ycmax_=etaclmax_+rclus_;
ycmin_=-ycmax_;
// Initialise calorimeter.
calini_m();
}
// Throws a veto according to MLM strategy ... when we finish writing it.
bool AlpGenHandler::showerHardProcessVeto() {
-
if(vetoIsTurnedOff_) return false;
-
// Skip veto for processes in which merging is not implemented:
if(ihrd_==7||ihrd_==8||ihrd_==13) {
ostringstream wstring;
wstring << "AlpGenHandler::showerHardProcessVeto() - warning."
<< "MLM merging not implemented for AlpGen "
<< "processes 4Q (ihrd=7), QQh (ihrd=8), "
<< "(single) top (ihrd=13) \n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
return false;
}
// Fill preshowerISPs_ pair and preshowerFSPs_ particle pointer vector.
getPreshowerParticles();
// Fill showeredISHs_, showeredISPs and showeredRems pairs, as well as
// showeredFSPs_ particle pointer vector.
getShoweredParticles();
// Turn on some screen output debugging: 0 = none ---> 5 = very verbose.
doSanityChecks(0);
// Dimensions of each calorimter cell in y and phi.
dely_ = (ycmax_-ycmin_)/double(ncy_);
delphi_ = 2*M_PI/double(ncphi_);
// Fill partonsToMatch_ with only those pre-shower partons intended to
// used in jet-parton matching and fill particlesToCluster_ using only
// those final state particles (post-shower) which are supposed to go
// in the jet clustering used to do merging.
partonsToMatch_ = preshowerFSPs_;
particlesToCluster_ = showeredFSPs_ ; // <--- TO DO: add remnants in here ???
// Filter out all but the 'extra' light-parton progenitors and their
// associated final state particles.
caldel_m();
double prob(1);
//if etclusfixed_ then set the etclus_ to the fixed chosen value
if(etclusfixed_) {
etclus_ = etclusmean_;
} else {
//else, if we wish to vary etclus_, we use the probability distribution
//choose a probability between 0 and 1
prob = rnd();
etclus_ = etclusran_(prob);
}
if(jetAlgorithm_==2) {
// If using GetJet fill the calorimeter cells now from particlesToCluster_
calsim_m();
// Make jets from the calorimeter blobs.
getjet_m(rclus_,etclus_,etaclmax_);
} else {
// Cluster particlesToCluster_ into jets with FastJet.
getFastJets(rclus_,etclus_,etaclmax_);
}
// If there are less jets than partons then parton-jet matching is
// bound to fail: reject the event already. Also, if the input is
// an NLO event file it will 99.5% of the time contain a number of
// light partons in the F.S. equal to that in the real emission
// process in the NLO calculation, moreover, it has already
// effectively merged njets_-1 and njets jet events. So in that
// case we do not reject events on the grounds they have jet
// multiplicity less than partonsToMatch_.size() but rather less
// jets than partonsToMatch.size()-1; such events are better
// described by the lower-by-one-unit (partonsToMatch_.size()-1)
// of multiplicity NLO event file, or the lower-by-two-units
// (partonsToMatch_.size()-2) of multiplicity LO event file.
// If it is not jet production apply rejection criterion as above.
if(ihrd_!=9) {
if(!inputIsNLO_) {
if(pjet_.size() < partonsToMatch_.size()) return true;
} else {
if(pjet_.size() < partonsToMatch_.size()-1) return true;
}
// Otherwise, in the case of jet production allow the lowest
// contributing multiplicity process (just at NLO), namely,
// dijet production, to give rise to 1-jet and even 0-jet
// events, since these can contribute to, for example, the
// inclusive jet cross section i.e. in this case the rejection
// is only applied in the case of the next-to-lowest multiplicity
// processes (>2 parton events at LO and >3 parton events at NLO).
} else {
if(!inputIsNLO_) {
// KH - March 5th
// Removed the following line giving special treatment
// also to the LO events, to maintain consistency with
// the fortran algorithm, at least for now. So now jet
// production at LO is being treated the same as all
// other processes.
// if(partonsToMatch_.size()==2 && pjet_.size()<2) return false;
if(pjet_.size() < partonsToMatch_.size()) return true;
} else {
if(partonsToMatch_.size()<=3 && pjet_.size()<2) return false;
if(pjet_.size() < partonsToMatch_.size()-1) return true;
}
}
// Sort partonsToMatch_ from high to low pT.
sort(partonsToMatch_.begin(),partonsToMatch_.end(),pTsortFunction);
// Match light progenitors to jets.
vector<int> jetToPartonMap(pjet_.size(),-999);
Energy etmin(777e100*GeV);
// If the input is NLO events then don't do any jet-parton matching!
if(!inputIsNLO_) {
// For each parton, starting with the hardest one ...
for(unsigned int ixx=0; ixx<partonsToMatch_.size(); ixx++) {
// ... loop over all jets not already matched.
double DRmin(777e100);
int jetIndexForDRmin(-999);
for(unsigned int jxx=0; jxx<pjet_.size(); jxx++) {
// ... and tag closest of the remaining ones
double DRpartonJet(partonJetDeltaR(partonsToMatch_[ixx],pjet_[jxx]));
if(jetToPartonMap[jxx]<0&&DRpartonJet<DRmin) {
DRmin=DRpartonJet;
jetIndexForDRmin=jxx;
}
}
// If the parton-jet distance is less than the matching
// distance, the parton and jet match.
if(DRmin<rclus_*rclusfactor_&&jetIndexForDRmin>=0) {
jetToPartonMap[jetIndexForDRmin]=ixx;
if(ixx==0||etjet_[jetIndexForDRmin]<etmin)
etmin=etjet_[jetIndexForDRmin];
// Otherwise this parton is not matched so veto the event.
} else return true;
}
}
// Veto events with larger jet multiplicity from exclusive sample.
if(!highestMultiplicity_&&pjet_.size()>partonsToMatch_.size()
&& !inputIsNLO_) return true;
if(inputIsNLO_) {
if(!highestNLOMultiplicity_) {
if(pjet_.size()>partonsToMatch_.size()-1) return true;
} else {
if(!highestMultiplicity_&&pjet_.size()>partonsToMatch_.size())
return true;
}
}
// Veto events where matched jets are softer than non-matched ones,
// in the inclusive (highestMultiplicity_ = true) mode, unless we
// are dealing with NLO input events.
if(highestMultiplicity_ && !inputIsNLO_ ) {
for(unsigned int ixx=0; ixx<pjet_.size(); ixx++)
if(jetToPartonMap[ixx]<0&&etmin<etjet_[ixx]) return true;
}
-
+
// **************************************************************** //
// * Now look to the non-light partons for heavy quark processes. * //
// **************************************************************** //
if(ihrd_<=2||ihrd_==6||ihrd_==10||ihrd_==15||ihrd_==16) {
// Extract heavy quark progenitors and the radiation they
// produce and put it in the calorimeter.
caldel_hvq();
if(jetAlgorithm_==2) {
// If using GetJet fill the calorimeter cells now from particlesToCluster_
calsim_m();
// Make jets from the calorimeter blobs.
getjet_m(rclus_,etclus_,etaclmax_);
} else {
// Cluster particlesToCluster_ into jets with FastJet.
getFastJets(rclus_,etclus_,etaclmax_);
}
// If the radiation from the heavy quarks does not give rise
// to any jets we accept event.
if(pjet_.size() == 0) return false;
// If extra jets emerge from the jet clustering we only
// accept events where the jets formed by radiation from
// b and c quarks lies within drjmin_ of the heavy quark
// progenitor.
int nmjet(pjet_.size());
for(unsigned int ixx=0; ixx<pjet_.size(); ixx++) {
for(unsigned int jxx=0; jxx<partonsToMatch_.size(); jxx++) {
if(!(abs(partonsToMatch_[jxx]->id())==4||abs(partonsToMatch_[jxx]->id())==5)) continue;
if(partonJetDeltaR(partonsToMatch_[jxx],pjet_[ixx])<drjmin_) {
nmjet--; // Decrease the number of unmatched jets.
etjet_[ixx]=0*GeV; // Set jet ET to zero to indicate it is 'matched'.
}
}
}
// If every jet matched to _at_least_one_ progenitor accept the event.
if(nmjet<=0) return false;
else {
// If unmatched jets remain, reject the event if highestMultiplicity_!=1
if(!highestMultiplicity_) return true;
else {
// If unmatched jets remain and highestMultiplicity is true then check
// that these are softer than all the matched ones (from the light-parton
// matching round).
Energy etmax(0.*GeV);
for(unsigned int ixx=0; ixx<pjet_.size(); ixx++) etmax=max(etjet_[ixx],etmax);
if(etmax>etmin) return true;
}
}
}
// Otherwise we accept the event ...
return false;
}
/* Function that returns the R distance
between a particle and a jet. */
double AlpGenHandler::partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom) {
LorentzMomentum partonmom(partonptr->momentum());
// Calculate DY, DPhi and then DR
double DY(partonmom.eta()-jetmom.eta());
double DPhi(partonmom.phi()-jetmom.phi());
if(DPhi>M_PI) DPhi=2*M_PI-DPhi;
double DR(sqrt(sqr(DY)+sqr(DPhi)));
return DR;
}
// Initialize calorimeter for calsim_m and getjet_m. Note that
// because initialization is separte calsim_m can be called more
// than once to simulate pileup of several events.
void AlpGenHandler::calini_m() {
// Making sure arrays are clear before filling;
cphcal_.clear(); sphcal_.clear();
cthcal_.clear(); sthcal_.clear();
// Fill array holding phi values of calorimeter cell centres.
double deltaPhi(2*M_PI/ncphi_);
for(unsigned int iphi=1; iphi<=ncphi_; iphi++) {
double phi(deltaPhi*(iphi-0.5)); // Goes phi~=0 to phi~=2*pi (iphi=0--->ncphi).
cphcal_.push_back(cos(phi)); // ==> goes from +1 ---> +1 (iphi=0--->ncphi).
sphcal_.push_back(sin(phi)); // ==> goes 0 -> 1 -> 0 -> -1 -> 0 (iphi=0--->ncphi).
}
// Fill array holding theta values of calorimeter cell centres in Y.
double deltaY((ycmax_-ycmin_)/double(ncy_));
for(unsigned int iy=1; iy<=ncy_; iy++) {
double Y(deltaY*(iy-0.5)+ycmin_);
double th(2*atan(exp(-Y))); // Goes bwds th~=pi to fwds th~=0 (iy=0--->ncy).
cthcal_.push_back(cos(th)); // ==> goes from -1 ---> +1 (iy=0--->ncy).
sthcal_.push_back(sin(th)); // ==> goes from 0 ---> +1 ---> 0 (iy=0--->ncy).
}
return;
}
// Get FastJets
void AlpGenHandler::getFastJets(double rjet, Energy ejcut, double etajcut) {
vector<fastjet::PseudoJet> particlesToCluster;
for(unsigned int ipar=0; ipar<particlesToCluster_.size(); ipar++) {
double y(particlesToCluster_[ipar]->momentum().eta());
if(y>=ycmin_&&y<=ycmax_) {
int absId(abs(particlesToCluster_[ipar]->id()));
// If it's not a lepton / top / photon it may go in the jet finder.
if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) {
// input particles into fastjet pseudojet
fastjet::PseudoJet p(particlesToCluster_[ipar]->momentum().x()/GeV,
particlesToCluster_[ipar]->momentum().y()/GeV,
particlesToCluster_[ipar]->momentum().z()/GeV,
particlesToCluster_[ipar]->momentum().e()/GeV);
p.set_user_index(ipar);
particlesToCluster.push_back(p);
}
}
}
fastjet::RecombinationScheme recombinationScheme = fastjet::E_scheme;
fastjet::Strategy strategy = fastjet::Best;
double R(rjet);
fastjet::JetDefinition theJetDefinition;
switch (jetAlgorithm_) {
case -1: theJetDefinition=fastjet::JetDefinition(fastjet::antikt_algorithm,
R,
recombinationScheme,
strategy); break;
case 0: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm,
R,
recombinationScheme,
strategy); break;
case 1: theJetDefinition=fastjet::JetDefinition(fastjet::kt_algorithm,
R,
recombinationScheme,
strategy); break;
default: theJetDefinition=fastjet::JetDefinition(fastjet::cambridge_algorithm,
R,
recombinationScheme,
strategy); break;
}
fastjet::ClusterSequence fastjetEvent(particlesToCluster,theJetDefinition);
vector<fastjet::PseudoJet> inclusiveJets = fastjetEvent.inclusive_jets();
inclusiveJets = fastjet::sorted_by_pt(inclusiveJets);
// Fill the array of jet momenta for the rest of the veto procedure.
pjet_.clear();
pjet_.resize(inclusiveJets.size());
etjet_.clear();
etjet_.resize(inclusiveJets.size());
for(unsigned int ffj=0; ffj<pjet_.size();ffj++) {
pjet_[ffj] = Lorentz5Momentum(inclusiveJets[ffj].px()*GeV,
inclusiveJets[ffj].py()*GeV,
inclusiveJets[ffj].pz()*GeV,
inclusiveJets[ffj].e()*GeV);
pjet_[ffj].rescaleMass();
etjet_[ffj] = pjet_[ffj].et();
}
// Throw the jet away if it's outside required eta region or
// has transverse energy below ejcut.
for(unsigned int fj=0; fj<pjet_.size(); fj++)
if(etjet_[fj]<ejcut||fabs(pjet_[fj].eta())>etajcut) {
pjet_.erase(pjet_.begin()+fj);
etjet_.erase(etjet_.begin()+fj);
fj--;
}
// Sort jets from high to low ET.
vector<pair<Energy, Lorentz5Momentum> > etjet_pjet;
for(unsigned int ixx=0; ixx<etjet_.size(); ixx++)
etjet_pjet.push_back(make_pair(etjet_[ixx],pjet_[ixx]));
sort(etjet_pjet.begin(),etjet_pjet.end(),ETsortFunction);
for(unsigned int ixx=0; ixx<etjet_.size(); ixx++) {
etjet_[ixx]=etjet_pjet[ixx].first;
pjet_[ixx]=etjet_pjet[ixx].second;
}
return;
}
// Simple calorimeter simulation - assume uniform Y and phi bins.
void AlpGenHandler::calsim_m() {
// Reset transverse energies of all calorimter cells ready for new fill.
for(unsigned int ixx=0; ixx<et_.size(); ixx++)
for(unsigned int iyy=0; iyy<et_[ixx].size(); iyy++)
et_[ixx][iyy]=0*GeV;
// Assign ET to each calorimeter cell (mostly 0's).
for(unsigned int ipar=0; ipar<particlesToCluster_.size(); ipar++) {
double y(particlesToCluster_[ipar]->momentum().eta());
if(y>=ycmin_&&y<=ycmax_) {
int absId(abs(particlesToCluster_[ipar]->id()));
// If it's not a lepton / top / photon it goes in the calorimeter.
if(!(absId>=11&&absId<=16) && absId!=6 && absId!=22) {
double phi(atan2(particlesToCluster_[ipar]->momentum().y()/GeV,
particlesToCluster_[ipar]->momentum().x()/GeV));
if(phi<0) phi+=2*M_PI;
unsigned int iy(int((y-ycmin_)/dely_));
unsigned int iphi(int(phi/delphi_));
et_[iy][iphi]+=particlesToCluster_[ipar]->momentum().e()*sthcal_[iy];
}
}
}
return;
}
// Find highest remaining cell > etstop and sum surrounding cells
// with -- delta(y)^2+delta(phi)^2 < Rjet^2 , ET>eccut. Keep sets
// with ET>ejcut and abs(eta)<etacut.
void AlpGenHandler::getjet_m(double rjet, Energy ejcut, double etajcut) {
// Minimum ET the calorimeter can "see".
Energy eccut(0.1*GeV);
// So long as the cell remaining with the highest ET has
// ET < etstop we try to cluster the surrounding cells into
// it to potentially form a jet.
Energy etstop(1.5*GeV);
// Reset the vector holding the jet-index each calo cell
// was clustered into.
for(unsigned int iy=0; iy<ncy_; iy++)
for(unsigned int iphi=0; iphi<ncphi_; iphi++)
jetIdx_[iy][iphi]=-777;
// Reset the vector that will hold the jet momenta.
pjet_.clear();
// # cells spanned by cone radius in phi dir., _rounded_down_.
unsigned int nphi1(rjet/delphi_);
// # cells spanned by cone radius in eta dir., _rounded_down_.
unsigned int ny1(rjet/dely_);
// Vector to hold the "ET" of each jet, where here ET really means
// the scalar sum of ETs in each calo cell clustered into the jet.
// Note that this is _not_ the same as the ET you would compute from
// the final momentum worked out for each jet.
etjet_.clear();
// The ET of the highest ET cell found.
Energy etmax(777e100*GeV);
// Counter for number of highest ET calo cells found.
unsigned int ipass(0);
// Start finding jets.
while(etmax>=etstop) {
// Find the cell with the highest ET from
// those not already assigned to a jet.
etmax=0*GeV;
int iymx(0), iphimx(0);
for(unsigned int iphi=0; iphi<ncphi_; iphi++)
for(unsigned int iy=0; iy<ncy_; iy++)
if(et_[iy][iphi]>etmax&&jetIdx_[iy][iphi]<0) {
etmax = et_[iy][iphi];
iymx = iy;
iphimx = iphi;
}
// If the remaining cell with the highest ET has ET < etstop, stop.
if(etmax<etstop) break;
// You cannot have more cells with the highest ET
// so far than you have cells in the calorimeter.
ipass++;
if(ipass>(ncy_*ncphi_)) {
cout << "AlpGenHandler::getjet_m() - Fatal error." << endl;
cout << "We found " << ipass << " calo cells with the highest ET so"
<< "far\nbut the calorimeter only has " << ncy_*ncphi_ << " "
<< "cells in it!" << endl;
exit(10);
}
// Add a jet vector (may get deleted if jet fails ET / eta cuts).
etjet_.push_back(0*GeV);
pjet_.push_back(Lorentz5Momentum(0.*GeV,0.*GeV,0.*GeV,0.*GeV,0.*GeV));
// Loop over all calo cells in range iphimx +/- nphi1 (inclusive)
// wrapping round in azimuth if required.
for(unsigned int iphi1=0; iphi1<=2*nphi1; iphi1++) {
int iphix(iphimx-nphi1+iphi1);
if(iphix<0) iphix += ncphi_;
if(iphix>=int(ncphi_)) iphix -= ncphi_;
// Loop over all calo cells in range iymx +/- ny1 (inclusive).
for(unsigned int iy1=0; iy1<=2*ny1; iy1++) {
int iyx(iymx-ny1+iy1);
// If the cell is outside the calorimeter OR if it was already
// associated to a jet then skip to the next loop.
if(iyx>=0&&iyx<int(ncy_)&&jetIdx_[iyx][iphix]<0) {
// N.B. iyx-iymx = iy1-ny1 and iphix-iphimx = iphi1-nphi1
// hence the following is the distance in R between the
// centre of the cell we are looking at and the one
// with the highest ET.
double r2(sqr( dely_*(double(iy1) -double(ny1) ))
+sqr(delphi_*(double(iphi1)-double(nphi1))));
if(r2<sqr(rjet)&&et_[iyx][iphix]>=eccut) {
Energy ECell(et_[iyx][iphix]/sthcal_[iyx]);
pjet_.back()+=LorentzMomentum(ECell*sthcal_[iyx]*cphcal_[iphix], // px
ECell*sthcal_[iyx]*sphcal_[iphix], // py
ECell*cthcal_[iyx],ECell); // pz, E.
// N.B. This is the same reln as in ThePEG between phi and x,y.
etjet_.back()+=et_[iyx][iphix];
jetIdx_[iyx][iphix] = pjet_.size()-1; // Identify cell with this jet.
}
}
}
}
// Compute the current jet's mass.
pjet_.back().rescaleMass();
// Throw the jet away if it's ET is less than ejcut.
if(etjet_.back()<ejcut||fabs(pjet_.back().eta())>etajcut) {
pjet_.pop_back();
etjet_.pop_back();
}
}
// Sort jets from high to low ET.
vector<pair<Energy, Lorentz5Momentum> > etjet_pjet;
for(unsigned int ixx=0; ixx<etjet_.size(); ixx++)
etjet_pjet.push_back(make_pair(etjet_[ixx],pjet_[ixx]));
sort(etjet_pjet.begin(),etjet_pjet.end(),ETsortFunction);
for(unsigned int ixx=0; ixx<etjet_.size(); ixx++) {
etjet_[ixx]=etjet_pjet[ixx].first;
pjet_[ixx]=etjet_pjet[ixx].second;
}
return;
}
// Deletes particles from partonsToMatch_ and particlesToCluster_
// vectors so that these contain only the partons to match to the
// jets and the particles used to build jets respectively. By and
// large the candidates for deletion are: vector bosons and their
// decay products, Higgs bosons, photons as well as _primary_, i.e.
// present in the lowest multiplicity process, heavy quarks and
// any related decay products.
void AlpGenHandler::getDescendents(PPtr theParticle) {
ParticleVector theChildren(theParticle->children());
for (unsigned int ixx=0; ixx<theChildren.size(); ixx++)
if(theChildren[ixx]->children().size()==0)
tmpList_.push_back(theChildren[ixx]);
else
getDescendents(theChildren[ixx]);
return;
}
void AlpGenHandler::caldel_m() {
preshowerFSPsToDelete_.clear();
showeredFSPsToDelete_.clear();
for(unsigned int ixx=0; ixx<preshowerFSPs_.size(); ixx++) {
tmpList_.clear();
if(ihrd_<=2) {
/* wqq... , zqq... */
/* Exclude the heavy quarks and any children they may
have produced as well as the v.boson and any children
it may have produced from the jet parton matching. */
if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==23||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
if(abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=4) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "wqq / zqq process should have 4 particles to omit from"
<< "jet-parton matching for ihvy=" << ihvy_ << "." << Exception::eventerror;
}
} else if(ihrd_<=4) {
/* zjet... */
/* Exclude the v.boson and any children
it may have produced from the jet parton matching. */
if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==23||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=2) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "zjet process should have 2 particles to omit from"
<< "jet-parton matching." << Exception::eventerror;
}
} else if(ihrd_==5) {
/* vbjet... */
/* Exclude the v.bosons and any children they may
have produced from the jet parton matching. */
if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==23||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==24||
abs(preshowerFSPs_[ixx]->id())==22||
abs(preshowerFSPs_[ixx]->id())==25) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
} else if(ihrd_==6) {
/* 2Q... */
/* Exclude the heavy quarks and any children
they may have produced from the jet parton matching. */
if(ihvy_==6) {
if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==6||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
}
if(abs(preshowerFSPs_[ixx]->parents()[0]->id())==6) {
getDescendents(preshowerFSPs_[ixx]->parents()[0]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=6) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "2Q process should have 6 particles to omit from"
<< "jet-parton matching for ihvy=" << ihvy_ << "." << Exception::eventerror;
}
} else {
if(abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=2) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "2Q process should have 2 particles to omit from"
<< "jet-parton matching for ihvy=" << ihvy_ << "." << Exception::eventerror;
}
}
} else if(ihrd_==7) {
/* 4Q... */
/* There are no light jets for this process, so nothing to match. */
} else if(ihrd_==9) {
/* Njet... */
} else if(ihrd_==10) {
/* wcjet... */
/* Exclude the charm quark and any children it may
have produced as well as the v.boson and any children
it may have produced from the jet parton matching. */
if((abs(preshowerFSPs_[ixx]->id())==4&&ixx<1)||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=3) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "wcjet process should have 3 particles to omit from"
<< "jet-parton matching." << Exception::eventerror;
}
} else if(ihrd_==11) {
/* phjet... */
/* Exclude the hard photons from the jet parton matching. */
if(abs(preshowerFSPs_[ixx]->id())==22) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
unsigned int tmpUnsignedInt(nph_);
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=tmpUnsignedInt) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "phjet process should have " << nph_ << " particles to omit from"
<< "jet-parton matching." << Exception::eventerror;
}
} else if(ihrd_==12) {
/* hjet... */
/* Exclude the higgs and any children it may have
produced from the jet parton matching. */
if(abs(preshowerFSPs_[ixx]->id())==25) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=1) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "hjet process should have 1 particle to omit from"
<< "jet-parton matching." << Exception::eventerror;
}
} else if(ihrd_==14) {
/* wphjet... */
/* Exclude the v.boson and any children it may have
produced from the jet parton matching. */
// AND WHAT ABOUT THE PHOTON? <--- CHECK THIS WITH AlpGen GUYs.
if(abs(preshowerFSPs_[ixx]->id())==22||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
unsigned int tmpUnsignedInt(2+nph_);
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=tmpUnsignedInt) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "wphjet process should have " << 2+nph_ << " particles to omit from"
<< "jet-parton matching." << Exception::eventerror;
}
} else if(ihrd_==15) {
/* wphqq... <--- N.B. if q = top, it is not decayed. */
/* Exclude the heavy quarks and any children they may
have produced as well as the v.boson and any children
it may have produced from the jet parton matching. */
// AND WHAT ABOUT THE PHOTON? <--- CHECK THIS WITH AlpGen GUYs.
if(abs(preshowerFSPs_[ixx]->id())==22||
(abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+1)))||
(abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx==(preshowerFSPs_.size()-(2+nph_+2)))||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
unsigned int tmpUnsignedInt(4+nph_);
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=tmpUnsignedInt) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "wphjet process should have " << 4+nph_ << " particles to omit from"
<< "jet-parton matching." << Exception::eventerror;
}
} else if(ihrd_==16) {
/* 2Qph... <--- if Q is a top it will decay. */
/* Exclude the hard photons and any children they
may have produced from the jet parton matching
as well as the heavy quarks and any children it
may have produced. */
// AND WHAT ABOUT THE PHOTON?
if(ihvy_==6) {
if(abs(preshowerFSPs_[ixx]->id())==22||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==6||
abs(preshowerFSPs_[ixx]->parents()[0]->id())==24) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
unsigned int tmpUnsignedInt(6+nph_);
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=tmpUnsignedInt) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "wphjet process should have " << 6+nph_ << " particles to omit from"
<< "jet-parton matching for ihvy=" << ihvy_ << "." << Exception::eventerror;
}
} else {
if(abs(preshowerFSPs_[ixx]->id())==22||
(abs(preshowerFSPs_[ixx]->id())==ihvy_&&ixx<2)) {
preshowerFSPsToDelete_.push_back(preshowerFSPs_[ixx]);
getDescendents(preshowerFSPs_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
unsigned int tmpUnsignedInt(2+nph_);
if(ixx==preshowerFSPs_.size()-1&&preshowerFSPsToDelete_.size()!=tmpUnsignedInt) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "wphjet process should have " << 2+nph_ << " particles to omit from"
<< "jet-parton matching for ihvy=" << ihvy_ << "." << Exception::eventerror;
}
}
}
}
for(unsigned int ixx=0; ixx<preshowerFSPsToDelete_.size(); ixx++) {
for(unsigned int jxx=0; jxx<partonsToMatch_.size(); jxx++) {
if(preshowerFSPsToDelete_[ixx]==partonsToMatch_[jxx]) {
partonsToMatch_.erase(partonsToMatch_.begin()+jxx);
break;
}
}
}
for(unsigned int ixx=0; ixx<showeredFSPsToDelete_.size(); ixx++) {
for(unsigned int jxx=0; jxx<particlesToCluster_.size(); jxx++) {
if(showeredFSPsToDelete_[ixx]==particlesToCluster_[jxx]) {
particlesToCluster_.erase(particlesToCluster_.begin()+jxx);
break;
}
}
}
// Sanity check!
if(partonsToMatch_.size()>particlesToCluster_.size()) {
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "No. of ME level partons to be matched to jets = "
<< partonsToMatch_.size() << "\n"
<< "No. of showered particles to build jets from = "
<< particlesToCluster_.size() << "\n"
<< "There should be at least as many partons to\n"
<< "cluster as there are partons to match to.\n"
<< Exception::eventerror;
}
// Acid test.
unsigned int tmpUnsignedInt(njets_);
if(!inputIsNLO_&&partonsToMatch_.size()!=tmpUnsignedInt) {
for(unsigned int ixx=0; ixx<partonsToMatch_.size(); ixx++) {
if(abs(partonsToMatch_[ixx]->id())>=6&&
abs(partonsToMatch_[ixx]->id())!=21)
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "Found a parton to match to which is not a quark or gluon!"
<< *partonsToMatch_[ixx] << "\n"
<< Exception::eventerror;
}
throw Exception()
<< "AlpGenHandler::caldel_m() - ERROR!\n"
<< "No. of ME level partons to be matched to jets = "
<< partonsToMatch_.size() << "\n"
<< "No. of light jets (njets) in AlpGen process = "
<< njets_ << "\n"
<< "These should be equal." << "\n"
<< Exception::eventerror;
}
return;
}
// This looks for all descendents of a top up to but not including
// the W and b children.
void AlpGenHandler::getTopRadiation(PPtr theParticle) {
ParticleVector theChildren(theParticle->children());
for (unsigned int ixx=0; ixx<theChildren.size(); ixx++)
if(theChildren[ixx]->children().size()==0)
tmpList_.push_back(theChildren[ixx]);
else if(abs(theChildren[ixx]->id())==5||abs(theChildren[ixx]->id())==24)
return;
else
getTopRadiation(theChildren[ixx]);
return;
}
void AlpGenHandler::caldel_hvq() {
// Fill partonsToMatch_ with only those pre-shower partons intended to
// be used in heavy-quark-jet matching and fill particlesToCluster_ using
// only those final state particles (post-shower) which are supposed
// in the heavy-quark-jet clustering used to do merging. To begin with
// these are made from the corresponding sets of particles that were
// omitted from the initial jet-parton matching run.
partonsToMatch_ = preshowerFSPsToDelete_;
particlesToCluster_.resize(showeredFSPsToDelete_.size());
for(unsigned int ixx=0; ixx<showeredFSPsToDelete_.size(); ixx++)
particlesToCluster_[ixx] = showeredFSPsToDelete_[ixx];
// Reset the arrays of particles to delete so that the partonsToMatch_
// and particlesToCluster_ vectors can undergo further filtering.
preshowerFSPsToDelete_.clear();
showeredFSPsToDelete_.clear();
// Determine further particles in partonsToMatch_ and particlesToCluster_
// for deletion.
for(unsigned int ixx=0; ixx<partonsToMatch_.size(); ixx++) {
// If the progenitor particle is not a heavy
// quark we delete it and its descendents.
if(abs(partonsToMatch_[ixx]->id())<4||abs(partonsToMatch_[ixx]->id())>6) {
preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]);
tmpList_.clear();
getDescendents(partonsToMatch_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
// If the progenitor is a b quark from a top decay drop
// it & it's descendents too!
} else if(abs(partonsToMatch_[ixx]->id())==5&&
partonsToMatch_[ixx]->parents().size()>0&&
abs(partonsToMatch_[ixx]->parents()[0]->id())==6) {
preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]);
tmpList_.clear();
getDescendents(partonsToMatch_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
// If (it's a hvy quark not from a top decay and) it has a W/Z/H
// as a parent [ditto].
} else if(partonsToMatch_[ixx]->parents().size()>0&&
(abs(partonsToMatch_[ixx]->parents()[0]->id())==23||
abs(partonsToMatch_[ixx]->parents()[0]->id())==24||
abs(partonsToMatch_[ixx]->parents()[0]->id())==25)) {
preshowerFSPsToDelete_.push_back(partonsToMatch_[ixx]);
tmpList_.clear();
getDescendents(partonsToMatch_[ixx]);
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
showeredFSPsToDelete_.push_back(tmpList_[jxx]);
}
}
// Now do the necessary deleting from partonsToMatch_ and
// particlesToCluster_.
for(unsigned int ixx=0; ixx<preshowerFSPsToDelete_.size(); ixx++) {
for(unsigned int jxx=0; jxx<partonsToMatch_.size(); jxx++) {
if(preshowerFSPsToDelete_[ixx]==partonsToMatch_[jxx]) {
partonsToMatch_.erase(partonsToMatch_.begin()+jxx);
break;
}
}
}
for(unsigned int ixx=0; ixx<showeredFSPsToDelete_.size(); ixx++) {
for(unsigned int jxx=0; jxx<particlesToCluster_.size(); jxx++) {
if(showeredFSPsToDelete_[ixx]==particlesToCluster_[jxx]) {
particlesToCluster_.erase(particlesToCluster_.begin()+jxx);
break;
}
}
}
// Now we return to get the decaying top quarks and any
// radiation they produced.
ParticleVector intermediates(lastXCombPtr()->subProcess()->intermediates());
for(unsigned int ixx=0; ixx<intermediates.size(); ixx++) {
if(abs(intermediates[ixx]->id())==6) {
partonsToMatch_.push_back(intermediates[ixx]);
tmpList_.clear();
getTopRadiation(partonsToMatch_.back());
for(unsigned int jxx=0; jxx<tmpList_.size(); jxx++)
particlesToCluster_.push_back(tmpList_[jxx]);
}
}
// If there are any heavy quark progenitors we have to remove
// the final (showered) instance of them from particlesToCluster.
ParticleVector evolvedHeavyQuarks;
for(unsigned int ixx=0; ixx<partonsToMatch_.size(); ixx++) {
if(abs(partonsToMatch_[ixx]->id())>=4&&abs(partonsToMatch_[ixx]->id())<=6) {
theProgenitor = partonsToMatch_[ixx];
// Follow the heavy quark line down to where it stops branching.
while(theProgenitor->children().size()>0) {
theLastProgenitor = theProgenitor;
for(unsigned int jxx=0; jxx<theProgenitor->children().size(); jxx++) {
if(theProgenitor->children()[jxx]->id()==theProgenitor->id())
theProgenitor=theProgenitor->children()[jxx];
}
// If the progenitor had children but none of them had
// the same particle id as it, then it must have undergone
// a decay rather than a branching, i.e. it is the end of
// the evolution line, so,
if(theProgenitor==theLastProgenitor) break;
}
evolvedHeavyQuarks.push_back(theProgenitor);
}
}
// Now delete the evolved heavy quark from the particlesToCluster.
for(unsigned int ixx=0; ixx<evolvedHeavyQuarks.size(); ixx++) {
for(unsigned int jxx=0; jxx<particlesToCluster_.size(); jxx++) {
if(evolvedHeavyQuarks[ixx]==particlesToCluster_[jxx]) {
particlesToCluster_.erase(particlesToCluster_.begin()+jxx);
break;
}
}
}
return;
}
void AlpGenHandler::getPreshowerParticles() {
// LH file initial-state partons:
preshowerISPs_ = lastXCombPtr()->subProcess()->incoming();
// LH file final-state partICLEs:
preshowerFSPs_ = lastXCombPtr()->subProcess()->outgoing();
return;
}
void AlpGenHandler::getShoweredParticles() {
// Post-shower initial-state hadrons:
showeredISHs_ = eventHandler()->currentEvent()->incoming();
// Post-shower initial-state partons:
for(unsigned int ixx=0; ixx<(showeredISHs_.first)->children().size(); ixx++)
if(((showeredISHs_.first)->children()[ixx]->id())<6||
((showeredISHs_.first)->children()[ixx]->id())==21)
showeredISPs_.first=(showeredISHs_.first)->children()[ixx];
for(unsigned int ixx=0; ixx<(showeredISHs_.second)->children().size(); ixx++)
if(((showeredISHs_.second)->children()[ixx]->id())<6||
((showeredISHs_.second)->children()[ixx]->id())==21)
showeredISPs_.second=(showeredISHs_.second)->children()[ixx];
// Post-shower final-state partICLEs plus remnants (to be removed later):
showeredFSPs_ = eventHandler()->currentEvent()->getFinalState();
// Post-shower final-state remnants:
for(unsigned int ixx=0; ixx<showeredFSPs_.size(); ixx++) {
if(showeredFSPs_[ixx]->PDGName()=="Rem:p+"||
showeredFSPs_[ixx]->PDGName()=="Rem:pbar-") {
if(showeredFSPs_[ixx]->parents()[0]->parents()[0]==
showeredISHs_.first)
showeredRems_.first=showeredFSPs_[ixx];
else if(showeredFSPs_[ixx]->parents()[0]->parents()[0]==
showeredISHs_.second)
showeredRems_.second=showeredFSPs_[ixx];
}
}
// Now delete found remnants from the showeredFSPs vector for consistency.
for(unsigned int ixx=0; ixx<showeredFSPs_.size(); ixx++)
if(showeredFSPs_[ixx]->PDGName()=="Rem:p+")
showeredFSPs_.erase(showeredFSPs_.begin()+ixx);
for(unsigned int ixx=0; ixx<showeredFSPs_.size(); ixx++)
if(showeredFSPs_[ixx]->PDGName()=="Rem:pbar-")
showeredFSPs_.erase(showeredFSPs_.begin()+ixx);
sort(showeredFSPs_.begin(),showeredFSPs_.end(),recordEntry);
return;
}
void AlpGenHandler::doSanityChecks(int debugLevel) {
// When checking momentum conservation in the form
// p_in - p_out, any momentum component bigger / less
// than + / - epsilon will result in the p_in - p_out
// vector being flagged as "non-null", triggering a
// warning that momentum conservation is violated.
Energy epsilon(0.5*GeV);
if(debugLevel>=5) epsilon=1e-9*GeV;
// Print out what was found for the incoming and outgoing
// partons in the lastXCombPtr regardless.
if(debugLevel>=5) {
cout << "\n\n\n\n";
cout << "****************************************************" << endl;
cout << " The following are the hard subprocess momenta from " << "\n"
<< " lastXCombPtr and should be basically identical to " << "\n"
<< " the input LH file momenta." << "\n\n";
cout << " Incoming particles:" << "\n"
<< *(preshowerISPs_.first) << "\n"
<< *(preshowerISPs_.second) << endl;
cout << " Outgoing particles:" << endl;
for(unsigned int ixx=0; ixx<preshowerFSPs_.size(); ixx++)
cout << *(preshowerFSPs_[ixx]) << endl;
}
// Print out what was found for the incoming and outgoing
// partons after the shower.
if(debugLevel>=5) {
cout << "\n\n";
cout << "****************************************************" << endl;
cout << " The following are the particles left at the end of" << "\n"
<< " the showering step." << "\n\n";
cout << " Incoming hadrons:" << "\n"
<< *(showeredISHs_.first) << "\n"
<< *(showeredISHs_.second) << endl;
cout << " Incoming partons:" << "\n"
<< *(showeredISPs_.first) << "\n"
<< *(showeredISPs_.second) << endl;
cout << " Outgoing partons:" << endl;
for(unsigned int ixx=0; ixx<showeredFSPs_.size(); ixx++)
cout << *(showeredFSPs_[ixx]) << endl;
cout << " Outgoing remnants:" << "\n"
<< *(showeredRems_.first) << "\n"
<< *(showeredRems_.second) << endl;
}
// Check if we correctly identified all initial and final-state
// particles by testing momentum is conserved.
if(debugLevel>=4) {
Lorentz5Momentum tmpMom;
tmpMom += showeredISPs_.first->momentum();
tmpMom += showeredISPs_.second->momentum();
for(unsigned int ixx=0; ixx<showeredFSPs_.size(); ixx++)
tmpMom -= showeredFSPs_[ixx]->momentum();
if(!isMomLessThanEpsilon(tmpMom,epsilon))
cout << "Total parton mom.in - total parton mom.out = "
<< tmpMom/GeV << endl;
tmpMom = showeredISHs_.first->momentum()
- showeredRems_.first->momentum() -showeredISPs_.first->momentum();
if(!isMomLessThanEpsilon(tmpMom,epsilon))
cout << "First p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl;
tmpMom = showeredISHs_.second->momentum()
- showeredRems_.second->momentum()-showeredISPs_.second->momentum();
if(!isMomLessThanEpsilon(tmpMom,epsilon))
cout << "Second p_hadron-p_remnant-p_incoming " << tmpMom/GeV << endl;
}
// Check if what we found to be the remnant is consistent with
// what we identified as the parent incoming hadron i.e. p+
// goes with Rem:p+ and pbar- goes with Rem:pbar-.
if(debugLevel>=0) {
string tmpString;
tmpString=showeredRems_.first->PDGName();
tmpString=tmpString.substr(tmpString.find_first_of(":")+1,
string::npos);
if(showeredISHs_.first->PDGName()!=tmpString) {
cout << "AlpGenHandler::showerHardProcessVeto" << "\n"
<< "Fatal error in pairing of remnant and parent hadron." << "\n"
<< "Remnant = " << *(showeredRems_.first) << "\n"
<< "Parent hadron = " << *(showeredISHs_.first)
<< endl;
cout << showeredISHs_.first->PDGName() << endl;
cout << tmpString << endl;
}
tmpString=showeredRems_.second->PDGName();
tmpString=tmpString.substr(tmpString.find_first_of(":")+1,
string::npos);
if(showeredISHs_.second->PDGName()!=tmpString) {
cout << "AlpGenHandler::showerHardProcessVeto" << "\n"
<< "Fatal error in pairing of remnant and parent hadron." << "\n"
<< "Remnant = " << *(showeredRems_.second) << "\n"
<< "Parent hadron = " << *(showeredISHs_.second)
<< endl;
cout << showeredISHs_.second->PDGName() << endl;
cout << tmpString << endl;
}
}
return;
}
void AlpGenHandler::printMomVec(vector<Lorentz5Momentum> momVec) {
cout << "\n\n";
// Label columns.
printf("%5s %9s %9s %9s %9s %9s %9s %9s %9s %9s\n",
"jet #",
"px","py","pz","E",
"eta","phi","pt","et","mass");
// Print out the details for each jet
for (unsigned int ixx=0; ixx<momVec.size(); ixx++) {
printf("%5u %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f\n",
ixx,
double(momVec[ixx].x()/GeV),double(momVec[ixx].y()/GeV),
double(momVec[ixx].z()/GeV),double(momVec[ixx].t()/GeV),
double(momVec[ixx].eta()) ,double(momVec[ixx].phi()),
double(momVec[ixx].perp()/GeV),
double(momVec[ixx].et()/GeV),
double(momVec[ixx].m()/GeV));
}
}
Energy AlpGenHandler::etclusran_(double petc) {
return (((2 * epsetclus_)/M_PI) * asin(2 * petc - 1) + etclusmean_);
}
diff --git a/Decay/General/FFSDecayer.cc b/Decay/General/FFSDecayer.cc
--- a/Decay/General/FFSDecayer.cc
+++ b/Decay/General/FFSDecayer.cc
@@ -1,407 +1,407 @@
// -*- C++ -*-
//
// FFSDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FFSDecayer class.
//
#include "FFSDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig/Utilities/Kinematics.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
IBPtr FFSDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FFSDecayer::fullclone() const {
return new_ptr(*this);
}
void FFSDecayer::doinit() {
_perturbativeVertex = dynamic_ptr_cast<FFSVertexPtr> (getVertex());
_abstractVertex = dynamic_ptr_cast<AbstractFFSVertexPtr>(getVertex());
_abstractIncomingVertex = dynamic_ptr_cast<AbstractFFVVertexPtr>(getIncomingVertex());
if (getOutgoingVertices()[0]){
if (getOutgoingVertices()[0]->getName()==VertexType::FFV){
_abstractOutgoingVertexF = dynamic_ptr_cast<AbstractFFVVertexPtr>(getOutgoingVertices()[0]);
_abstractOutgoingVertexS = dynamic_ptr_cast<AbstractVSSVertexPtr>(getOutgoingVertices()[1]);
}
else {
_abstractOutgoingVertexF = dynamic_ptr_cast<AbstractFFVVertexPtr>(getOutgoingVertices()[1]);
_abstractOutgoingVertexS = dynamic_ptr_cast<AbstractVSSVertexPtr>(getOutgoingVertices()[0]);
}
}
else if (getOutgoingVertices()[1]){
if (getOutgoingVertices()[1]->getName()==VertexType::FFV){
_abstractOutgoingVertexF = dynamic_ptr_cast<AbstractFFVVertexPtr>(getOutgoingVertices()[1]);
_abstractOutgoingVertexS = dynamic_ptr_cast<AbstractVSSVertexPtr>(getOutgoingVertices()[0]);
}
else {
_abstractOutgoingVertexF = dynamic_ptr_cast<AbstractFFVVertexPtr>(getOutgoingVertices()[0]);
_abstractOutgoingVertexS = dynamic_ptr_cast<AbstractVSSVertexPtr>(getOutgoingVertices()[1]);
}
}
GeneralTwoBodyDecayer::doinit();
}
void FFSDecayer::persistentOutput(PersistentOStream & os) const {
os << _perturbativeVertex << _abstractVertex
<< _abstractIncomingVertex << _abstractOutgoingVertexF
<< _abstractOutgoingVertexS;
}
void FFSDecayer::persistentInput(PersistentIStream & is, int) {
is >> _perturbativeVertex >> _abstractVertex
>> _abstractIncomingVertex >> _abstractOutgoingVertexF
>> _abstractOutgoingVertexS;
}
ClassDescription<FFSDecayer> FFSDecayer::initFFSDecayer;
// Definition of the static class description member.
void FFSDecayer::Init() {
static ClassDocumentation<FFSDecayer> documentation
("The FFSDecayer class implements the decay of a fermion to "
"a fermion and a scalar.");
}
double FFSDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0)));
//Need to use different barred or unbarred spinors depending on
//whether particle is cc or not.
int itype[2];
if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0? 0:1;
else itype[0] = 2;
if(decay[0]->dataPtr()->CC()) itype[1] = decay[0]->id() > 0? 0:1;
else itype[1] = 2;
bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2));
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(_wave,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wave[0].wave().Type() != u_spinortype)
+ if(_wave[0].wave().Type() != SpinorType::u)
for(unsigned int ix = 0; ix < 2; ++ix) _wave [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(_wavebar,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wavebar[0].wave().Type() != v_spinortype)
+ if(_wavebar[0].wave().Type() != SpinorType::v)
for(unsigned int ix = 0; ix < 2; ++ix) _wavebar[ix].conjugate();
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(_wave,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_wavebar,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_wave,decay[0],outgoing,true);
}
ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true);
}
if(ferm)
SpinorBarWaveFunction::
calculateWaveFunctions(_wavebar,decay[0],outgoing);
else
SpinorWaveFunction::
calculateWaveFunctions(_wave ,decay[0],outgoing);
ScalarWaveFunction scal(decay[1]->momentum(),decay[1]->dataPtr(),outgoing);
Energy2 scale(sqr(inpart.mass()));
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 2; ++if2) {
if(ferm) (*ME())(if1, if2, 0) =
_abstractVertex->evaluate(scale,_wave[if1],_wavebar[if2],scal);
else (*ME())(if2, if1, 0) =
_abstractVertex->evaluate(scale,_wave[if1],_wavebar[if2],scal);
}
}
double output = (ME()->contract(_rho)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// return the answer
return output;
}
Energy FFSDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
double mu1(0.),mu2(0.);
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
if(outa.first->iSpin() == PDT::Spin1Half) {
mu1 = outa.second/inpart.second;
mu2 = outb.second/inpart.second;
_perturbativeVertex->setCoupling(sqr(inpart.second), in, outa.first, outb.first);
}
else {
mu1 = outb.second/inpart.second;
mu2 = outa.second/inpart.second;
_perturbativeVertex->setCoupling(sqr(inpart.second), in, outb.first, outa.first);
}
double c2 = norm(_perturbativeVertex->norm());
Complex cl = _perturbativeVertex->left();
Complex cr = _perturbativeVertex->right();
double me2 = c2*( (norm(cl) + norm(cr))*(1. + sqr(mu1) - sqr(mu2))
+ 2.*mu1*(conj(cl)*cr + conj(cr)*cl).real() );
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second,
outb.second);
Energy output = me2*pcm/16./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
double FFSDecayer::threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay, MEOption meopt) {
int iscal (0), iferm (1), iglu (2);
// get location of outgoing fermion/scalar
if(decay[1]->dataPtr()->iSpin()==PDT::Spin0) swap(iscal,iferm);
// work out whether inpart is a fermion or antifermion
int itype[2];
if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1;
else itype[0] = 2;
if(decay[iferm]->dataPtr()->CC()) itype[1] = decay[iferm]->id() > 0 ? 0 : 1;
else itype[1] = 2;
bool ferm(itype[0] == 0 || itype[1] == 0 ||
(itype[0] == 2 && itype[1] == 2 && decay[iscal]->id() < 0));
if(meopt==Initialize) {
// create spinor (bar) for decaying particle
if(ferm) {
SpinorWaveFunction::calculateWaveFunctions(_wave3, _rho3, const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wave3[0].wave().Type() != u_spinortype)
+ if(_wave3[0].wave().Type() != SpinorType::u)
for(unsigned int ix = 0; ix < 2; ++ix) _wave3[ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(_wavebar3,_rho3, const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wavebar3[0].wave().Type() != v_spinortype)
+ if(_wavebar3[0].wave().Type() != SpinorType::v)
for(unsigned int ix = 0; ix < 2; ++ix) _wavebar3[ix].conjugate();
}
}
// setup spin information when needed
if(meopt==Terminate) {
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(_wave3,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_wavebar3,decay[iferm],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar3,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_wave3,decay[iferm],outgoing,true);
}
ScalarWaveFunction::constructSpinInfo( decay[iscal],outgoing,true);
VectorWaveFunction::constructSpinInfo(_gluon, decay[iglu ],outgoing,true,false);
return 0.;
}
// calulate colour factors and number of colour flows
unsigned int nflow;
vector<DVector> cfactors = getColourFactors(inpart, decay, nflow);
if(nflow==2) cfactors[0][1] = cfactors[1][0];
vector<GeneralDecayMEPtr> ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half, PDT::Spin0,
PDT::Spin1Half, PDT::Spin1)));
// create wavefunctions
if (ferm) SpinorBarWaveFunction::calculateWaveFunctions(_wavebar3, decay[iferm],outgoing);
else SpinorWaveFunction:: calculateWaveFunctions(_wave3 , decay[iferm],outgoing);
ScalarWaveFunction _swave3(decay[iscal]->momentum(), decay[iscal]->dataPtr(),outgoing);
VectorWaveFunction::calculateWaveFunctions(_gluon, decay[iglu ],outgoing,true);
// // gauge invariance test
// _gluon.clear();
// for(unsigned int ix=0;ix<3;++ix) {
// if(ix==1) _gluon.push_back(VectorWaveFunction());
// else {
// _gluon.push_back(VectorWaveFunction(decay[iglu ]->momentum(),
// decay[iglu ]->dataPtr(),10,
// outgoing));
// }
// }
if (! ((_abstractIncomingVertex && (_abstractOutgoingVertexF || _abstractOutgoingVertexS)) ||
(_abstractOutgoingVertexF && _abstractOutgoingVertexS)))
throw Exception()
<< "Invalid vertices for QCD radiation in FFS decay in FFSDecayer::threeBodyME"
<< Exception::runerror;
// sort out colour flows
int F(1), S(2);
if (decay[iscal]->dataPtr()->iColour()==PDT::Colour3 &&
decay[iferm]->dataPtr()->iColour()==PDT::Colour8)
swap(F,S);
else if (decay[iferm]->dataPtr()->iColour()==PDT::Colour3bar &&
decay[iscal]->dataPtr()->iColour()==PDT::Colour8)
swap(F,S);
Complex diag;
Energy2 scale(sqr(inpart.mass()));
const GeneralTwoBodyDecayer::CFlow & colourFlow
= colourFlows(inpart, decay);
for(unsigned int ifi = 0; ifi < 2; ++ifi) {
for(unsigned int ifo = 0; ifo < 2; ++ifo) {
for(unsigned int ig = 0; ig < 2; ++ig) {
// radiation from the incoming fermion
if(inpart.dataPtr()->coloured()) {
assert(_abstractIncomingVertex);
double gs = _abstractIncomingVertex->strongCoupling(scale);
if (ferm){
SpinorWaveFunction spinorInter =
_abstractIncomingVertex->evaluate(scale,3,inpart.dataPtr(),_wave3[ifi],
_gluon[2*ig],inpart.mass());
if (_wave3[ifi].particle()->PDGName()!=spinorInter.particle()->PDGName())
throw Exception()
<< _wave3[ifi].particle()->PDGName() << " was changed to "
<< spinorInter.particle()->PDGName() << " in FFSDecayer::threeBodyME"
<< Exception::runerror;
diag = _abstractVertex->evaluate(scale,spinorInter,_wavebar3[ifo],_swave3)/gs;
}
else {
SpinorBarWaveFunction spinorBarInter =
_abstractIncomingVertex->evaluate(scale,3,inpart.dataPtr(),_wavebar3[ifi],
_gluon[2*ig],inpart.mass());
if (_wavebar3[ifi].particle()->PDGName()!=spinorBarInter.particle()->PDGName())
throw Exception()
<< _wavebar3[ifi].particle()->PDGName() << " was changed to "
<< spinorBarInter.particle()->PDGName() << " in FFSDecayer::threeBodyME"
<< Exception::runerror;
diag = _abstractVertex->evaluate(scale,_wave3[ifo], spinorBarInter,_swave3)/gs;
}
for(unsigned int ix=0;ix<colourFlow[0].size();++ix) {
(*ME[colourFlow[0][ix].first])(ifi, 0, ifo, ig) +=
colourFlow[0][ix].second*diag;
}
}
// radiation from outgoing fermion
if(decay[iferm]->dataPtr()->coloured()) {
assert(_abstractOutgoingVertexF);
// ensure you get correct outgoing particle from first vertex
tcPDPtr off = decay[iferm]->dataPtr();
if(off->CC()) off = off->CC();
double gs = _abstractOutgoingVertexF->strongCoupling(scale);
if (ferm) {
SpinorBarWaveFunction spinorBarInter =
_abstractOutgoingVertexF->evaluate(scale,3,off,_wavebar3[ifo],
_gluon[2*ig],decay[iferm]->mass());
if(_wavebar3[ifo].particle()->PDGName()!=spinorBarInter.particle()->PDGName())
throw Exception()
<< _wavebar3[ifo].particle()->PDGName() << " was changed to "
<< spinorBarInter.particle()->PDGName() << " in FFSDecayer::threeBodyME"
<< Exception::runerror;
diag = _abstractVertex->evaluate(scale,_wave3[ifi],spinorBarInter,_swave3)/gs;
}
else {
SpinorWaveFunction spinorInter =
_abstractOutgoingVertexF->evaluate(scale,3,off,_wave3[ifo],
_gluon[2*ig],decay[iferm]->mass());
if(_wave3[ifo].particle()->PDGName()!=spinorInter.particle()->PDGName())
throw Exception()
<< _wave3[ifo].particle()->PDGName() << " was changed to "
<< spinorInter.particle()->PDGName() << " in FFSDecayer::threeBodyME"
<< Exception::runerror;
diag = _abstractVertex->evaluate(scale,spinorInter,_wavebar3[ifi],_swave3)/gs;
}
for(unsigned int ix=0;ix<colourFlow[F].size();++ix) {
(*ME[colourFlow[F][ix].first])(ifi, 0, ifo, ig) +=
colourFlow[F][ix].second*diag;
}
}
// radiation from outgoing scalar
if(decay[iscal]->dataPtr()->coloured()) {
assert(_abstractOutgoingVertexS);
// ensure you get correct ougoing particle from first vertex
tcPDPtr off = decay[iscal]->dataPtr();
if(off->CC()) off = off->CC();
double gs = _abstractOutgoingVertexS->strongCoupling(scale);
ScalarWaveFunction scalarInter =
_abstractOutgoingVertexS->evaluate(scale,3,off,_gluon[2*ig],
_swave3,decay[iscal]->mass());
if(_swave3.particle()->PDGName()!=scalarInter.particle()->PDGName())
throw Exception()
<< _swave3 .particle()->PDGName() << " was changed to "
<< scalarInter.particle()->PDGName() << " in FFSDecayer::threeBodyME"
<< Exception::runerror;
if (ferm){
diag = _abstractVertex->evaluate(scale,_wave3[ifi],_wavebar3[ifo],scalarInter)/gs;
}
else {
diag = _abstractVertex->evaluate(scale,_wave3[ifo],_wavebar3[ifi],scalarInter)/gs;
}
for(unsigned int ix=0;ix<colourFlow[S].size();++ix) {
(*ME[colourFlow[S][ix].first])(ifi, 0, ifo, ig) +=
colourFlow[S][ix].second*diag;
}
}
}
}
}
// contract matrices
double output=0.;
for(unsigned int ix=0; ix<nflow; ++ix){
for(unsigned int iy=0; iy<nflow; ++iy){
output+=cfactors[ix][iy]*(ME[ix]->contract(*ME[iy],_rho3)).real();
}
}
output*=(4.*Constants::pi);
// return the answer
return output;
}
diff --git a/Decay/General/FFVCurrentDecayer.cc b/Decay/General/FFVCurrentDecayer.cc
--- a/Decay/General/FFVCurrentDecayer.cc
+++ b/Decay/General/FFVCurrentDecayer.cc
@@ -1,199 +1,197 @@
// -*- C++ -*-
//
// FFVCurrentDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FFVCurrentDecayer class.
//
#include "FFVCurrentDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
-using ThePEG::Helicity::u_spinortype;
-using ThePEG::Helicity::v_spinortype;
using ThePEG::Helicity::VectorWaveFunction;
using ThePEG::Helicity::SpinorWaveFunction;
using ThePEG::Helicity::SpinorBarWaveFunction;
using ThePEG::Helicity::Direction;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
IBPtr FFVCurrentDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FFVCurrentDecayer::fullclone() const {
return new_ptr(*this);
}
void FFVCurrentDecayer::doinit() {
_theFFVPtr = dynamic_ptr_cast<FFVVertexPtr>(getVertex());
GeneralCurrentDecayer::doinit();
}
void FFVCurrentDecayer::rebind(const TranslationMap & trans)
{
_theFFVPtr = trans.translate(_theFFVPtr);
GeneralCurrentDecayer::rebind(trans);
}
IVector FFVCurrentDecayer::getReferences() {
IVector ret = GeneralCurrentDecayer::getReferences();
ret.push_back(_theFFVPtr);
return ret;
}
void FFVCurrentDecayer::persistentOutput(PersistentOStream & os) const {
os << _theFFVPtr;
}
void FFVCurrentDecayer::persistentInput(PersistentIStream & is, int) {
is >> _theFFVPtr;
}
ClassDescription<FFVCurrentDecayer> FFVCurrentDecayer::initFFVCurrentDecayer;
// Definition of the static class description member.
void FFVCurrentDecayer::Init() {
static ClassDocumentation<FFVCurrentDecayer> documentation
("There is no documentation for the FFVCurrentDecayer class");
}
double FFVCurrentDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// get the particles for the hadronic curret
Energy q;
ParticleVector hadpart(decay.begin()+1,decay.end());
// fermion types
int itype[2];
if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1;
else itype[0] = 2;
if(decay[0]->dataPtr()->CC()) itype[1] = decay[0]->id() > 0 ? 0 : 1;
else itype[1] = 2;
//Need to use different barred or unbarred spinors depending on
//whether particle is cc or not.
bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2));
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(_wave,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wave[0].wave().Type() != u_spinortype)
+ if(_wave[0].wave().Type() != SpinorType::u)
for(unsigned int ix = 0; ix < 2; ++ix) _wave [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(_wavebar,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wavebar[0].wave().Type() != v_spinortype)
+ if(_wavebar[0].wave().Type() != SpinorType::v)
for(unsigned int ix = 0; ix < 2; ++ix) _wavebar[ix].conjugate();
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(_wave,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_wavebar,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_wave,decay[0],outgoing,true);
}
weakCurrent()->current(mode(),ichan,q,hadpart,meopt);
return 0.;
}
Energy2 scale(sqr(inpart.mass()));
if(ferm)
SpinorBarWaveFunction::
calculateWaveFunctions(_wavebar,decay[0],outgoing);
else
SpinorWaveFunction::
calculateWaveFunctions(_wave ,decay[0],outgoing);
// calculate the hadron current
vector<LorentzPolarizationVectorE>
hadron(weakCurrent()->current(mode(),ichan,q,hadpart,meopt));
// prefactor
double pre = sqr(pow(inpart.mass()/q,int(hadpart.size()-2)));
// work out the mapping for the hadron vector
vector<unsigned int> constants(decay.size()+1),ihel(decay.size()+1);
vector<PDT::Spin> ispin(decay.size());
int itemp(1);
unsigned int hhel,ix(decay.size());
do {
--ix;
ispin[ix]=decay[ix]->data().iSpin();
itemp*=ispin[ix];
constants[ix]=itemp;
}
while(ix>0);
constants[decay.size()]=1;
constants[0]=constants[1];
// compute the matrix element
GeneralDecayMEPtr newME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,ispin)));
VectorWaveFunction vWave;
tcPDPtr vec= inpart.dataPtr()->iCharge()-decay[0]->dataPtr()->iCharge() > 0
? getParticleData(ParticleID::Wplus) : getParticleData(ParticleID::Wminus);
Lorentz5Momentum vmom=inpart.momentum()-decay[0]->momentum();
vmom.rescaleMass();
for(hhel=0;hhel<hadron.size();++hhel) {
// map the index for the hadrons to a helicity state
for(ix=decay.size();ix>1;--ix) ihel[ix]=(hhel%constants[ix-1])/constants[ix];
vWave=VectorWaveFunction(vmom,vec,hadron[hhel]*UnitRemoval::InvE,outgoing);
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 2; ++if2) {
ihel[0]=if1;
ihel[1]=if2;
if(!ferm) swap(ihel[0],ihel[1]);
(*newME)(ihel) = _theFFVPtr->evaluate(scale,_wave[if1],_wavebar[if2],vWave);
}
}
}
// store the matrix element
ME(newME);
// multiply by the CKM element
int iq,ia;
weakCurrent()->decayModeInfo(mode(),iq,ia);
double ckm(1.);
if(iq<=6) {
if(iq%2==0) ckm = SM().CKM(iq/2-1,(abs(ia)-1)/2);
else ckm = SM().CKM(abs(ia)/2-1,(iq-1)/2);
}
pre /= 0.125*sqr(_theFFVPtr->weakCoupling(scale));
double output(0.5*pre*ckm*(ME()->contract(_rho)).real()*
sqr(SM().fermiConstant()*UnitRemoval::E2));
return output;
}
Energy FFVCurrentDecayer::partialWidth(tPDPtr inpart, tPDPtr outa,
vector<tPDPtr> currout) {
vector<long> id;
id.push_back(inpart->id());
id.push_back(outa->id());
for(unsigned int ix=0;ix<currout.size();++ix) id.push_back(currout[ix]->id());
bool cc;
int mode=modeNumber(cc,id);
imode(mode);
return initializePhaseSpaceMode(mode,true,true);
}
diff --git a/Decay/General/FFVDecayer.cc b/Decay/General/FFVDecayer.cc
--- a/Decay/General/FFVDecayer.cc
+++ b/Decay/General/FFVDecayer.cc
@@ -1,428 +1,428 @@
// -*- C++ -*-
//
// FFVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FFVDecayer class.
//
#include "FFVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig/Utilities/Kinematics.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
IBPtr FFVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FFVDecayer::fullclone() const {
return new_ptr(*this);
}
void FFVDecayer::doinit() {
_perturbativeVertex = dynamic_ptr_cast<FFVVertexPtr> (getVertex());
_abstractVertex = dynamic_ptr_cast<AbstractFFVVertexPtr>(getVertex());
_abstractIncomingVertex = dynamic_ptr_cast<AbstractFFVVertexPtr>(getIncomingVertex());
if (getOutgoingVertices()[0]){
if (getOutgoingVertices()[0]->getName()==VertexType::FFV){
_abstractOutgoingVertexF = dynamic_ptr_cast<AbstractFFVVertexPtr>(getOutgoingVertices()[0]);
_abstractOutgoingVertexV = dynamic_ptr_cast<AbstractVVVVertexPtr>(getOutgoingVertices()[1]);
}
else {
_abstractOutgoingVertexF = dynamic_ptr_cast<AbstractFFVVertexPtr>(getOutgoingVertices()[1]);
_abstractOutgoingVertexV = dynamic_ptr_cast<AbstractVVVVertexPtr>(getOutgoingVertices()[0]);
}
}
else if (getOutgoingVertices()[1]){
if (getOutgoingVertices()[1]->getName()==VertexType::FFV){
_abstractOutgoingVertexF = dynamic_ptr_cast<AbstractFFVVertexPtr>(getOutgoingVertices()[1]);
_abstractOutgoingVertexV = dynamic_ptr_cast<AbstractVVVVertexPtr>(getOutgoingVertices()[0]);
}
else {
_abstractOutgoingVertexF = dynamic_ptr_cast<AbstractFFVVertexPtr>(getOutgoingVertices()[0]);
_abstractOutgoingVertexV = dynamic_ptr_cast<AbstractVVVVertexPtr>(getOutgoingVertices()[1]);
}
}
GeneralTwoBodyDecayer::doinit();
}
void FFVDecayer::persistentOutput(PersistentOStream & os) const {
os << _abstractVertex << _perturbativeVertex
<< _abstractIncomingVertex << _abstractOutgoingVertexF
<< _abstractOutgoingVertexV;
}
void FFVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _abstractVertex >> _perturbativeVertex
>> _abstractIncomingVertex >> _abstractOutgoingVertexF
>> _abstractOutgoingVertexV;
}
double FFVDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1)));
// type of process
int itype[2];
if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1;
else itype[0] = 2;
if(decay[0]->dataPtr()->CC()) itype[1] = decay[0]->id() > 0 ? 0 : 1;
else itype[1] = 2;
//Need to use different barred or unbarred spinors depending on
//whether particle is cc or not.
bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2));
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(_wave,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wave[0].wave().Type() != u_spinortype)
+ if(_wave[0].wave().Type() != SpinorType::u)
for(unsigned int ix = 0; ix < 2; ++ix) _wave [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(_wavebar,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wavebar[0].wave().Type() != v_spinortype)
+ if(_wavebar[0].wave().Type() != SpinorType::v)
for(unsigned int ix = 0; ix < 2; ++ix) _wavebar[ix].conjugate();
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(_wave,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_wavebar,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_wave,decay[0],outgoing,true);
}
VectorWaveFunction::
constructSpinInfo(_vector,decay[1],outgoing,true,false);
}
Energy2 scale(sqr(inpart.mass()));
if(ferm)
SpinorBarWaveFunction::
calculateWaveFunctions(_wavebar,decay[0],outgoing);
else
SpinorWaveFunction::
calculateWaveFunctions(_wave ,decay[0],outgoing);
bool massless = decay[1]->dataPtr()->mass()==ZERO;
VectorWaveFunction::
calculateWaveFunctions(_vector,decay[1],outgoing,massless);
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 2; ++if2) {
for(unsigned int vhel = 0; vhel < 3; ++vhel) {
if(massless && vhel == 1) ++vhel;
if(ferm)
(*ME())(if1, if2,vhel) =
_abstractVertex->evaluate(scale,_wave[if1],_wavebar[if2],_vector[vhel]);
else
(*ME())(if2, if1, vhel) =
_abstractVertex->evaluate(scale,_wave[if1],_wavebar[if2],_vector[vhel]);
}
}
}
double output=(ME()->contract(_rho)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),decay[1]->dataPtr());
// return the answer
return output;
}
Energy FFVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
double mu1(outa.second/inpart.second),mu2(outb.second/inpart.second);
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
if( outa.first->iSpin() == PDT::Spin1Half)
_perturbativeVertex->setCoupling(sqr(inpart.second), in,
outa.first, outb.first);
else {
swap(mu1,mu2);
_perturbativeVertex->setCoupling(sqr(inpart.second),in,
outb.first,outa.first);
}
Complex cl(_perturbativeVertex->left()),cr(_perturbativeVertex->right());
double me2(0.);
if( mu2 > 0. ) {
me2 = (norm(cl) + norm(cr))*(1. + sqr(mu1*mu2) + sqr(mu2)
- 2.*sqr(mu1) - 2.*sqr(mu2*mu2)
+ sqr(mu1*mu1))
- 6.*mu1*sqr(mu2)*(conj(cl)*cr + conj(cr)*cl).real();
me2 /= sqr(mu2);
}
else
me2 = 2.*( (norm(cl) + norm(cr))*(sqr(mu1) + 1.)
- 4.*mu1*(conj(cl)*cr + conj(cr)*cl).real() );
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second,
outb.second);
Energy output = norm(_perturbativeVertex->norm())*me2*pcm/16./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
ClassDescription<FFVDecayer> FFVDecayer::initFFVDecayer;
// Definition of the static class description member.
void FFVDecayer::Init() {
static ClassDocumentation<FFVDecayer> documentation
("There is no documentation for the FFVDecayer class");
}
double FFVDecayer::threeBodyME(const int , const Particle & inpart,
const ParticleVector & decay, MEOption meopt) {
int iferm (0), ivect (1), iglu (2);
// get location of outgoing lepton/vector
if(decay[1]->dataPtr()->iSpin()==PDT::Spin1Half) swap(iferm,ivect);
// work out whether inpart is a fermion or antifermion
int itype[2];
if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1;
else itype[0] = 2;
if(decay[iferm]->dataPtr()->CC()) itype[1] = decay[iferm]->id() > 0 ? 0 : 1;
else itype[1] = 2;
bool ferm(itype[0] == 0 || itype[1] == 0 ||
(itype[0] == 2 && itype[1] == 2 && decay[ivect]->id() < 0));
// no emissions from massive vectors
bool massless = decay[ivect]->dataPtr()->mass()==ZERO;
if (_abstractOutgoingVertexV && (! massless))
throw Exception()
<< "No dipoles available for massive vectors in FFVDecayer::threeBodyME"
<< Exception::runerror;
if(meopt==Initialize) {
// create spinor (bar) for decaying particle
if(ferm) {
SpinorWaveFunction::calculateWaveFunctions(_wave3, _rho3, const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wave3[0].wave().Type() != u_spinortype)
+ if(_wave3[0].wave().Type() != SpinorType::u)
for(unsigned int ix = 0; ix < 2; ++ix) _wave3[ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(_wavebar3,_rho3, const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(_wavebar3[0].wave().Type() != v_spinortype)
+ if(_wavebar3[0].wave().Type() != SpinorType::v)
for(unsigned int ix = 0; ix < 2; ++ix) _wavebar3[ix].conjugate();
}
}
// setup spin information when needed
if(meopt==Terminate) {
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(_wave3,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_wavebar3,decay[iferm],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar3,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_wave3,decay[iferm],outgoing,true);
}
VectorWaveFunction::constructSpinInfo(_vector3, decay[ivect],outgoing,true,massless);
VectorWaveFunction::constructSpinInfo(_gluon, decay[iglu ],outgoing,true,false);
return 0.;
}
// calulate colour factors and number of colour flows
unsigned int nflow;
vector<DVector> cfactors = getColourFactors(inpart, decay, nflow);
if(nflow==2) cfactors[0][1] = cfactors[1][0];
vector<GeneralDecayMEPtr> ME(nflow,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half, PDT::Spin1Half,
PDT::Spin1, PDT::Spin1)));
// create wavefunctions
if (ferm) SpinorBarWaveFunction::calculateWaveFunctions(_wavebar3, decay[iferm],outgoing);
else SpinorWaveFunction:: calculateWaveFunctions(_wave3 , decay[iferm],outgoing);
VectorWaveFunction::calculateWaveFunctions(_vector3, decay[ivect],outgoing,massless);
VectorWaveFunction::calculateWaveFunctions(_gluon, decay[iglu ],outgoing,true );
// // gauge invariance test
// _gluon.clear();
// for(unsigned int ix=0;ix<3;++ix) {
// if(ix==1) _gluon.push_back(VectorWaveFunction());
// else {
// _gluon.push_back(VectorWaveFunction(decay[iglu ]->momentum(),
// decay[iglu ]->dataPtr(),10,
// outgoing));
// }
// }
if (! ((_abstractIncomingVertex && (_abstractOutgoingVertexF || _abstractOutgoingVertexV)) ||
(_abstractOutgoingVertexF && _abstractOutgoingVertexV)))
throw Exception()
<< "Invalid vertices for QCD radiation in FFV decay in FFVDecayer::threeBodyME"
<< Exception::runerror;
// sort out colour flows
int F(1), V(2);
if (decay[iferm]->dataPtr()->iColour()==PDT::Colour3bar &&
decay[ivect]->dataPtr()->iColour()==PDT::Colour8)
swap(F,V);
else if (decay[ivect]->dataPtr()->iColour()==PDT::Colour3 &&
decay[iferm]->dataPtr()->iColour()==PDT::Colour8)
swap(F,V);
Complex diag;
Energy2 scale(sqr(inpart.mass()));
const GeneralTwoBodyDecayer::CFlow & colourFlow
= colourFlows(inpart, decay);
for(unsigned int ifi = 0; ifi < 2; ++ifi) {
for(unsigned int ifo = 0; ifo < 2; ++ifo) {
for(unsigned int iv = 0; iv < 3; ++iv) {
for(unsigned int ig = 0; ig < 2; ++ig) {
// radiation from the incoming fermion
if(inpart.dataPtr()->coloured()) {
assert(_abstractIncomingVertex);
double gs = _abstractIncomingVertex->strongCoupling(scale);
if (ferm){
SpinorWaveFunction spinorInter =
_abstractIncomingVertex->evaluate(scale,3,inpart.dataPtr(),_wave3[ifi],
_gluon[2*ig],inpart.mass());
if (_wave3[ifi].particle()->PDGName()!=spinorInter.particle()->PDGName())
throw Exception()
<< _wave3[ifi].particle()->PDGName() << " was changed to "
<< spinorInter.particle()->PDGName() << " in FFVDecayer::threeBodyME"
<< Exception::runerror;
diag = _abstractVertex->evaluate(scale,spinorInter,_wavebar3[ifo],_vector3[iv])/gs;
}
else {
SpinorBarWaveFunction spinorBarInter =
_abstractIncomingVertex->evaluate(scale,3,inpart.dataPtr(),_wavebar3[ifi],
_gluon[2*ig],inpart.mass());
if (_wavebar3[ifi].particle()->PDGName()!=spinorBarInter.particle()->PDGName())
throw Exception()
<< _wavebar3[ifi].particle()->PDGName() << " was changed to "
<< spinorBarInter.particle()->PDGName() << " in FFVDecayer::threeBodyME"
<< Exception::runerror;
diag = _abstractVertex->evaluate(scale,_wave3[ifo], spinorBarInter,_vector3[iv])/gs;
}
for(unsigned int ix=0;ix<colourFlow[0].size();++ix) {
(*ME[colourFlow[0][ix].first])(ifi, ifo, iv, ig) +=
colourFlow[0][ix].second*diag;
}
}
// radiation from outgoing fermion
if(decay[iferm]->dataPtr()->coloured()) {
assert(_abstractOutgoingVertexF);
// ensure you get correct outgoing particle from first vertex
tcPDPtr off = decay[iferm]->dataPtr();
if(off->CC()) off = off->CC();
double gs = _abstractOutgoingVertexF->strongCoupling(scale);
if (ferm) {
SpinorBarWaveFunction spinorBarInter =
_abstractOutgoingVertexF->evaluate(scale,3,off,_wavebar3[ifo],
_gluon[2*ig],decay[iferm]->mass());
if(_wavebar3[ifo].particle()->PDGName()!=spinorBarInter.particle()->PDGName())
throw Exception()
<< _wavebar3[ifo].particle()->PDGName() << " was changed to "
<< spinorBarInter.particle()->PDGName() << " in FFVDecayer::threeBodyME"
<< Exception::runerror;
diag = _abstractVertex->evaluate(scale,_wave3[ifi],spinorBarInter,_vector3[iv])/gs;
}
else {
SpinorWaveFunction spinorInter =
_abstractOutgoingVertexF->evaluate(scale,3,off,_wave3[ifo],
_gluon[2*ig],decay[iferm]->mass());
if(_wave3[ifo].particle()->PDGName()!=spinorInter.particle()->PDGName())
throw Exception()
<< _wave3[ifo].particle()->PDGName() << " was changed to "
<< spinorInter.particle()->PDGName() << " in FFVDecayer::threeBodyME"
<< Exception::runerror;
diag = _abstractVertex->evaluate(scale,spinorInter,_wavebar3[ifi],_vector3[iv])/gs;
}
for(unsigned int ix=0;ix<colourFlow[F].size();++ix) {
(*ME[colourFlow[F][ix].first])(ifi, ifo, iv, ig) +=
colourFlow[F][ix].second*diag;
}
}
// radiation from outgoing vector
if(decay[ivect]->dataPtr()->coloured()) {
assert(_abstractOutgoingVertexV);
// ensure you get correct ougoing particle from first vertex
tcPDPtr off = decay[ivect]->dataPtr();
if(off->CC()) off = off->CC();
double sign = decay[iferm]->id()>0 ? -1:1;
double gs = _abstractOutgoingVertexV->strongCoupling(scale);
VectorWaveFunction vectorInter =
_abstractOutgoingVertexV->evaluate(scale,3,off,_gluon[2*ig],
_vector3[iv],decay[ivect]->mass());
if(_vector3[iv].particle()->PDGName()!=vectorInter.particle()->PDGName())
throw Exception()
<< _vector3[iv].particle()->PDGName() << " was changed to "
<< vectorInter. particle()->PDGName() << " in FFVDecayer::threeBodyME"
<< Exception::runerror;
if (ferm){
diag = sign*_abstractVertex->evaluate(scale,_wave3[ifi],_wavebar3[ifo],vectorInter)/gs;
}
else {
diag = sign*_abstractVertex->evaluate(scale,_wave3[ifo],_wavebar3[ifi],vectorInter)/gs;
}
for(unsigned int ix=0;ix<colourFlow[V].size();++ix) {
(*ME[colourFlow[V][ix].first])(ifi, ifo, iv, ig) +=
colourFlow[V][ix].second*diag;
}
}
}
if(massless) ++iv;
}
}
}
// contract matrices
double output=0.;
for(unsigned int ix=0; ix<nflow; ++ix){
for(unsigned int iy=0; iy<nflow; ++iy){
output+=cfactors[ix][iy]*(ME[ix]->contract(*ME[iy],_rho3)).real();
}
}
output*=(4.*Constants::pi);
// return the answer
return output;
}
diff --git a/Decay/General/FRSDecayer.cc b/Decay/General/FRSDecayer.cc
--- a/Decay/General/FRSDecayer.cc
+++ b/Decay/General/FRSDecayer.cc
@@ -1,176 +1,176 @@
// -*- C++ -*-
//
// FRSDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FRSDecayer class.
//
#include "FRSDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig/Utilities/Kinematics.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
IBPtr FRSDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FRSDecayer::fullclone() const {
return new_ptr(*this);
}
void FRSDecayer::doinit() {
perturbativeVertex_ = dynamic_ptr_cast<RFSVertexPtr> (getVertex());
abstractVertex_ = dynamic_ptr_cast<AbstractRFSVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void FRSDecayer::persistentOutput(PersistentOStream & os) const {
os << perturbativeVertex_ << abstractVertex_;
}
void FRSDecayer::persistentInput(PersistentIStream & is, int) {
is >> perturbativeVertex_ >> abstractVertex_;
}
ClassDescription<FRSDecayer> FRSDecayer::initFRSDecayer;
// Definition of the static class description member.
void FRSDecayer::Init() {
static ClassDocumentation<FRSDecayer> documentation
("The FRSDecayer class implements the decay of a fermion to "
"a spin-3/2 fermion and a scalar.");
}
double FRSDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
bool ferm = inpart.id() > 0;
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin3Half,PDT::Spin0)));
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(wave_,rho_,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(wave_[0].wave().Type() != u_spinortype)
+ if(wave_[0].wave().Type() != SpinorType::u)
for(unsigned int ix = 0; ix < 2; ++ix) wave_ [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(wavebar_,rho_,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(wavebar_[0].wave().Type() != v_spinortype)
+ if(wavebar_[0].wave().Type() != SpinorType::v)
for(unsigned int ix = 0; ix < 2; ++ix) wavebar_[ix].conjugate();
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(wave_,const_ptr_cast<tPPtr>(&inpart),incoming,true);
RSSpinorBarWaveFunction::constructSpinInfo(RSwavebar_,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(wavebar_,const_ptr_cast<tPPtr>(&inpart),incoming,true);
RSSpinorWaveFunction::constructSpinInfo(RSwave_,decay[0],outgoing,true);
}
ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true);
}
if(ferm)
RSSpinorBarWaveFunction::
calculateWaveFunctions(RSwavebar_,decay[0],outgoing);
else
RSSpinorWaveFunction::
calculateWaveFunctions(RSwave_ ,decay[0],outgoing);
ScalarWaveFunction scal(decay[1]->momentum(),decay[1]->dataPtr(),outgoing);
Energy2 scale(sqr(inpart.mass()));
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 4; ++if2) {
if(ferm) (*ME())(if1, if2, 0) =
abstractVertex_->evaluate(scale,wave_[if1],RSwavebar_[if2],scal);
else (*ME())(if1, if2, 0) =
abstractVertex_->evaluate(scale,RSwave_[if2],wavebar_[if1],scal);
}
}
double output = (ME()->contract(rho_)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// test code
// Energy q = inpart.mass();
// Energy m1 = decay[0]->mass();
// Energy m2 = decay[1]->mass();
// Energy2 q2(q*q),m12(m1*m1),m22(m2*m2);
// Energy2 pcm2(0.25*(q2*(q2-2.*m12-2.*m22)+(m12-m22)*(m12-m22))/q2);
// Energy pcm(sqrt(pcm2));
// Energy Qp(sqrt((q+m1)*(q+m1)-m22)),Qm(sqrt((q-m1)*(q-m1)-m22));
// double r23(sqrt(2./3.));
// // couplings
// Complex left = perturbativeVertex_-> left()*perturbativeVertex_-> norm();
// Complex right = perturbativeVertex_->right()*perturbativeVertex_-> norm();
// complex<InvEnergy> A1 = 0.5*(left+right)*UnitRemoval::InvE;
// complex<InvEnergy> B1 = 0.5*(right-left)*UnitRemoval::InvE;
// complex<Energy> h1(-2.*r23*pcm*q/m1*Qm*B1);
// complex<Energy> h2( 2.*r23*pcm*q/m1*Qp*A1);
// cout << "testing 1/2->3/2 0 "
// << output*scale/GeV2 << " "
// << real(h1*conj(h1)+h2*conj(h2))/4./GeV2 << " "
// << real(h1*conj(h1)+h2*conj(h2))/4./(output*scale) << endl;
// return the answer
return output;
}
Energy FRSDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(perturbativeVertex_) {
Energy q = inpart.second;
Energy m1 = outa.second;
Energy m2 = outb.second;
Energy2 q2(q*q),m12(m1*m1),m22(m2*m2);
Energy2 pcm2(0.25*(q2*(q2-2.*m12-2.*m22)+(m12-m22)*(m12-m22))/q2);
Energy pcm(sqrt(pcm2));
Energy Qp(sqrt((q+m1)*(q+m1)-m22)),Qm(sqrt((q-m1)*(q-m1)-m22));
double r23(sqrt(2./3.));
// couplings
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
perturbativeVertex_->setCoupling(sqr(inpart.second), outa.first,
in, outb.first);
Complex left = perturbativeVertex_-> left()*perturbativeVertex_-> norm();
Complex right = perturbativeVertex_->right()*perturbativeVertex_-> norm();
complex<InvEnergy> A1 = 0.5*(left+right)*UnitRemoval::InvE;
complex<InvEnergy> B1 = 0.5*(right-left)*UnitRemoval::InvE;
complex<Energy> h1(-2.*r23*pcm*q/m1*Qm*B1);
complex<Energy> h2( 2.*r23*pcm*q/m1*Qp*A1);
double me2 = real(h1*conj(h1)+h2*conj(h2))/4./sqr(inpart.second);
Energy output = me2*pcm/8./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
diff --git a/Decay/General/FRVDecayer.cc b/Decay/General/FRVDecayer.cc
--- a/Decay/General/FRVDecayer.cc
+++ b/Decay/General/FRVDecayer.cc
@@ -1,207 +1,207 @@
// -*- C++ -*-
//
// FRVDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FRVDecayer class.
//
#include "FRVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig/Utilities/Kinematics.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
IBPtr FRVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FRVDecayer::fullclone() const {
return new_ptr(*this);
}
void FRVDecayer::doinit() {
perturbativeVertex_ = dynamic_ptr_cast<RFVVertexPtr> (getVertex());
abstractVertex_ = dynamic_ptr_cast<AbstractRFVVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void FRVDecayer::persistentOutput(PersistentOStream & os) const {
os << abstractVertex_ << perturbativeVertex_;
}
void FRVDecayer::persistentInput(PersistentIStream & is, int) {
is >> abstractVertex_ >> perturbativeVertex_;
}
double FRVDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin3Half,PDT::Spin1)));
// decaying fermion or antifermion
bool ferm = inpart.id() > 0;
// initialize
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(wave_,rho_,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(wave_[0].wave().Type() != u_spinortype)
+ if(wave_[0].wave().Type() != SpinorType::u)
for(unsigned int ix = 0; ix < 2; ++ix) wave_ [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(wavebar_,rho_,
const_ptr_cast<tPPtr>(&inpart),
incoming);
- if(wavebar_[0].wave().Type() != v_spinortype)
+ if(wavebar_[0].wave().Type() != SpinorType::v)
for(unsigned int ix = 0; ix < 2; ++ix) wavebar_[ix].conjugate();
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(wave_,const_ptr_cast<tPPtr>(&inpart),incoming,true);
RSSpinorBarWaveFunction::constructSpinInfo(RSwavebar_,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(wavebar_,const_ptr_cast<tPPtr>(&inpart),incoming,true);
RSSpinorWaveFunction::constructSpinInfo(RSwave_,decay[0],outgoing,true);
}
VectorWaveFunction::
constructSpinInfo(vector_,decay[1],outgoing,true,false);
}
Energy2 scale(sqr(inpart.mass()));
if(ferm)
RSSpinorBarWaveFunction::
calculateWaveFunctions(RSwavebar_,decay[0],outgoing);
else
RSSpinorWaveFunction::
calculateWaveFunctions(RSwave_ ,decay[0],outgoing);
bool massless = decay[1]->dataPtr()->mass()==ZERO;
VectorWaveFunction::
calculateWaveFunctions(vector_,decay[1],outgoing,massless);
// loop over helicities
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 4; ++if2) {
for(unsigned int vhel = 0; vhel < 3; ++vhel) {
if(massless && vhel == 1) ++vhel;
if(ferm)
(*ME())(if1, if2,vhel) =
abstractVertex_->evaluate(scale,wave_[if1],
RSwavebar_[if2],vector_[vhel]);
else
(*ME())(if1, if2, vhel) =
abstractVertex_->evaluate(scale,RSwave_[if2],
wavebar_[if1],vector_[vhel]);
}
}
}
double output=(ME()->contract(rho_)).real()/scale*UnitRemoval::E2;
// test
// Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass());
// Energy2 m12(m1*m1),m22(m2*m2),m32(m3*m3);
// Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3)));
// double r2(sqrt(2.)),r3(sqrt(3.));
// Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3));
// vector<Complex> left = perturbativeVertex_-> left();
// vector<Complex> right = perturbativeVertex_->right();
// Complex A1 = 0.5*(left [0]+right[0])*perturbativeVertex_-> norm();
// Complex B1 = 0.5*(right[0]- left[0])*perturbativeVertex_-> norm();
// complex<InvEnergy> A2 = 0.5*(left [1]+right[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE;
// complex<InvEnergy> B2 = 0.5*(right[1]- left[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE;
// complex<InvEnergy2> A3 = 0.5*(left [2]+right[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2;
// complex<InvEnergy2> B3 = 0.5*(right[2]- left[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2;
// complex<Energy> h1(-2.*Qp*A1),h2(2.*Qm*B1);
// complex<Energy> h3(-2./r3*Qp*(A1-Qm*Qm/m2*A2));
// complex<Energy> h4( 2./r3*Qm*(B1-Qp*Qp/m2*B2));
// complex<Energy> h5(ZERO),h6(ZERO);
// if(decay[1]->mass()>ZERO) {
// h5 = -2.*r2/r3/m2/m3*Qp*(0.5*(m12-m22-m32)*A1+0.5*Qm*Qm*(m1+m2)*A2
// +m12*pcm*pcm*A3);
// h6 = 2.*r2/r3/m2/m3*Qm*(0.5*(m12-m22-m32)*B1-0.5*Qp*Qp*(m1-m2)*B2
// +m12*pcm*pcm*B3);
// }
// cout << "testing 1/2->3/2 1 " << inpart.id() << " "
// << output << " "
// << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+
// h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass()) << " "
// << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+
// h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass())/output << endl;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),decay[1]->dataPtr());
// return the answer
return output;
}
Energy FRVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(perturbativeVertex_) {
Energy m1(inpart.second),m2(outa.second),m3(outb.second);
Energy2 m12(m1*m1),m22(m2*m2),m32(m3*m3);
Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3)));
double r2(sqrt(2.)),r3(sqrt(3.));
Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3));
// couplings
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
perturbativeVertex_->setCoupling(sqr(inpart.second), outa.first,
in, outb.first);
vector<Complex> left = perturbativeVertex_-> left();
vector<Complex> right = perturbativeVertex_->right();
Complex A1 = 0.5*(left [0]+right[0])*perturbativeVertex_-> norm();
Complex B1 = 0.5*(right[0]- left[0])*perturbativeVertex_-> norm();
complex<InvEnergy> A2 = 0.5*(left [1]+right[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE;
complex<InvEnergy> B2 = 0.5*(right[1]- left[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE;
complex<InvEnergy2> A3 = 0.5*(left [2]+right[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2;
complex<InvEnergy2> B3 = 0.5*(right[2]- left[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2;
complex<Energy> h1(-2.*Qp*A1),h2(2.*Qm*B1);
complex<Energy> h3(-2./r3*Qp*(A1-Qm*Qm/m2*A2));
complex<Energy> h4( 2./r3*Qm*(B1-Qp*Qp/m2*B2));
complex<Energy> h5(ZERO),h6(ZERO);
if(outb.second>ZERO) {
h5 = -2.*r2/r3/m2/m3*Qp*(0.5*(m12-m22-m32)*A1+0.5*Qm*Qm*(m1+m2)*A2
+m12*pcm*pcm*A3);
h6 = 2.*r2/r3/m2/m3*Qm*(0.5*(m12-m22-m32)*B1-0.5*Qp*Qp*(m1-m2)*B2
+m12*pcm*pcm*B3);
}
double me2 = 0.25*real(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+
h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.second);
Energy output = me2*pcm/8./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
ClassDescription<FRVDecayer> FRVDecayer::initFRVDecayer;
// Definition of the static class description member.
void FRVDecayer::Init() {
static ClassDocumentation<FRVDecayer> documentation
("The FRVDecayer class handles the decay of a fermion to "
"a spin-3/2 particle and a vector boson.");
}
diff --git a/Decay/General/FtoFFFDecayer.cc b/Decay/General/FtoFFFDecayer.cc
--- a/Decay/General/FtoFFFDecayer.cc
+++ b/Decay/General/FtoFFFDecayer.cc
@@ -1,305 +1,305 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FtoFFFDecayer class.
//
#include "FtoFFFDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Decay/DecayPhaseSpaceMode.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include <numeric>
using namespace Herwig;
IBPtr FtoFFFDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FtoFFFDecayer::fullclone() const {
return new_ptr(*this);
}
void FtoFFFDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _vec << _ten;
}
void FtoFFFDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _vec >> _ten;
}
ClassDescription<FtoFFFDecayer> FtoFFFDecayer::initFtoFFFDecayer;
// Definition of the static class description member.
void FtoFFFDecayer::Init() {
static ClassDocumentation<FtoFFFDecayer> documentation
("The FtoFFFDecayer class implements the general decay of a fermion to "
"three fermions.");
}
void FtoFFFDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_vec.resize(ndiags);
_ten.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( offshell->CC() ) offshell = offshell->CC();
if(offshell->iSpin() == PDT::Spin0) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in FtoFFFDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in FtoFFFDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractFFTVertexPtr vert1 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.first);
AbstractFFTVertexPtr vert2 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a tensor diagram in FtoFFFDecayer::doinit()"
<< Exception::runerror;
_ten[ix] = make_pair(vert1, vert2);
}
}
}
double FtoFFFDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
const size_t ncf(numberOfFlows());
Energy2 scale(sqr(inpart.mass()));
if(meopt==Initialize) {
SpinorWaveFunction::
calculateWaveFunctions(_inwave.first,_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
_inwave.second.resize(2);
- if(_inwave.first[0].wave().Type() == u_spinortype) {
+ if(_inwave.first[0].wave().Type() == SpinorType::u) {
for(unsigned int ix = 0; ix < 2; ++ix) {
_inwave.second[ix] = _inwave.first[ix].bar();
_inwave.second[ix].conjugate();
}
}
else {
for(unsigned int ix = 0; ix < 2; ++ix) {
_inwave.second[ix] = _inwave.first[ix].bar();
_inwave.first[ix].conjugate();
}
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(inpart.id()<0)
SpinorWaveFunction::constructSpinInfo(_inwave.first,
const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
else
SpinorBarWaveFunction::constructSpinInfo(_inwave.second,
const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
// outgoing particles
for(unsigned int ix = 0; ix < 3; ++ix) {
SpinorWaveFunction::
constructSpinInfo(_outwave[ix].first,decay[ix],Helicity::outgoing,true);
}
}
// outgoing particles
for(unsigned int ix = 0; ix < 3; ++ix) {
SpinorWaveFunction::
calculateWaveFunctions(_outwave[ix].first,decay[ix],Helicity::outgoing);
_outwave[ix].second.resize(2);
- if(_outwave[ix].first[0].wave().Type() == u_spinortype) {
+ if(_outwave[ix].first[0].wave().Type() == SpinorType::u) {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outwave[ix].second[iy] = _outwave[ix].first[iy].bar();
_outwave[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outwave[ix].second[iy] = _outwave[ix].first[iy].bar();
_outwave[ix].second[iy].conjugate();
}
}
}
bool ferm = inpart.id()>0;
vector<Complex> flows(ncf, Complex(0.)),largeflows(ncf, Complex(0.));
static const unsigned int out2[3]={1,0,0},out3[3]={2,2,1};
vector<GeneralDecayMEPtr> mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half)));
vector<GeneralDecayMEPtr> mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half)));
unsigned int ihel[4];
for(ihel[0] = 0; ihel[0] < 2; ++ihel[0]) {
for(ihel[1] = 0; ihel[1] < 2; ++ihel[1]) {
for(ihel[2] = 0; ihel[2] < 2; ++ihel[2]) {
for(ihel[3] = 0; ihel[3] < 2; ++ihel[3]) {
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag=0;
for(vector<TBDiagram>::const_iterator dit=getProcessInfo().begin();
dit!=getProcessInfo().end();++dit) {
if(ichan>=0&&diagramMap()[ichan]!=idiag) {
++idiag;
continue;
}
// the sign from normal ordering
double sign = ferm ? 1. : -1;
// outgoing wavefunction and NO sign
if (dit->channelType==TBDiagram::channel23) sign *= -1.;
else if(dit->channelType==TBDiagram::channel13) sign *= 1.;
else if(dit->channelType==TBDiagram::channel12) sign *= -1.;
else throw Exception()
<< "Unknown diagram type in FtoFFFDecayer::me2()" << Exception::runerror;
// wavefunctions
SpinorWaveFunction w0,w3;
SpinorBarWaveFunction w1,w2;
// incoming wavefunction
if(ferm) {
w0 = _inwave.first [ihel[0]];
w1 = _outwave[dit->channelType].second[ihel[dit->channelType+1]];
}
else {
w0 = _outwave[dit->channelType].first [ihel[dit->channelType+1]];
w1 = _inwave.second[ihel[0]];
}
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
w2 = _outwave[out3[dit->channelType]].second[ihel[out3[dit->channelType]+1]];
w3 = _outwave[out2[dit->channelType]].first [ihel[out2[dit->channelType]+1]];
sign *= -1.;
}
else {
w2 = _outwave[out2[dit->channelType]].second[ihel[out2[dit->channelType]+1]];
w3 = _outwave[out3[dit->channelType]].first [ihel[out3[dit->channelType]+1]];
}
tcPDPtr offshell = dit->intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag(0.);
// intermediate scalar
if (offshell->iSpin() == PDT::Spin0) {
ScalarWaveFunction inters = _sca[idiag].first->
evaluate(scale, widthOption(), offshell, w0, w1);
diag = _sca[idiag].second->evaluate(scale,w3,w2,inters);
}
// intermediate vector
else if(offshell->iSpin() == PDT::Spin1) {
VectorWaveFunction interv = _vec[idiag].first->
evaluate(scale, widthOption(), offshell, w0, w1);
diag = _vec[idiag].second->evaluate(scale,w3,w2,interv);
}
// intermediate tensor
else if(offshell->iSpin() == PDT::Spin2) {
TensorWaveFunction intert = _ten[idiag].first->
evaluate(scale, widthOption(), offshell, w0, w1);
diag = _ten[idiag].second->evaluate(scale,w3,w2,intert);
}
// unknown
else throw Exception()
<< "Unknown intermediate in FtoFFFDecayer::me2()"
<< Exception::runerror;
// apply NO sign
diag *= sign;
// matrix element for the different colour flows
if(ichan<0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
}
// now add the flows to the me2 with appropriate colour factors
for(unsigned int ix = 0; ix < ncf; ++ix) {
(*mes[ix])(ihel[0],ihel[1],ihel[2],ihel[3]) = flows[ix];
(*mel[ix])(ihel[0],ihel[1],ihel[2],ihel[3]) = largeflows[ix];
}
}
}
}
}
double me2(0.);
if(ichan<0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],_rho)).real();
me2 += con;
if(ix==iy) {
con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *=UseRandom::rnd();
for(unsigned int ix=0;ix<pflows.size();++ix) {
if(ptotal<=pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal-=pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
WidthCalculatorBasePtr FtoFFFDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<FtoFFFDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
outgoing()[0]->mass(),outgoing()[1]->mass(),outgoing()[2]->mass(),
relativeError()));
}
diff --git a/Decay/General/FtoFVVDecayer.cc b/Decay/General/FtoFVVDecayer.cc
--- a/Decay/General/FtoFVVDecayer.cc
+++ b/Decay/General/FtoFVVDecayer.cc
@@ -1,397 +1,397 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FtoFVVDecayer class.
//
#include "FtoFVVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Decay/DecayPhaseSpaceMode.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include <numeric>
using namespace Herwig;
IBPtr FtoFVVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FtoFVVDecayer::fullclone() const {
return new_ptr(*this);
}
void FtoFVVDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _fer << _vec << _ten;
}
void FtoFVVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _fer >> _vec >> _ten;
}
ClassDescription<FtoFVVDecayer> FtoFVVDecayer::initFtoFVVDecayer;
// Definition of the static class description member.
void FtoFVVDecayer::Init() {
static ClassDocumentation<FtoFVVDecayer> documentation
("The FtoFVVDecayer class implements the general decay of a fermion to "
"a fermion and a pair of vectors.");
}
void FtoFVVDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_fer.resize(ndiags);
_vec.resize(ndiags);
_ten.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(offshell->iSpin() == PDT::Spin0) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractVVSVertexPtr vert2 = dynamic_ptr_cast<AbstractVVSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in FtoFVVDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1Half) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in FtoFVVDecayer::doinit()"
<< Exception::runerror;
_fer[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractVVVVertexPtr vert2 = dynamic_ptr_cast<AbstractVVVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in FtoFVVDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractFFTVertexPtr vert1 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.first);
AbstractVVTVertexPtr vert2 = dynamic_ptr_cast<AbstractVVTVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a tensor diagram in FtoFVVDecayer::doinit()"
<< Exception::runerror;
_ten[ix] = make_pair(vert1, vert2);
}
}
}
double FtoFVVDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
//Set up wave-functions
bool ferm( inpart.id() > 0 );
if(meopt==Initialize) {
if( ferm ) {
SpinorWaveFunction::
calculateWaveFunctions(_fwave,_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
- if( _fwave[0].wave().Type() != u_spinortype )
+ if( _fwave[0].wave().Type() != SpinorType::u )
_fwave[0].conjugate();
- if( _fwave[1].wave().Type() != u_spinortype )
+ if( _fwave[1].wave().Type() != SpinorType::u )
_fwave[1].conjugate();
}
else {
SpinorBarWaveFunction::
calculateWaveFunctions(_fbwave, _rho, const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
- if( _fbwave[0].wave().Type() != v_spinortype )
+ if( _fbwave[0].wave().Type() != SpinorType::v )
_fbwave[0].conjugate();
- if( _fbwave[1].wave().Type() != v_spinortype )
+ if( _fbwave[1].wave().Type() != SpinorType::v )
_fbwave[1].conjugate();
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm)
SpinorWaveFunction::constructSpinInfo(_fwave,
const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
else
SpinorBarWaveFunction::constructSpinInfo(_fbwave,
const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
int ivec(-1);
// outgoing particles
for(int ix = 0; ix < 3; ++ix) {
tPPtr p = decay[ix];
if( p->dataPtr()->iSpin() == PDT::Spin1Half ) {
if( ferm ) {
SpinorBarWaveFunction::
constructSpinInfo(_fbwave, p, Helicity::outgoing,true);
}
else {
SpinorWaveFunction::
constructSpinInfo(_fwave , p, Helicity::outgoing,true);
}
}
else if( p->dataPtr()->iSpin() == PDT::Spin1 ) {
if( ivec < 0 ) {
ivec = ix;
VectorWaveFunction::
constructSpinInfo(_vwave.first , p, Helicity::outgoing, true, false);
}
else {
VectorWaveFunction::
constructSpinInfo(_vwave.second, p, Helicity::outgoing, true, false);
}
}
}
return 0.;
}
// outgoing, keep track of fermion and first occurrence of vector positions
int isp(-1), ivec(-1);
// outgoing particles
pair<bool,bool> mass = make_pair(false,false);
for(int ix = 0; ix < 3; ++ix) {
tPPtr p = decay[ix];
if( p->dataPtr()->iSpin() == PDT::Spin1Half ) {
isp = ix;
if( ferm ) {
SpinorBarWaveFunction::
calculateWaveFunctions(_fbwave, p, Helicity::outgoing);
- if( _fbwave[0].wave().Type() != u_spinortype )
+ if( _fbwave[0].wave().Type() != SpinorType::u )
_fbwave[0].conjugate();
- if( _fbwave[1].wave().Type() != u_spinortype )
+ if( _fbwave[1].wave().Type() != SpinorType::u )
_fbwave[1].conjugate();
}
else {
SpinorWaveFunction::
calculateWaveFunctions(_fwave, p, Helicity::outgoing);
- if( _fwave[0].wave().Type() != v_spinortype )
+ if( _fwave[0].wave().Type() != SpinorType::v )
_fwave[0].conjugate();
- if( _fwave[1].wave().Type() != v_spinortype )
+ if( _fwave[1].wave().Type() != SpinorType::v )
_fwave[1].conjugate();
}
}
else if( p->dataPtr()->iSpin() == PDT::Spin1 ) {
bool massless = p->id() == ParticleID::gamma || p->id() == ParticleID::g;
if( ivec < 0 ) {
ivec = ix;
VectorWaveFunction::
calculateWaveFunctions(_vwave.first , p, Helicity::outgoing, massless);
mass.first = massless;
}
else {
VectorWaveFunction::
calculateWaveFunctions(_vwave.second, p, Helicity::outgoing, massless);
mass.second = massless;
}
}
}
assert(isp >= 0 && ivec >= 0);
Energy2 scale(sqr(inpart.mass()));
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
const size_t ncf(numberOfFlows());
vector<Complex> flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.));
vector<GeneralDecayMEPtr>
mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,
(isp == 0) ? PDT::Spin1Half : PDT::Spin1,
(isp == 1) ? PDT::Spin1Half : PDT::Spin1,
(isp == 2) ? PDT::Spin1Half : PDT::Spin1)));
vector<GeneralDecayMEPtr>
mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,
(isp == 0) ? PDT::Spin1Half : PDT::Spin1,
(isp == 1) ? PDT::Spin1Half : PDT::Spin1,
(isp == 2) ? PDT::Spin1Half : PDT::Spin1)));
//Helicity calculation
for( unsigned int if1 = 0; if1 < 2; ++if1 ) {
for( unsigned int if2 = 0; if2 < 2; ++if2 ) {
for( unsigned int iv1 = 0; iv1 < 3; ++iv1 ) {
if ( mass.first && iv1 == 1 ) continue;
for( unsigned int iv2 = 0; iv2 < 3; ++iv2 ) {
if ( mass.second && iv2 == 1 ) continue;
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag(0);
for(vector<TBDiagram>::const_iterator dit = getProcessInfo().begin();
dit != getProcessInfo().end(); ++dit) {
// If we are selecting a particular channel
if( ichan >= 0 && diagramMap()[ichan] != idiag ) {
++idiag;
continue;
}
tcPDPtr offshell = (*dit).intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag;
if( offshell->iSpin() == PDT::Spin1Half ) {
// Make sure we connect the correct particles
VectorWaveFunction vw1, vw2;
if( (*dit).channelType == TBDiagram::channel23 ) {
vw1 = _vwave.first[iv1];
vw2 = _vwave.second[iv2];
}
else if( (*dit).channelType == TBDiagram::channel12 ) {
vw1 = _vwave.second[iv2];
vw2 = _vwave.first[iv1];
}
else {
if( ivec < isp ) {
vw1 = _vwave.second[iv2];
vw2 = _vwave.first[iv1];
}
else {
vw1 = _vwave.first[iv1];
vw2 = _vwave.second[iv2];
}
}
if( ferm ) {
SpinorWaveFunction inters =
_fer[idiag].first->evaluate(scale, widthOption(), offshell,
_fwave[if1], vw1);
diag = _fer[idiag].second->evaluate(scale, inters, _fbwave[if2],
vw2);
}
else {
SpinorBarWaveFunction inters =
_fer[idiag].first->evaluate(scale, widthOption(), offshell,
_fbwave[if2], vw1);
diag = _fer[idiag].second->evaluate(scale, _fwave[if1], inters,
vw2);
}
}
else if( offshell->iSpin() == PDT::Spin0 ) {
ScalarWaveFunction inters =
_sca[idiag].first->evaluate(scale, widthOption(), offshell,
_fwave[if1], _fbwave[if2]);
diag = _sca[idiag].second->evaluate(scale, _vwave.first[iv1],
_vwave.second[iv2], inters);
}
else if( offshell->iSpin() == PDT::Spin1 ) {
VectorWaveFunction interv =
_vec[idiag].first->evaluate(scale, widthOption(), offshell,
_fwave[if1], _fbwave[if2]);
diag = _vec[idiag].second->evaluate(scale, _vwave.first[iv1],
_vwave.second[iv2], interv);
}
else if( offshell->iSpin() == PDT::Spin2 ) {
TensorWaveFunction intert =
_ten[idiag].first->evaluate(scale, widthOption(), offshell,
_fwave[if1], _fbwave[if2]);
diag = _ten[idiag].second->evaluate(scale, _vwave.first[iv1],
_vwave.second[iv2], intert);
}
else
throw Exception()
<< "Unknown intermediate in FtoFVVDecayer::me2()"
<< Exception::runerror;
//NO sign
if( !ferm ) diag *= -1;
if(ichan<0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
}// end diagram loop
// now add the flows to the me2
unsigned int h1(if1), h2(if2);
if( !ferm ) swap(h1,h2);
for(unsigned int ix = 0; ix < ncf; ++ix) {
if(isp == 0) {
(*mes[ix])(h1, h2, iv1, iv2) = flows[ix];
(*mel[ix])(h1, h2, iv1, iv2) = largeflows[ix];
}
else if(isp == 1) {
(*mes[ix])(h1, iv1, h2, iv2) = flows[ix];
(*mel[ix])(h1, iv1, h2, iv2) = largeflows[ix];
}
else if(isp == 2) {
(*mes[ix])(h1, iv1, iv2, h2) = flows[ix];
(*mel[ix])(h1, iv1, h2, iv2) = largeflows[ix];
}
}
}//v2
}//v1
}//f2
}//f1
//Finally, work out me2. This depends on whether we are selecting channels
//or not
double me2(0.);
if(ichan<0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],_rho)).real();
me2 += con;
if(ix==iy) {
con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *= UseRandom::rnd();
for(unsigned int ix=0;ix<pflows.size();++ix) {
if(ptotal<=pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal-=pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
WidthCalculatorBasePtr FtoFVVDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<FtoFVVDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
outgoing()[0]->mass(),outgoing()[1]->mass(),
outgoing()[2]->mass(),relativeError()));
}
diff --git a/Decay/General/StoFFFFDecayer.cc b/Decay/General/StoFFFFDecayer.cc
--- a/Decay/General/StoFFFFDecayer.cc
+++ b/Decay/General/StoFFFFDecayer.cc
@@ -1,1306 +1,1306 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the StoFFFFDecayer class.
//
#include "StoFFFFDecayer.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Decay/DecayPhaseSpaceMode.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
#include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include <numeric>
using namespace Herwig;
using namespace ThePEG::Helicity;
namespace {
inline bool isParticle(tPPtr part) {
return part->id()>0 && part->dataPtr()->CC();
}
inline bool isAntiParticle(tPPtr part) {
return part->id()<0 && part->dataPtr()->CC();
}
inline bool isMajorana(tPPtr part) {
return !part->dataPtr()->CC();
}
}
IBPtr StoFFFFDecayer::clone() const {
return new_ptr(*this);
}
IBPtr StoFFFFDecayer::fullclone() const {
return new_ptr(*this);
}
void StoFFFFDecayer::persistentOutput(PersistentOStream & os) const {
os << firstVVS_ << firstVSS_ << firstSSS_ << firstFFS_
<< secondFFV_ << secondFFS_
<< thirdFFV_ << thirdFFS_ << sign_;
}
void StoFFFFDecayer::persistentInput(PersistentIStream & is, int) {
is >> firstVVS_ >> firstVSS_ >> firstSSS_ >> firstFFS_
>> secondFFV_ >> secondFFS_
>> thirdFFV_ >> thirdFFS_ >> sign_;
}
DescribeClass<StoFFFFDecayer,GeneralFourBodyDecayer>
describeStoFFFFDecayer("Herwig::StoFFFFDecayer", "Herwig.so");
void StoFFFFDecayer::Init() {
static ClassDocumentation<StoFFFFDecayer> documentation
("The StoFFFFDecayer class performs the 4-fermion "
"decays of scalar particles in BSM models");
}
void StoFFFFDecayer::doinit() {
GeneralFourBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
firstVVS_ .resize(ndiags);
firstVSS_ .resize(ndiags);
firstSSS_ .resize(ndiags);
firstFFS_ .resize(ndiags);
secondFFV_.resize(ndiags);
secondFFS_.resize(ndiags);
thirdFFV_ .resize(ndiags);
thirdFFS_ .resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
const NBDiagram & current = getProcessInfo()[ix];
// first vertex
firstVVS_[ix] = dynamic_ptr_cast<AbstractVVSVertexPtr>(current.vertex);
firstVSS_[ix] = dynamic_ptr_cast<AbstractVSSVertexPtr>(current.vertex);
firstSSS_[ix] = dynamic_ptr_cast<AbstractSSSVertexPtr>(current.vertex);
firstFFS_[ix] = dynamic_ptr_cast<AbstractFFSVertexPtr>(current.vertex);
// get the other vertices
const NBVertex & second = current.vertices.begin()->second.incoming ?
current.vertices.begin()->second : (++current.vertices.begin())->second;
// get the other vertices
const NBVertex & third = current.vertices.begin()->second.incoming ?
(++current.vertices.begin())->second : (++second.vertices.begin())->second;
// second vertex
secondFFV_[ix] = dynamic_ptr_cast<AbstractFFVVertexPtr>(second.vertex);
secondFFS_[ix] = dynamic_ptr_cast<AbstractFFSVertexPtr>(second.vertex);
// third vertex
thirdFFV_ [ix] = dynamic_ptr_cast<AbstractFFVVertexPtr>(third .vertex);
thirdFFS_ [ix] = dynamic_ptr_cast<AbstractFFSVertexPtr>(third .vertex);
assert( ( firstVVS_[ix] || firstVSS_[ix] ||
firstSSS_[ix] || firstFFS_[ix] ) &&
(secondFFV_[ix] || secondFFS_[ix] ) &&
( thirdFFV_[ix] || thirdFFS_[ix] ));
// NO sign
int order =
current.channelType[0]*1000+current.channelType[1]*100+
current.channelType[2]*10 +current.channelType[3];
switch(order) {
case 1234: case 1342: case 1423:
case 2143: case 2314: case 2431:
case 3124: case 3241: case 3412:
case 4132: case 4213: case 4321:
sign_.push_back( 1.);
break;
case 1243: case 1324: case 1432:
case 2134: case 2341: case 2413:
case 3142: case 3214: case 3421:
case 4123: case 4231: case 4312:
sign_.push_back(-1.);
break;
default:
assert(false);
}
}
}
double StoFFFFDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay, MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming->id() != inpart.id();
// special handling or first/last call
const vector<vector<double> > & cfactors(getColourFactors());
const vector<vector<double> > & nfactors(getLargeNcColourFactors());
const size_t ncf(numberOfFlows());
Energy2 scale(sqr(inpart.mass()));
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(rho_,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
swave_ = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),
Helicity::incoming);
}
// setup spin info when needed
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
// outgoing particles
for(unsigned int ix = 0; ix < 4; ++ix) {
SpinorWaveFunction::
constructSpinInfo(outwave_[ix].first,decay[ix],Helicity::outgoing,true);
}
}
// outgoing particles
for(unsigned int ix = 0; ix < 4; ++ix) {
SpinorWaveFunction::
calculateWaveFunctions(outwave_[ix].first,decay[ix],Helicity::outgoing);
outwave_[ix].second.resize(2);
- if(outwave_[ix].first[0].wave().Type() == u_spinortype) {
+ if(outwave_[ix].first[0].wave().Type() == SpinorType::u) {
for(unsigned int iy = 0; iy < 2; ++iy) {
outwave_[ix].second[iy] = outwave_[ix].first[iy].bar();
outwave_[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
outwave_[ix].second[iy] = outwave_[ix].first[iy].bar();
outwave_[ix].second[iy].conjugate();
}
}
}
// matrix element for the colour flows
vector<Complex> flows(ncf, Complex(0.)),largeflows(ncf, Complex(0.));
vector<GeneralDecayMEPtr> mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0,
PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half)));
vector<GeneralDecayMEPtr> mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0,
PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half)));
// calculate the matrix element
unsigned int ihel[4];
for(ihel[0] = 0; ihel[0] < 2; ++ihel[0]) {
for(ihel[1] = 0; ihel[1] < 2; ++ihel[1]) {
for(ihel[2] = 0; ihel[2] < 2; ++ihel[2]) {
for(ihel[3] = 0; ihel[3] < 2; ++ihel[3]) {
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag=0;
for(vector<NBDiagram>::const_iterator dit=getProcessInfo().begin();
dit!=getProcessInfo().end();++dit) {
if(ichan>=0&&diagramMap()[ichan]!=idiag) {
++idiag;
continue;
}
// location of the particles
int iloc[4];
for(unsigned int ix=0;ix<4;++ix) iloc[ix] = dit->channelType[ix]-1;
// NO sign
double sign = sign_[idiag];
// work out the type of topology
bool topo = dit->vertices.begin()->second.incoming;
const NBVertex & second = topo ?
dit->vertices.begin() ->second :
(++(dit->vertices.begin()))->second;
const NBVertex & third = topo ?
(++(dit-> vertices.begin()))->second :
(++(second.vertices.begin()))->second;
// extract the intermediates
tPDPair inter = make_pair(second.incoming,
third .incoming);
if( inter.second->CC()) inter.second = inter.second->CC();
if(cc&&inter.first ->CC()) inter.first = inter.first ->CC();
if(cc&&inter.second->CC()) inter.second = inter.second->CC();
// value for the diagram
Complex diag(0.);
// first compute the last part of the diagram
VectorWaveFunction offVector2;
ScalarWaveFunction offScalar2;
// intermediate scalar
if(inter.second->iSpin()==PDT::Spin0) {
if( (isAntiParticle(decay[iloc[2]]) || isMajorana(decay[iloc[2]])) &&
(isParticle (decay[iloc[3]]) || isMajorana(decay[iloc[3]])) ) {
sign *= -1.;
offScalar2 = thirdFFS_[idiag]->
evaluate(scale, widthOption(),inter.second,
outwave_[iloc[2]].first [ihel[iloc[2]]],
outwave_[iloc[3]].second[ihel[iloc[3]]]);
}
else {
offScalar2 = thirdFFS_[idiag]->
evaluate(scale, widthOption(),inter.second,
outwave_[iloc[3]].first [ihel[iloc[3]]],
outwave_[iloc[2]].second[ihel[iloc[2]]]);
}
}
// intermediate vector
else if(inter.second->iSpin()==PDT::Spin1) {
if( (isAntiParticle(decay[iloc[2]]) || isMajorana(decay[iloc[2]])) &&
(isParticle(decay[iloc[3]])||isMajorana(decay[iloc[3]]))) {
sign *= -1.;
offVector2 = thirdFFV_[idiag]->
evaluate(scale, widthOption(),inter.second,
outwave_[iloc[2]].first [ihel[iloc[2]]],
outwave_[iloc[3]].second[ihel[iloc[3]]]);
}
else {
offVector2 = thirdFFV_[idiag]->
evaluate(scale, widthOption(),inter.second,
outwave_[iloc[3]].first [ihel[iloc[3]]],
outwave_[iloc[2]].second[ihel[iloc[2]]]);
}
}
// unknown
else
assert(false);
// first topology
if(topo) {
// first intermediate
if(inter.first->CC()) inter.first = inter.first->CC();
VectorWaveFunction offVector1;
ScalarWaveFunction offScalar1;
// intermeidate scalar
if(inter.first->iSpin()==PDT::Spin0) {
if(decay[iloc[0]]->id()<0&&
decay[iloc[1]]->id()>0) {
sign *= -1.;
offScalar1 = secondFFS_[idiag]->
evaluate(scale, widthOption(),inter.first,
outwave_[iloc[0]].first [ihel[iloc[0]]],
outwave_[iloc[1]].second[ihel[iloc[1]]]);
}
else {
offScalar1 = secondFFS_[idiag]->
evaluate(scale, widthOption(),inter.first,
outwave_[iloc[1]].first [ihel[iloc[1]]],
outwave_[iloc[0]].second[ihel[iloc[0]]]);
}
}
// intermediate vector
else if(inter.first->iSpin()==PDT::Spin1) {
if(decay[iloc[0]]->id()<0&&
decay[iloc[1]]->id()>0) {
sign *= -1.;
offVector1 = secondFFV_[idiag]->
evaluate(scale, widthOption(),inter.first,
outwave_[iloc[0]].first [ihel[iloc[0]]],
outwave_[iloc[1]].second[ihel[iloc[1]]]);
}
else {
offVector1 = secondFFV_[idiag]->
evaluate(scale, widthOption(),inter.first,
outwave_[iloc[1]].first [ihel[iloc[1]]],
outwave_[iloc[0]].second[ihel[iloc[0]]]);
}
}
// unknown
else
assert(false);
// put it all together
if(inter.first->iSpin()==PDT::Spin0) {
if(inter.second->iSpin()==PDT::Spin0) {
diag = firstSSS_[idiag]->
evaluate(scale,swave_,offScalar1,offScalar2);
}
else if(inter.second->iSpin()==PDT::Spin1) {
diag = firstVSS_[idiag]->
evaluate(scale,offVector2,offScalar1,swave_);
}
}
else if(inter.first->iSpin()==PDT::Spin1) {
if(inter.second->iSpin()==PDT::Spin0) {
diag = firstVSS_[idiag]->
evaluate(scale,offVector1,offScalar2,swave_);
}
else if(inter.second->iSpin()==PDT::Spin1) {
diag = firstVVS_[idiag]->
evaluate(scale,offVector1,offVector2,swave_);
}
}
}
// second topology
else {
if(((isAntiParticle(decay[iloc[0]]) || isMajorana(decay[iloc[0]]))&&
(isParticle (decay[iloc[1]]) || isMajorana(decay[iloc[1]])))) {
sign *= -1.;
SpinorWaveFunction inters = firstFFS_[idiag]->
evaluate(scale,widthOption(),inter.first,
outwave_[iloc[0]].first [ihel[iloc[0]]],swave_);
if(inter.second->iSpin()==PDT::Spin0) {
diag = secondFFS_[idiag]->
evaluate(scale,inters,outwave_[iloc[1]].second[ihel[iloc[1]]],
offScalar2);
}
else {
diag = secondFFV_[idiag]->
evaluate(scale,inters,outwave_[iloc[1]].second[ihel[iloc[1]]],
offVector2);
}
}
else {
SpinorBarWaveFunction inters = firstFFS_[idiag]->
evaluate(scale,widthOption(),inter.first,
outwave_[iloc[0]].second[ihel[iloc[0]]],swave_);
if(inter.second->iSpin()==PDT::Spin0) {
diag = secondFFS_[idiag]->
evaluate(scale,outwave_[iloc[1]].first [ihel[iloc[1]]],inters,
offScalar2);
}
else {
diag = secondFFV_[idiag]->
evaluate(scale,outwave_[iloc[1]].first [ihel[iloc[1]]],inters,
offVector2);
}
}
}
// apply NO sign
diag *= sign;
// matrix element for the different colour flows
if(ichan<0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
}
// now add the flows to the me2 with appropriate colour factors
for(unsigned int ix = 0; ix < ncf; ++ix) {
(*mes[ix])(0,ihel[0],ihel[1],ihel[2],ihel[3]) = flows[ix];
(*mel[ix])(0,ihel[0],ihel[1],ihel[2],ihel[3]) = largeflows[ix];
}
}
}
}
}
double me2(0.);
if(ichan<0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],rho_)).real();
me2 += con;
if(ix==iy) {
con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],rho_)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *=UseRandom::rnd();
for(unsigned int ix=0;ix<pflows.size();++ix) {
if(ptotal<=pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal-=pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],rho_)).real();
}
// return the matrix element squared
return me2*scale*UnitRemoval::InvE2;
}
// OLD TESTING CODE
// extracted from StandardModel.h
// public:
// virtual void StopCouplings(Energy2 &,tcPDPtr, tcPDPtr,
// double &, double &, double &,
// Complex &, Complex &,
// vector<Complex> &, vector<Complex> &,
// vector<Complex> &,
// vector<Complex> &, vector<Complex> &,
// vector<Complex> &, vector<Complex> &,
// vector<Complex> &, vector<Complex> &,
// vector<vector<Complex> > &, vector<vector<Complex> > &,
// vector<vector<Complex> > &, vector<vector<Complex> > &,
// vector<Complex> &, vector<Complex> &,
// vector<Complex> &, vector<Complex> &,
// double &, double &) {
// assert(false);
// }
// extracted from RunningMass.cc
// if(id==5) return 4.8787783899999999*GeV;
// if(id==15) return 1.7770999999999999*GeV;
// extracted from MSSM.h
// public:
// virtual void StopCouplings(Energy2 &, tcPDPtr, tcPDPtr,
// double & g, double & sw, double & cw,
// Complex & aL, Complex & aR,
// vector<Complex> & cL, vector<Complex> & cR,
// vector<Complex> & d,
// vector<Complex> & bL, vector<Complex> & bR,
// vector<Complex> & kL, vector<Complex> & kR,
// vector<Complex> & fL, vector<Complex> & fR,
// vector<vector<Complex> > & eL, vector<vector<Complex> > & eR,
// vector<vector<Complex> > & gL, vector<vector<Complex> > & gR,
// vector<Complex> & hL, vector<Complex> & hR,
// vector<Complex> & lL, vector<Complex> & lR,
// double & ytop, double & ytau);
// extracted from MSSM.cc
// void MSSM::StopCouplings(Energy2 & scale, tcPDPtr ferm, tcPDPtr anti, double & g, double & sw, double & cw,
// Complex & aL, Complex & aR,
// vector<Complex> & cL, vector<Complex> & cR,
// vector<Complex> & d,
// vector<Complex> & bL, vector<Complex> & bR,
// vector<Complex> & kL, vector<Complex> & kR,
// vector<Complex> & fL, vector<Complex> & fR,
// vector<vector<Complex> > & eL, vector<vector<Complex> > & eR,
// vector<vector<Complex> > & gL, vector<vector<Complex> > & gR,
// vector<Complex> & hL, vector<Complex> & hR,
// vector<Complex> & lL, vector<Complex> & lR,
// double & ytop, double & ytau) {
// MixingMatrixPtr stop = stopMix();
// MixingMatrixPtr sbot = sbottomMix();
// MixingMatrixPtr stau = stauMix();
// MixingMatrixPtr neut = neutralinoMix();
// MixingMatrixPtr vmix = charginoVMix();
// MixingMatrixPtr umix = charginoUMix();
// sw = sqrt( sin2ThetaW());
// cw = sqrt(1.-sin2ThetaW());
// g = sqrt(4.0*Constants::pi*alphaEMMZ()/sin2ThetaW());
// Energy mb = mass(scale,getParticleData(ParticleID::b));
// Energy mt = mass(scale,getParticleData(ParticleID::t));
// Energy mw = getParticleData(ParticleID::Wplus)->mass();
// double tb = tanBeta();
// double sb = tb/sqrt(1 + sqr(tb));
// double cb = sqrt(1 - sqr(sb));
// Complex n1prime = (*neut)(0,0)*cw + (*neut)(0,1)*sw;
// Complex n2prime = (*neut)(0,1)*cw - (*neut)(0,0)*sw;
// double yt = double(mt/mw)/sb/sqrt(2.);
// Complex bracketl = 2./ 3.*sw*( conj(n1prime) - sw*conj(n2prime)/cw );
// Complex bracketr = 2./3.*sw*n1prime - n2prime*(-0.5 + 2./3.*sqr(sw))/cw;
// ytop = mt/tb/mw;
// aL = -yt*conj((*neut)(0,3))*(*stop)(0,0) + sqrt(2.)*(*stop)(0,1)*bracketl;
// aR = -yt* (*neut)(0,3) *(*stop)(0,1) - sqrt(2.)*(*stop)(0,0)*bracketr;
// cL.resize(2); cR.resize(2); d.resize(2.);
// kL.resize(2); kR.resize(2);
// bL.resize(2); bR.resize(2);
// double yb = double(mb/mw)/cb/sqrt(2.);
// bracketl = -1./3.*sw*( conj(n1prime) - sw*conj(n2prime)/cw );
// bracketr = -1./3.*sw*n1prime - n2prime*(0.5 -1./3.*sqr(sw))/cw;
// for(unsigned int k=0;k<2;++k) {
// cL[k] =-yb*conj((*neut)(0,2))*(*sbot)(k,0) + sqrt(2.)*(*sbot)(k,1)*bracketl;
// cR[k] =-yb* (*neut)(0,2) *(*sbot)(k,1) - sqrt(2.)*(*sbot)(k,0)*bracketr;
// d[k] = (*stop)(0,0)*(*sbot)(k,0);
// bL[k] = mb*conj((*umix)(k,1))/sqrt(2.)/mw/cb*(*stop)(0,0);
// bR[k] = -(*vmix)(k,0)*(*stop)(0,0)+mt*(*vmix)(k,1)/sqrt(2.)/mw/sb*(*stop)(0,1);
// kR[k] = - (*neut)(0,3)*conj((*vmix)(k,1))/sqrt(2.)
// + (*neut)(0,1) *conj((*vmix)(k,0));
// kL[k] = conj((*neut)(0,2))* (*umix)(k,1) /sqrt(2.)
// +conj((*neut)(0,1))* (*umix)(k,0) ;
// }
// fL.resize(2); fR.resize(2);
// double qf = ferm->charge()/eplus;
// Energy mf = (abs(ferm->id())<5||(abs(ferm->id())>=11&&abs(ferm->id())<=14)) ? ZERO : mass(scale, ferm);
// Energy ma = (abs(anti->id())<5||(abs(anti->id())>=11&&abs(anti->id())<=14)) ? ZERO : mass(scale, anti);
// fL[0] = 0.;
// fR[0] = - sqrt(2.)*(qf*sw*n1prime - n2prime*(-0.5 + qf*sqr(sw))/cw);
// fL[1] = + sqrt(2.)*qf*sw*( conj(n1prime) - sw*conj(n2prime)/cw );
// fR[1] = 0.;
// eL.resize(2,vector<Complex>(2,0.));
// eR.resize(2,vector<Complex>(2,0.));
// for(unsigned int i=0;i<2;++i) {
// eR[i][0] = ma*conj((*umix)(i,1))/sqrt(2.)/mw/cb;
// eL[i][0] = -(*vmix)(i,0);
// eL[i][1] = 0.;
// eR[i][1] = 0.;
// }
// hL.resize(2); hR.resize(2);
// double ya = double(ma/mw)/cb/sqrt(2.);
// qf =-anti->charge()/eplus;
// bracketl = qf*sw*( conj(n1prime) - sw*conj(n2prime)/cw );
// bracketr = qf*sw*n1prime - n2prime*(0.5 +qf*sqr(sw))/cw;
// if(abs(anti->id())==ParticleID::tauminus) {
// for(unsigned int k=0;k<2;++k) {
// hR[k] =-ya*conj((*neut)(0,2))*(*stau)(k,0) + sqrt(2.)*(*stau)(k,1)*bracketl;
// hL[k] =-ya* (*neut)(0,2) *(*stau)(k,1) - sqrt(2.)*(*stau)(k,0)*bracketr;
// }
// }
// else {
// hR[0] = 0.;
// hL[0] = - sqrt(2.)*bracketr;
// hR[1] = + sqrt(2.)*bracketl;
// hL[1] = 0.;
// }
// gL.resize(2,vector<Complex>(2,0.));
// gR.resize(2,vector<Complex>(2,0.));
// double y = ma/mw/sqrt(2.)/cb;
// ytau = ma/mw*tb;
// for(unsigned int i=0;i<2;++i) {
// if(abs(anti->id())==ParticleID::tauminus) {
// for(unsigned int j=0;j<2;++j) {
// gL[i][j] = 0.;
// gR[i][j] = -(*umix)(i,0)*(*stau)(j,0) + ya*(*stau)(j,1)*(*umix)(i,1);
// }
// }
// else {
// gL[i][0] = 0.;
// gR[i][0] = -(*umix)(i,0);
// gL[i][1] = 0.;
// gR[i][1] = 0.;
// }
// }
// double tw = sw/cw;
// lL.resize(2);
// lR.resize(2);
// for(unsigned int j = 0; j < 2; ++j) {
// lL[j] = -(conj((*neut)(0, 3)*(*vmix)(j,0) + ((*neut)(0,1) + (*neut)(0,0)*tw)*(*vmix)(j,1)/sqrt(2)))*cb;
// lR[j] = -( (*neut)(0, 2)*(*umix)(j,0) - ((*neut)(0,1) + (*neut)(0,0)*tw)*(*umix)(j,1)/sqrt(2) )*sb;
// }
// }
// extracted from SSFFHVertex.cc
// if(particle1->id()!=ParticleID::b) theMassLast.first = theMSSM->mass(q2,particle1);
// if(particle2->id()!=ParticleID::b) theMassLast.second = theMSSM->mass(q2,particle2);
// extracted from FourBodyDecayConstructor.cc
// from createDecayMode
// unsigned int nferm=0;
// tcPDPtr bottom,ferm,anti,chi;
// for(OrderedParticles::const_iterator it=diagrams[0].outgoing.begin();
// it!=diagrams[0].outgoing.end();++it) {
// if((**it).iSpin()==PDT::Spin1Half) ++nferm;
// if(abs((**it).id())==ParticleID::b)
// bottom = *it;
// else if(abs((**it).id())>1000000)
// chi = *it;
// else if((**it).id()<0)
// anti = *it;
// else
// ferm = *it;
// }
// if(!bottom||!chi||!ferm||!anti) return;
// if(ferm->id()-abs(anti->id())!=1) return;
//if(anti->id()!=ParticleID::tauplus) return;
// from decayList
// set<PDPtr> new_particles;
// for(set<PDPtr>::iterator it=particles.begin();it!=particles.end();++it) {
// if((**it).id()==ParticleID::SUSY_t_1) new_particles.insert(*it);
// }
// NBodyDecayConstructorBase::DecayList(new_particles);
// extracted from StoFFFFDecayer.h
// private :
// InvEnergy2 stopMatrixElement(const Particle & inpart,
// const ParticleVector & decay,
// InvEnergy2 me2) const;
// #include "Herwig/Models/StandardModel/StandardModel.h"
// InvEnergy2 StoFFFFDecayer::stopMatrixElement(const Particle & inpart,
// const ParticleVector & decay,
// InvEnergy2 me2) const {
// // extract the momenta and check the process
// bool found[4]={false,false,false,false};
// Lorentz5Momentum pb,pf,pfp,pChi;
// double col = 1.;
// tcPDPtr ferm,anti;
// for(unsigned int ix=0;ix<decay.size();++ix) {
// long id = decay[ix]->id();
// if(id==ParticleID::b) {
// found[0] = true;
// pb = decay[ix]->momentum();
// }
// else if(id==ParticleID::SUSY_chi_10) {
// found[1] = true;
// pChi = decay[ix]->momentum();
// }
// else if(abs(id)%2==0) {
// if(decay[ix]->dataPtr()->coloured()) col = 3.;
// found[2] = true;
// pf = decay[ix]->momentum();
// ferm = decay[ix]->dataPtr();
// }
// else {
// found[3] = true;
// pfp = decay[ix]->momentum();
// anti = decay[ix]->dataPtr();
// }
// }
// // check the process
// if(!found[0]||!found[1]||!found[2]||!found[3]) return ZERO;
// // extract the couplings we need
// HwSMPtr model = dynamic_ptr_cast<HwSMPtr>(generator()->standardModel());
// double sw(0.),cw(0.),g(0.);
// Energy mb = getParticleData(ParticleID::b)->mass();
// Energy mt = getParticleData(ParticleID::t)->mass();
// Energy mChi = getParticleData(ParticleID::SUSY_chi_10)->mass();
// Energy mw = getParticleData(ParticleID::Wplus)->mass();
// Energy mbt[2] = {getParticleData(ParticleID::SUSY_b_1)->mass(),
// getParticleData(ParticleID::SUSY_b_2)->mass()};
// Energy mP[2] = {getParticleData(ParticleID::SUSY_chi_1plus)->mass(),
// getParticleData(ParticleID::SUSY_chi_2plus)->mass()};
// Energy msf[2]={ZERO,ZERO};
// tcPDPtr sf = getParticleData(1000000+abs(ferm->id()));
// msf[0] = sf->mass();
// sf = getParticleData(2000000+abs(ferm->id()));
// msf[1] = sf ? sf->mass() : 1e30*GeV;
// Energy msfp[2]={getParticleData(1000000+abs(anti->id()))->mass(),
// getParticleData(2000000+abs(anti->id()))->mass()};
// Complex aL(0.),aR(0.);
// vector<Complex> cL,cR,d,bL,bR,kL,kR,fL,fR,hL,hR,lL,lR;
// vector<vector<Complex> > eL,eR,gL,gR;
// double ytop,ytau;
// Energy2 scale = sqr(inpart.mass());
// model->StopCouplings(scale,ferm,anti,g,sw,cw,aL,aR,cL,cR,d,bL,bR,kL,kR,fL,fR,eL,eR,gL,gR,hL,hR,
// lL,lR,ytop,ytau);
// // compute the matrix element
// Lorentz5Momentum pw = pf+pfp; pw.rescaleMass();
// Lorentz5Momentum ptop = pw+pb; ptop.rescaleMass();
// Lorentz5Momentum ptt = inpart.momentum();
// Lorentz5Momentum pbt = inpart.momentum()-pw; pbt.rescaleMass();
// Lorentz5Momentum pChiP= inpart.momentum()-pb; pb.rescaleMass();
// Lorentz5Momentum psf = pChi+pf;psf.rescaleMass();
// Lorentz5Momentum psfp = pChi+pfp;psfp.rescaleMass();
// Energy2 ptpt = ptop*ptop;
// Energy2 pChipfp = pChi*pfp;
// Energy2 ptopptop = ptop.m2();
// Energy2 pbpf = pb*pf;
// Energy2 pbpfp = pb*pfp;
// Energy2 ptoppfp = ptop*pfp;
// Energy2 pChipt = pChi*ptop;
// Energy2 pChiptt = pChi*ptt;
// Energy2 pfpfp = pf*pfp;
// Energy2 pChipb = pChi*pb;
// Energy2 pChipf = pChi*pf;
// Energy2 pttptt = ptt.m2();
// Energy2 pbptt = pb*ptt;
// Energy2 pfpptt = pfp*ptt;
// Energy2 pfppt = pfp*ptop;
// Energy2 pfptt = pf*ptt;
// Energy2 ptptt = ptop*ptt;
// Energy2 pfpt = pf*ptop;
// Energy2 pbpt = pb*ptop;
// Energy2 pChiPpChiP=pChiP*pChiP;
// Energy2 pChipChiP=pChi*pChiP;
// Energy2 pbpChiP = pb*pChiP;
// Energy2 pfppChiP = pfp*pChiP;
// Energy2 ptpChiP = ptop*pChiP;
// Energy2 pttpChiP = ptt*pChiP;
// Energy2 pfpChiP = pf*pChiP;
// Energy mf = pf.mass();
// Energy mfp = pfp.mass();
// assert(model);
// InvEnergy2 pTop = 1./(ptop.m2()-sqr(mt));
// InvEnergy2 pW = 1./(pw .m2()-sqr(mw));
// InvEnergy2 pBT[2] = {1./(pbt.m2()-sqr(mbt[0])),1./(pbt.m2()-sqr(mbt[1]))};
// InvEnergy2 pP[2] = {1./(pChiP.m2()-sqr(mP[0])),1./(pChiP.m2()-sqr(mP[1]))};
// InvEnergy2 pSF [2] = {1./(psf .m2()-sqr(msf [0])),1./(psf .m2()-sqr(msf [1]))};
// if(abs(ferm->id())==ParticleID::nu_e||abs(ferm->id())==ParticleID::nu_mu||abs(ferm->id())==ParticleID::nu_tau)
// pSF[1] = ZERO;
// InvEnergy2 pSFP[2] = {1./(psfp.m2()-sqr(msfp[0])),1./(psfp.m2()-sqr(msfp[1]))};
// // top squared
// InvEnergy2 mett = pow(g,6)*sqr(pTop*pW)*
// ( norm(aR) * ( -4.*pChipfp*pbpf*ptopptop + 8.*pChipt*pbpf*ptoppfp ) +
// norm(aL) * ( 4.*pChipfp*pbpf*sqr(mt))
// + real(aL*conj(aR)) * ( - 8*pbpf*ptoppfp*mChi*mt )
// );
// // colour factors
// mett *=col;
// // sbottom squared
// complex<InvEnergy2> mebb(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// mebb += pow(g,6)*d[i]*d[j]*pBT[i]*pBT[j]*sqr(pW)*
// (pChipb*(cR[i]*cR[j]+cL[i]*cL[j])- mChi*mb*(cL[j]*cR[i]+cL[i]*cR[j]))*
// ( - 4*pfpfp*pttptt + 8*pfptt*pfpptt + pfpfp*sqr(mfp) + pfpfp*sqr(mf)
// - 4*pfptt*sqr(mfp) - 4*pfpptt*sqr(mf) + 2*sqr(mf)*sqr(mfp) );
// }
// }
// // colour factors
// mebb *=col;
// // stop sbottom
// complex<InvEnergy2> metb(ZERO);
// for(unsigned int i=0;i<2;++i) {
// metb += pow(g,6)*d[i]*pTop*pBT[i]*sqr(pW)*cR[i]*
// (
// + aR*( - 2*pChipb*pfpfp*ptptt + 2*pChipb*pfpt*
// pfpptt + 2*pChipb*pfptt*pfppt + 2*pChipf*pbpfp*ptptt -
// 2*pChipf*pbpt*pfpptt - 2*pChipf*pbptt*pfppt - 2*pChipfp
// *pbpf*ptptt - 2*pChipfp*pbpt*pfptt + 2*pChipfp*pbptt*
// pfpt + 2*pChipt*pbpf*pfpptt + 2*pChipt*pbpfp*pfptt - 2*
// pChipt*pbptt*pfpfp + 2*pChiptt*pbpf*pfppt - 2*pChiptt*
// pbpfp*pfpt + 2*pChiptt*pbpt*pfpfp)
// + aL*mChi*mt*( - 2*pbpf*pfpptt - 2*pbpfp*pfptt + 2*pbptt*pfpfp ));
// }
// // colour factors
// metb *=col;
// complex<InvEnergy2> mecc(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// mecc += pow(g,6)*pP[i]*pP[j]*sqr(pW)*
// (+ bR[i]*bR[j]*kR[i]*kR[j] * ( 16*pChipb*pChipf*pChipfp + 16*pChipb*pChipf*pfpfp + 16*pChipb*pChipf*sqr(mfp) + 16*pChipf*
// pChipfp*pbpf + 16*pChipf*pbpf*pfpfp + 16*pChipf*pbpf*sqr(mfp) + 8*pChipf*pbpfp*sqr(mfp) - 8*pChipf*pbpfp*sqr(mf) - 16*sqr(pChipf)*pbpfp )
// + bR[i]*bR[j]*kL[i]*kL[j] * ( 8*pChipfp*pbpf*mP[i]*mP[j] )
// + bL[i]*bL[j]*kR[i]*kR[j] * ( 8*pChipf*pbpfp*mP[i]*mP[j] )
// + bL[i]*bL[j]*kL[i]*kL[j] * ( 16*pChipb*pChipf*pChipfp + 16*pChipb*
// pChipfp*pfpfp + 16*pChipb*pChipfp*sqr(mf) + 16*pChipf*
// pChipfp*pbpfp - 8*pChipfp*pbpf*sqr(mfp) + 8*pChipfp*pbpf*
// sqr(mf) + 16*pChipfp*pbpfp*pfpfp + 16*pChipfp*pbpfp*sqr(mf) -
// 16*sqr(pChipfp)*pbpf )
// + mb*bL[j]*bR[i]*kR[i]*kR[j] * ( - 8*pChipf*pChipfp*mP[j] - 8*pChipf*pfpfp*mP[j] - 8*pChipf*sqr(mfp)*mP[j] )
// + mb*bL[j]*bR[i]*kL[i]*kL[j] * ( - 8*pChipf*pChipfp*mP[i] - 8*pChipfp*pfpfp*mP[i] - 8*pChipfp*sqr(mf)*mP[i] )
// + mb*bL[i]*bR[j]*kR[i]*kR[j] * ( - 8*pChipf*pChipfp*mP[i] - 8*pChipf*pfpfp*mP[i] - 8*pChipf*sqr(mfp)*mP[i] )
// + mb*bL[i]*bR[j]*kL[i]*kL[j] * ( - 8*pChipf*pChipfp*mP[j] - 8*pChipfp*pfpfp*mP[j] - 8*pChipfp*sqr(mf)*mP[j] )
// + mChi*bR[i]*bR[j]*kR[i]*kL[j] * ( - 4*pChipb*pfpfp*mP[j] + 4*pChipf*pbpfp*mP[j] - 4*pChipfp*pbpf*mP[j] - 8*pbpf*pfpfp*mP[j] - 4*pbpf*sqr(mfp)*mP[j] + 4*pbpfp*sqr(mf)*mP[j] )
// + mChi*bR[i]*bR[j]*kL[i]*kR[j] * ( - 4*pChipb*pfpfp*mP[i] + 4*pChipf*pbpfp*mP[i] - 4*pChipfp*pbpf*mP[i] - 8*pbpf*pfpfp*mP[i] - 4*
// pbpf*sqr(mfp)*mP[i] + 4*pbpfp*sqr(mf)*mP[i] )
// + mChi*bL[i]*bL[j]*kR[i]*kL[j] * ( - 4*pChipb*pfpfp*mP[i] - 4*pChipf*pbpfp*mP[i] + 4*pChipfp*pbpf*mP[i] + 4*pbpf*sqr(mfp)*mP[i] - 8*pbpfp*pfpfp*mP[i] - 4*pbpfp*sqr(mf)*mP[i] )
// + mChi*bL[i]*bL[j]*kL[i]*kR[j] * ( - 4*pChipb*pfpfp*mP[j] - 4*pChipf*pbpfp*mP[j] + 4*pChipfp*pbpf*mP[j] + 4*pbpf*sqr(mfp)*mP[j] - 8*
// pbpfp*pfpfp*mP[j] - 4*pbpfp*sqr(mf)*mP[j] )
// + mChi*mb*bL[j]*bR[i]*kR[i]*kL[j] * ( 8*pChipf*pfpfp + 8*pChipfp*
// pfpfp + 4*pfpfp*sqr(mfp) + 4*pfpfp*sqr(mf) + 8*sqr(pfpfp) )
// + mChi*mb*bL[j]*bR[i]*kL[i]*kR[j] * ( 4*pfpfp*mP[i]*mP[j] )
// + mChi*mb*bL[i]*bR[j]*kR[i]*kL[j] * ( 4*pfpfp*mP[i]*mP[j] )
// + mChi*mb*bL[i]*bR[j]*kL[i]*kR[j] * ( 8*pChipf*pfpfp + 8*pChipfp*
// pfpfp + 4*pfpfp*sqr(mfp) + 4*pfpfp*sqr(mf) + 8*sqr(pfpfp) )
// + sqr(mChi)*bR[i]*bR[j]*kR[i]*kR[j] * ( - 8*pChipf*pbpfp )
// + sqr(mChi)*bL[i]*bL[j]*kL[i]*kL[j] * ( - 8*pChipfp*pbpf )
// + mChi*sqr(mChi)*mb*bL[j]*bR[i]*kR[i]*kL[j] * ( 4*pfpfp )
// + mChi*sqr(mChi)*mb*bL[i]*bR[j]*kL[i]*kR[j] * ( 4*pfpfp ));
// }
// }
// mecc *=col;
// complex<InvEnergy2> metc(ZERO);
// for(unsigned int j=0;j<2;++j) {
// metc += pow(g,6)*pP[j]*pTop*sqr(pW)/sqrt(2.)*(
// + aR*bR[j]*kR[j] * ( - 8*pChipb*pChipf*pbpfp + 8*pChipb*pChipf*pfpfp - 8*pChipb*
// pChipfp*pbpf - 8*pChipb*pChipfp*sqr(mf) + 8*pChipb*pbpf*pfpfp - 8*pChipb*pbpfp*
// sqr(mf) - 4*pChipb*pfpfp*sqr(mfp) - 4*
// pChipb*pfpfp*sqr(mf) - 8*pChipb*sqr(mf)*sqr(mfp) + 8*sqr(pChipb)*pfpfp + 8*pChipf*pChipfp*
// pbpf + 8*pChipf*pbpf*pbpfp + 16*
// pChipf*pbpf*pfpfp + 16*pChipf*pbpf*sqr(mfp) + 4*pChipf*pbpfp*sqr(mfp) - 4*pChipf*pbpfp*
// sqr(mf) - 8*sqr(pChipf)*pbpfp + 4*pChipfp*
// pbpf*sqr(mfp) - 4*pChipfp*pbpf*sqr(mf) - 8*
// pChipfp*sqr(pbpf) )
// + aR*mb*bL[j]*kR[j] * ( - 4*pChipb*pfpfp*mP[j] - 4*pChipf*pbpfp*mP[j] - 8*pChipf*pfpfp*mP[j]
// - 4*pChipf*sqr(mfp)*mP[j] + 4*pChipfp*
// pbpf*mP[j] + 4*pChipfp*sqr(mf)*mP[j] )
// + aR*sqr(mb)*bR[j]*kR[j] * ( 8*pChipf*pChipfp + 4*pChipf*sqr(mfp) + 4*pChipfp*sqr(mf) )
// + aR*mChi*bR[j]*kL[j] * ( - 8*pbpf*pbpfp*mP[j] - 8*pbpf*pfpfp*mP[j] - 8*pbpf*sqr(mfp)*mP[j] )
// + aR*mChi*mb*bL[j]*kL[j] * ( 8*sqr(mf)*sqr(mfp) + 8*
// pChipf*pbpfp + 8*pChipf*pfpfp + 8*
// pChipf*sqr(mfp) + 8*pbpfp*pfpfp + 8*
// pbpfp*sqr(mf) + 8*pfpfp*sqr(mfp) + 8*pfpfp*
// sqr(mf) + 8*sqr(pfpfp) )
// + aR*sqr(mChi)*bR[j]*kR[j] * ( 8*pbpf*pbpfp + 4
// *pbpf*sqr(mfp) + 4*pbpfp*sqr(mf) )
// + aR*sqr(mChi)*sqr(mb)*bR[j]*kR[j] * ( - 4*pfpfp )
// + aL*mt*bR[j]*kL[j] * ( 8*pChipfp*pbpf*mP[j] )
// + aL*mb*mt*bL[j]*kL[j] * ( - 8*pChipf*pChipfp - 8*pChipfp*pfpfp - 8*pChipfp*sqr(mf) )
// + aL*mChi*mt*bR[j]*kR[j] * ( - 4*pChipb*pfpfp + 4*pChipf*pbpfp - 4*pChipfp*pbpf - 8*pbpf*pfpfp - 4*pbpf*sqr(mfp) + 4*pbpfp*sqr(mf) )
// + aL*mChi*mb*mt*bL[j]*kR[j] * ( 4*pfpfp*mP[j] ));
// }
// metc *= col;
// complex<InvEnergy2> mebc(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// mebc += pow(g,6)*pP[j]*sqr(pW)*d[i]*pBT[i]/sqrt(2.)*
// (+ cR[i]*bR[j]*kR[j] * ( - 8*pChipb*pChipf*pfpptt + 4
// *pChipb*pChipf*sqr(mfp) - 8*pChipb*
// pChipfp*pfptt + 4*pChipb*pChipfp*sqr(mf) + 8*pChipb*pChiptt*pfpfp + 2*pChipb*
// pfpfp*sqr(mfp) + 2*pChipb*pfpfp*sqr(mf) - 4
// *pChipb*pfptt*sqr(mfp) - 4*pChipb*pfpptt*sqr(mf) + 4
// *pChipb*sqr(mf)*sqr(mfp) + 8*pChipf*pbpfp*
// pfptt + 2*pChipf*pbpfp*sqr(mfp) - 2*
// pChipf*pbpfp*sqr(mf) - 8*pChipf*pbptt*pfpfp - 4*pChipf*pbptt*sqr(mfp) - 8*pChipfp*pbpf*
// pfptt - 2*pChipfp*pbpf*sqr(mfp) + 2*
// pChipfp*pbpf*sqr(mf) + 4*pChipfp*pbptt*sqr(mf) + 8*pChiptt*pbpf*pfpfp + 4*pChiptt*pbpf*
// sqr(mfp) - 4*pChiptt*pbpfp*sqr(mf))
// + cL[i]*bL[j]*kL[j] * ( - 8*pChipb*pChipf*pfpptt + 4
// *pChipb*pChipf*sqr(mfp) - 8*pChipb*
// pChipfp*pfptt + 4*pChipb*pChipfp*sqr(mf) + 8*pChipb*pChiptt*pfpfp + 2*pChipb*
// pfpfp*sqr(mfp) + 2*pChipb*pfpfp*sqr(mf) - 4
// *pChipb*pfptt*sqr(mfp) - 4*pChipb*pfpptt*sqr(mf) + 4
// *pChipb*sqr(mf)*sqr(mfp) - 8*pChipf*pbpfp*
// pfpptt + 2*pChipf*pbpfp*sqr(mfp) - 2*
// pChipf*pbpfp*sqr(mf) + 4*pChipf*pbptt*sqr(mfp) + 8*pChipfp*pbpf*pfpptt - 2*pChipfp*pbpf
// *sqr(mfp) + 2*pChipfp*pbpf*sqr(mf) - 8*
// pChipfp*pbptt*pfpfp - 4*pChipfp*pbptt*sqr(mf) - 4*pChiptt*pbpf*sqr(mfp) + 8*pChiptt*
// pbpfp*pfpfp + 4*pChiptt*pbpfp*sqr(mf))
// + mb*cR[i]*bL[j]*kR[j] * ( 4*pChipf*pfpptt*mP[j] - 2*pChipf*sqr(mfp)*mP[j] + 4*pChipfp*pfptt*mP[j]
// - 2*pChipfp*sqr(mf)*mP[j] - 4*pChiptt*pfpfp*mP[j] )
// + mb*cL[i]*bR[j]*kL[j] * ( 4*pChipf*pfpptt*mP[j] - 2*pChipf*sqr(mfp)*mP[j] + 4*pChipfp*pfptt*mP[j]
// - 2*pChipfp*sqr(mf)*mP[j] - 4*pChiptt*pfpfp*mP[j] )
// + mChi*cR[i]*bR[j]*kL[j] * ( - 4*pbpf*pfpptt*mP[j] + 2*pbpf*sqr(mfp)*mP[j] - 4*pbpfp*pfptt*mP[j]
// + 2*pbpfp*sqr(mf)*mP[j] + 4*pbptt*pfpfp*mP[j] )
// + mChi*cL[i]*bL[j]*kR[j] * ( - 4*pbpf*pfpptt*mP[j] + 2*pbpf*sqr(mfp)*mP[j] - 4*pbpfp*pfptt*mP[j] + 2*pbpfp*sqr(mf)*mP[j] + 4*pbptt*pfpfp*mP[j] )
// + mChi*mb*cR[i]*bL[j]*kL[j] * ( - 4*sqr(mf)*sqr(mfp) + 4*pChipf*pfpptt - 2*pChipf*sqr(mfp) + 4*pChipfp*pfptt - 2*pChipfp*sqr(mf) - 4*pChiptt*pfpfp - 2*pfpfp*sqr(mfp) - 2*pfpfp*sqr(mf) + 4*pfptt*sqr(mfp) + 4*pfpptt*sqr(mf) )
// + mChi*mb*cL[i]*bR[j]*kR[j] * ( - 4*sqr(mf)*sqr(mfp) + 4*pChipf*pfpptt - 2*pChipf*sqr(mfp) + 4*pChipfp*pfptt - 2*pChipfp*sqr(mf) - 4*pChiptt*pfpfp - 2*pfpfp*sqr(mfp) - 2*pfpfp*sqr(mf) + 4*pfptt*sqr(mfp) + 4*pfpptt*sqr(mf) )
// + sqr(mChi)*cR[i]*bR[j]*kR[j] * ( 4*pbpf*pfpptt - 2*pbpf*sqr(mfp) + 4*pbpfp*pfptt - 2*pbpfp*sqr(mf) - 4*pbptt*pfpfp )
// + sqr(mChi)*cL[i]*bL[j]*kL[j] * ( 4*pbpf*pfpptt - 2*pbpf*sqr(mfp) + 4*pbpfp*pfptt - 2*pbpfp*sqr(mf) - 4*pbptt*pfpfp ));
// }
// }
// mebc *= col;
// complex<InvEnergy2> meff(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// for(unsigned int k=0;k<2;++k) {
// for(unsigned int l=0;l<2;++l) {
// meff += pow(g,6)*pP[i]*pP[j]*pSF[k]*pSF[l]*pChipf*(fR[k]*fR[l]+fL[k]*fL[l])*
// (
// + ( eR[i][k]*eR[j][l]*bR[i]*bR[j] + eL[i][k]*eL[j][l]*bL[i]*bL[j] )* ( 4.*pbpfp*mP[i]*mP[j] )
// + ( eR[i][k]*eR[j][l]*bL[i]*bL[j] + eL[i][k]*eL[j][l]*bR[i]*bR[j] )* ( - 4*pbpfp*pChiPpChiP +
// 8*pbpChiP*pfppChiP )
// +mb*mP[i]*( eR[i][k]*eR[j][l]*bL[j]*bR[i] + eL[i][k]*eL[j][l]*bL[i]*bR[j] ) * ( - 4*pfppChiP )
// +mb*mP[j]*( eR[i][k]*eR[j][l]*bL[i]*bR[j] + eL[i][k]*eL[j][l]*bL[j]*bR[i] ) * ( - 4*pfppChiP ));
// }
// }
// }
// }
// meff *= col;
// complex<InvEnergy2> mepp(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// for(unsigned int k=0;k<2;++k) {
// for(unsigned int l=0;l<2;++l) {
// mepp += pow(g,6)*pP[i]*pP[j]*pSFP[k]*pSFP[l]*pChipfp*(hR[k]*hR[l]+hL[k]*hL[l])*
// ((gR[i][k]*gR[j][l]*bR[i]*bR[j] + gL[i][k]*gL[j][l]*bL[i]*bL[j]) * ( 4*pbpf*mP[i]*mP[j] ) +
// (gR[i][k]*gR[j][l]*bL[i]*bL[j] + gL[i][k]*gL[j][l]*bR[i]*bR[j]) *
// ( - 4*pbpf*pChiPpChiP + 8*pbpChiP*pfpChiP ));
// }
// }
// }
// }
// mepp *= col;
// complex<InvEnergy2> metf(ZERO);
// for(unsigned int j=0;j<2;++j) {
// for(unsigned int l=0;l<2;++l) {
// metf += pow(g,6)*pTop*pW*pP[j]*pSF[l]*
// (+ aR*eL[j][l]*fR[l]*bR[j] * ( 2*pChipb*pfpfp*ptpChiP - 2*pChipb*pfpt*pfppChiP
// - 2*pChipb*pfpChiP*pfppt - 2*pChipf*pbpfp*ptpChiP
// + 2*pChipf*pbpt*pfppChiP + 2*pChipf*pbpChiP*pfppt
// - 2*pChipfp*pbpf*ptpChiP + 2*pChipfp*pbpt*pfpChiP
// - 2*pChipfp*pbpChiP*pfpt + 2*pChipt*pbpf*pfppChiP
// - 2*pChipt*pbpfp*pfpChiP + 2*pChipt*pbpChiP*pfpfp
// + 2*pChipChiP*pbpf*pfppt + 2*pChipChiP*pbpfp*pfpt
// - 2*pChipChiP*pbpt*pfpfp )
// + aL*mChi*mt*eL[j][l]*fR[l]*bR[j] * ( - 2*pbpf*pfppChiP + 2*pbpfp*pfpChiP - 2*pbpChiP*pfpfp )
// );
// }
// }
// metf *= col;
// // sbottom sfermion interference
// complex<InvEnergy2> mebf(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// for(unsigned int l=0;l<2;++l) {
// mebf += 2.*pow(g,6)*d[i]*pBT[i]*pW*pP[j]*pSF[l]*
// (cR[i]*eL[j][l]*fR[l]*bR[j] * ( pChipb*pfpfp*pttpChiP - pChipb*pfptt*pfppChiP - pChipb*pfpChiP*pfpptt +
// pChipf*pbpfp*pttpChiP - pChipf*pbptt*pfppChiP - pChipf*pbpChiP*pfpptt -
// pChipfp*pbpf*pttpChiP + pChipfp*pbptt*pfpChiP - pChipfp*pbpChiP*pfptt +
// pChiptt*pbpf*pfppChiP - pChiptt*pbpfp*pfpChiP + pChiptt*pbpChiP*pfpfp +
// pChipChiP*pbpf*pfpptt + pChipChiP*pbpfp*pfptt - pChipChiP*pbptt*pfpfp)
// + mChi*mP[j]*cL[i]*eL[j][l]*fR[l]*bL[j] * ( - pbpf*pfpptt - pbpfp*pfptt + pbptt*pfpfp ));
// }
// }
// }
// mebf *= col;
// // chi W sfermion interference
// complex<InvEnergy2> mecf(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// for(unsigned int l=0;l<2;++l) {
// mecf -= pow(g,6)*pP[i]*pW*pP[j]*pSF[l]*eL[j][l]*fR[l]/sqrt(2.)*
// (+ bR[i]*bR[j]*kR[i] * ( 8*pChipf*pbpfp*pChiPpChiP - 16*pChipf*pbpChiP*pfppChiP )
// + bR[i]*bR[j]*kL[i]*mChi*mP[i] * ( 4*pbpf*pfppChiP - 4*pbpfp*pfpChiP + 4*pbpChiP*pfpfp)
// + bL[i]*bL[j]*kR[i]*mP[i]*mP[j] * ( - 8*pChipf*pbpfp )
// + bL[i]*bL[j]*kL[i]*mChi*mP[j] * (-4*pbpf*pfppChiP + 4*pbpfp*pfpChiP + 4*pbpChiP*pfpfp)
// );
// }
// }
// }
// mecf *= col;
// complex<InvEnergy2> mebp(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// for(unsigned int l=0;l<2;++l) {
// mebp += pow(g,6)*d[i]*pBT[i]*pW*pP[j]*pSFP[l]*
// (
// + cL[i]*gR[j][l]*hL[l]*bL[j] *
// ( - 2*pChipb*pfpfp*pttpChiP + 2*pChipb*pfptt*pfppChiP
// + 2*pChipb*pfpChiP*pfpptt + 2*pChipf*pbpfp*pttpChiP
// - 2*pChipf*pbptt*pfppChiP + 2*pChipf*pbpChiP*pfpptt
// - 2*pChipfp*pbpf*pttpChiP + 2*pChipfp*pbptt*pfpChiP
// + 2*pChipfp*pbpChiP*pfptt + 2*pChiptt*pbpf*pfppChiP
// - 2*pChiptt*pbpfp*pfpChiP - 2*pChiptt*pbpChiP*pfpfp
// - 2*pChipChiP*pbpf*pfpptt - 2*pChipChiP*pbpfp*pfptt
// + 2*pChipChiP*pbptt*pfpfp)
// + mChi*cR[i]*gR[j][l]*hL[l]*bR[j]*mP[j] *
// ( 2*pbpf*pfpptt + 2*pbpfp*pfptt - 2*pbptt*pfpfp ));
// }
// }
// }
// mebp *= col;
// // chi W anti sfermion interference
// complex<InvEnergy2> mecp(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// for(unsigned int l=0;l<1;++l) {
// mecp +=pow(g,6)*pP[i]*pW*pP[j]*pSFP[l]/sqrt(2.)*gR[j][l]*hL[l]*
// (
// + bR[i]*bR[j]*kL[i] * ( - 8*pChipfp*pbpf*mP[i]*mP[j] )
// + bL[i]*bL[j]*kL[i] * ( 8*pChipfp*pbpf*pfppChiP + 8*pChipfp*pbpf*pChiPpChiP - 8*pChipfp*pbpfp*pfpChiP - 8*pChipfp*pbpChiP*pfpfp - 16*pChipfp*pbpChiP*pfpChiP)
// + mChi*bR[i]*bR[j]*kR[i]*mP[j]*( 4*pbpf*pfppChiP - 4*pbpfp*pfpChiP + 4*pbpChiP*pfpfp)
// + mChi*bL[i]*bL[j]*kR[i]*mP[i]*( - 4*pbpf*pfppChiP + 8*pbpfp*pfpfp + 4*pbpfp*pfpChiP + 4*pbpChiP*pfpfp));
// }
// }
// }
// mecp *= col;
// // sfermion antisfermion interferences
// complex<InvEnergy2> mefp(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// for(unsigned int k=0;k<1;++k) {
// for(unsigned int l=0;l<2;++l) {
// mefp +=pow(g,6)*pP[i]*pP[j]*pSF[k]*pSFP[l]*fR[k]*gR[j][l]*
// (
// + eR[i][k]*hR[l]*bR[i]*bR[j]*mP[i]*mP[j] *
// ( 2*pChipb*pfpfp - 2*pChipf*pbpfp - 2*pChipfp*pbpf )
// + eR[i][k]*hR[l]*bL[i]*bL[j]*
// ( - 2*pChipb*pfpfp*pChiPpChiP + 2*pChipf*pbpfp*pChiPpChiP
// - 4*pChipf*pbpChiP*pfppChiP + 2*pChipfp*pbpf*pChiPpChiP
// - 4*pChipfp*pbpChiP*pfpChiP + 4*pChipChiP*pbpChiP*pfpfp)
// + eL[i][k]*hL[l]*bL[i]*bL[j]*mChi*mP[i] *
// (-2*pbpf*pfppChiP + 2*pbpfp*pfpChiP + 2*pbpChiP*pfpfp )
// + eL[i][k]*hL[l]*bR[i]*bR[j]*mChi*mP[j] *
// ( 2*pbpf*pfppChiP - 2*pbpfp*pfpChiP + 2*pbpChiP*pfpfp ));
// }
// }
// }
// }
// mefp *= col;
// // top higgs
// Energy mHiggs = getParticleData(ParticleID::Hplus)->mass();
// InvEnergy2 pH = 1./(pw.m2()-sqr(mHiggs));
// InvEnergy2 meht = 0.25*sqr(ytop*ytau)*pow(g,6)*sqr(pTop*pH)*pfpfp*
// ( norm(aR) *sqr(mt)*4*pChipb +
// norm(aL) * ( - 4*pChipb*ptpt + 8*pChipt*pbpt )
// + real(aL*conj(aR)) * mChi*mt * ( - 8*pbpt ));
// // colour factors
// meht *=col;
// // chargino higgs
// complex<InvEnergy2> mehc(ZERO);
// for(unsigned int i=0;i<2;++i) {
// for(unsigned int j=0;j<2;++j) {
// mehc += pow(g,6)*pP[i]*pP[j]*sqr(pH)*sqr(ytau)*pfpfp*
// ( + (bR[i]*bR[j]*lR[i]*lR[j]+bL[i]*bL[j]*lL[i]*lL[j])*mP[i]*mP[j]*2*pChipb
// + (bR[i]*bR[j]*lL[i]*lL[j]+bL[i]*bL[j]*lR[i]*lR[j])*(-2*pChipb*pChiPpChiP+4*pChipChiP*pbpChiP)
// + (bR[i]*bR[j]*lR[i]*lL[j]+bL[i]*bL[j]*lL[i]*lR[j])*mChi*mP[i]*2*pbpChiP
// + (bR[i]*bR[j]*lL[i]*lR[j]+bL[i]*bL[j]*lR[i]*lL[j])*mChi*mP[j]*2*pbpChiP);
// }
// }
// // hehbc =
// // + cR1*d1*bR2*kR2 * ( 2*pChi.pb*pf.pfp*mP2 )
// // + cL1*d1*bL2*kL2 * ( 2*pChi.pb*pf.pfp*mP2 )
// // + mChi*cR1*d1*bR2*kL2 * ( 2*pb.pChiP*pf.pfp )
// // + mChi*cL1*d1*bL2*kR2 * ( 2*pb.pChiP*pf.pfp );
// // InvEnergy2 meTotal = meff.real()+mecc.real()+2.*mecf.real();
// InvEnergy2 meTotal = abs(mehc.real());
// // if(abs(anti->id())==ParticleID::tauminus) {
// // cerr << "testing inter " << (me2-mepp.real()-meff.real())*GeV2 << " " << 2.*mefp.real()*GeV2
// // << " " << 0.5*(me2-mepp.real()-meff.real())/mefp.real() << "\n";
// // cerr << "testing the matrix element " << meTotal*GeV2 << " "
// // << me2*GeV2 << " " << meTotal/me2 << "\n";
// // }
// return meTotal;
// }
// extracted from main diagram loop
// //\todo remove testing
// top
// if(!(abs(inter.first ->id())==ParticleID::t&&
// abs(inter.second->id())==ParticleID::Wplus)) {
// ++idiag;
// continue;
// }
// sbottom
// if(!((abs(inter.first ->id())==ParticleID::SUSY_b_1||
// abs(inter.first ->id())==ParticleID::SUSY_b_2)&&
// abs(inter.second->id())==ParticleID::Wplus)) {
// ++idiag;
// continue;
// }
// chargino W
// if(!((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())==ParticleID::Wplus)) {
// ++idiag;
// continue;
// }
// sneutrino
// if(!((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()<0)) {
// ++idiag;
// continue;
// }
// sneutrino
// if(!((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()<0)) {
// ++idiag;
// continue;
// }
// charged slepton
// if(!((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()>0)) {
// ++idiag;
// continue;
// }
// slepton sneutrino
// if(!((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// abs(inter.second->id())!=ParticleID::Hplus&&
// inter.second->id()>0) &&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// abs(inter.second->id())!=ParticleID::Hplus&&
// inter.second->id()<0)) {
// ++idiag;
// continue;
// }
// chi W and charged slepton
// if(!((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())==ParticleID::Wplus) &&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()>0) ) {
// ++idiag;
// continue;
// }
// chi W and sneutrino
// if(!((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())==ParticleID::Wplus) &&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()<0) ) {
// ++idiag;
// continue;
// }
// top/sbottom interference
// if(!(abs(inter.first ->id())==ParticleID::t&&
// abs(inter.second->id())==ParticleID::Wplus)&&
// !((abs(inter.first ->id())==ParticleID::SUSY_b_1||
// abs(inter.first ->id())==ParticleID::SUSY_b_2)&&
// abs(inter.second->id())==ParticleID::Wplus)) {
// ++idiag;
// continue;
// }
// top chiW interference
// if(!(abs(inter.first ->id())==ParticleID::t&&
// abs(inter.second->id())==ParticleID::Wplus)&&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())==ParticleID::Wplus)) {
// ++idiag;
// continue;
// }
// bottom chiW interference
// if(!((abs(inter.first ->id())==ParticleID::SUSY_b_1||
// abs(inter.first ->id())==ParticleID::SUSY_b_2)&&
// abs(inter.second->id())==ParticleID::Wplus)&&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())==ParticleID::Wplus)) {
// ++idiag;
// continue;
// }
// top charged slepton
// if(!(abs(inter.first ->id())==ParticleID::t&&
// abs(inter.second->id())==ParticleID::Wplus) &&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()>0)) {
// ++idiag;
// continue;
// }
// top sneutrino
// if(!(abs(inter.first ->id())==ParticleID::t&&
// abs(inter.second->id())==ParticleID::Wplus) &&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()<0)) {
// ++idiag;
// continue;
// }
// ~b sneutrino
// if(!((abs(inter.first ->id())==ParticleID::SUSY_b_1||
// abs(inter.first ->id())==ParticleID::SUSY_b_2)&&
// abs(inter.second->id())==ParticleID::Wplus)&&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()<0)) {
// ++idiag;
// continue;
// }
// ~b slepton
// if(!((abs(inter.first ->id())==ParticleID::SUSY_b_1||
// abs(inter.first ->id())==ParticleID::SUSY_b_2)&&
// abs(inter.second->id())==ParticleID::Wplus)&&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())!=ParticleID::Wplus&&
// inter.second->id()>0)) {
// ++idiag;
// continue;
// }
// top H
// if(!(abs(inter.first ->id())==ParticleID::t&&
// abs(inter.second->id())==ParticleID::Hplus)) {
// ++idiag;
// continue;
// }
// sbottom H
// if(!((abs(inter.first ->id())==ParticleID::SUSY_b_1||
// abs(inter.first ->id())==ParticleID::SUSY_b_2)&&
// abs(inter.second->id())==ParticleID::Hplus)) {
// ++idiag;
// continue;
// }
// chargino H
// if(!((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())==ParticleID::Hplus)) {
// ++idiag;
// continue;
// }
// top/sbottom interference
// if(!(abs(inter.first ->id())==ParticleID::t&&
// abs(inter.second->id())==ParticleID::Hplus)&&
// !((abs(inter.first ->id())==ParticleID::SUSY_b_1||
// abs(inter.first ->id())==ParticleID::SUSY_b_2)&&
// abs(inter.second->id())==ParticleID::Hplus)) {
// ++idiag;
// continue;
// }
// top chiH interference
// if(!(abs(inter.first ->id())==ParticleID::t&&
// abs(inter.second->id())==ParticleID::Hplus)&&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())==ParticleID::Hplus)) {
// ++idiag;
// continue;
// }
// bottom chiH interference
// if(!((abs(inter.first ->id())==ParticleID::SUSY_b_1||
// abs(inter.first ->id())==ParticleID::SUSY_b_2)&&
// abs(inter.second->id())==ParticleID::Hplus)&&
// !((abs(inter.first ->id())==ParticleID::SUSY_chi_1plus||
// abs(inter.first ->id())==ParticleID::SUSY_chi_2plus)&&
// abs(inter.second->id())==ParticleID::Hplus)) {
// ++idiag;
// continue;
// }
// all Higgs
// if(abs(inter.second->id())==ParticleID::Hplus) {
// ++idiag;
// continue;
// }
//reomved from end of me2()
//InvEnergy2 output = stopMatrixElement(inpart,decay,me2*UnitRemoval::InvE2);
// return output*scale;
diff --git a/Decay/General/StoFFVDecayer.cc b/Decay/General/StoFFVDecayer.cc
--- a/Decay/General/StoFFVDecayer.cc
+++ b/Decay/General/StoFFVDecayer.cc
@@ -1,328 +1,328 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the StoFFVDecayer class.
//
#include "StoFFVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include <numeric>
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
IBPtr StoFFVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr StoFFVDecayer::fullclone() const {
return new_ptr(*this);
}
void StoFFVDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _fer << _vec;
}
void StoFFVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _fer >> _vec;
}
ClassDescription<StoFFVDecayer> StoFFVDecayer::initStoFFVDecayer;
// Definition of the static class description member.
void StoFFVDecayer::Init() {
static ClassDocumentation<StoFFVDecayer> documentation
("The StoFFVDecayer class implements the general decay of a scalar to "
"a two fermions and a vector.");
}
WidthCalculatorBasePtr StoFFVDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<StoFFVDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
outgoing()[0]->mass(),outgoing()[1]->mass(),
outgoing()[2]->mass(),relativeError()));
}
void StoFFVDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_fer.resize(ndiags);
_vec.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( offshell->CC() ) offshell = offshell->CC();
if(offshell->iSpin() == PDT::Spin0) {
AbstractVSSVertexPtr vert1 = dynamic_ptr_cast<AbstractVSSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in StoFFVDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1Half) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a fermion diagram in StoFFVDecayer::doinit()"
<< Exception::runerror;
_fer[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractVVSVertexPtr vert1 = dynamic_ptr_cast<AbstractVVSVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in StoFFVDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
}
}
double StoFFVDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay, MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
_swave = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),
Helicity::incoming);
}
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
for(unsigned int ix=0;ix<decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin()==PDT::Spin1) {
VectorWaveFunction::constructSpinInfo(_outVector,decay[ix],
Helicity::outgoing,true,false);
}
else {
SpinorWaveFunction::
constructSpinInfo(_outspin[ix].first,decay[ix],Helicity::outgoing,true);
}
}
}
unsigned int ivec(0);
bool massless(false);
for(unsigned int ix = 0; ix < decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin() == PDT::Spin1) {
ivec = ix;
massless = decay[ivec]->mass()==ZERO;
VectorWaveFunction::
calculateWaveFunctions(_outVector, decay[ix], Helicity::outgoing,massless);
}
else {
SpinorWaveFunction::
calculateWaveFunctions(_outspin[ix].first,decay[ix],Helicity::outgoing);
_outspin[ix].second.resize(2);
// Need a ubar and a v spinor
- if(_outspin[ix].first[0].wave().Type() == u_spinortype) {
+ if(_outspin[ix].first[0].wave().Type() == SpinorType::u) {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].second[iy].conjugate();
}
}
}
}
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
Energy2 scale(sqr(inpart.mass()));
const size_t ncf(numberOfFlows());
vector<Complex> flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.));
// setup the DecayMatrixElement
vector<GeneralDecayMEPtr>
mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0,
ivec == 0 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 1 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 2 ? PDT::Spin1 : PDT::Spin1Half)));
vector<GeneralDecayMEPtr>
mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0,
ivec == 0 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 1 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 2 ? PDT::Spin1 : PDT::Spin1Half)));
//the channel possiblities
static const unsigned int out2[3] = {1,0,0}, out3[3] = {2,2,1};
for(unsigned int s1 = 0; s1 < 2; ++s1) {
for(unsigned int s2 = 0; s2 < 2; ++s2) {
for(unsigned int v1 = 0; v1 < 3; ++v1) {
if(massless&&v1==1) ++v1;
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag(0);
for(vector<TBDiagram>::const_iterator dit=getProcessInfo().begin();
dit!=getProcessInfo().end();++dit) {
// channels if selecting
if( ichan >= 0 && diagramMap()[ichan] != idiag ) {
++idiag;
continue;
}
tcPDPtr offshell = dit->intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag;
unsigned int o2(out2[dit->channelType]), o3(out3[dit->channelType]);
double sign = (o3 < o2) ? 1. : -1.;
// intermediate scalar
if(offshell->iSpin() == PDT::Spin0) {
ScalarWaveFunction inters = _sca[idiag].first->
evaluate(scale, widthOption(), offshell, _outVector[v1], _swave);
unsigned int h1(s1),h2(s2);
if(o2 > o3) swap(h1, h2);
if(decay[o2]->id() < 0 && decay[o3]->id() > 0) {
diag = -sign*_sca[idiag].second->
evaluate(scale,_outspin[o2].first[h1],
_outspin[o3].second[h2],inters);
}
else {
diag = sign*_sca[idiag].second->
evaluate(scale, _outspin[o3].first [h2],
_outspin[o2].second[h1],inters);
}
}
// intermediate fermion
else if(offshell->iSpin() == PDT::Spin1Half) {
int iferm = (decay[o2]->dataPtr()->iSpin() == PDT::Spin1Half)
? o2 : o3;
unsigned int h1(s1),h2(s2);
if(dit->channelType > iferm) swap(h1, h2);
sign = iferm < dit->channelType ? 1. : -1.;
if((decay[dit->channelType]->id() < 0 && decay[iferm]->id() > 0 ) ||
(decay[dit->channelType]->id()*offshell->id()>0)) {
SpinorWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].first[h1], _swave);
diag = -sign*_fer[idiag].second->
evaluate(scale,inters,_outspin[iferm].second[h2], _outVector[v1]);
}
else {
SpinorBarWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].second[h1],_swave);
diag = sign*_fer[idiag].second->
evaluate(scale,_outspin[iferm].first [h2],inters, _outVector[v1]);
}
}
// intermediate vector
else if(offshell->iSpin() == PDT::Spin1) {
VectorWaveFunction interv = _vec[idiag].first->
evaluate(scale, widthOption(), offshell, _outVector[v1], _swave);
unsigned int h1(s1),h2(s2);
if(o2 > o3) swap(h1,h2);
if(decay[o2]->id() < 0 && decay[o3]->id() > 0) {
diag =-sign*_vec[idiag].second->
evaluate(scale, _outspin[o2].first[h1],
_outspin[o3].second[h2], interv);
}
else {
diag = sign*_vec[idiag].second->
evaluate(scale, _outspin[o3].first[h2],
_outspin[o2].second[h1], interv);
}
}
// unknown
else throw Exception()
<< "Unknown intermediate in StoFFVDecayer::me2()"
<< Exception::runerror;
// matrix element for the different colour flows
if(ichan < 0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1 != colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
} //end of diagrams
// now add the flows to the me2 with appropriate colour factors
for(unsigned int ix = 0; ix < ncf; ++ix) {
if ( ivec == 0 ) {
(*mes[ix])(0, v1, s1, s2) = flows[ix];
(*mel[ix])(0, v1, s1, s2) = largeflows[ix];
}
else if( ivec == 1 ) {
(*mes[ix])(0, s1, v1, s2) = flows[ix];
(*mel[ix])(0, s1, v1, s2) = largeflows[ix];
}
else if( ivec == 2 ) {
(*mes[ix])(0, s1, s2, v1) = flows[ix];
(*mel[ix])(0, s1, s2, v1) = largeflows[ix];
}
}
}
}
}
double me2(0.);
if(ichan < 0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],_rho)).real();
me2 += con;
if(ix == iy) {
con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *= UseRandom::rnd();
for(unsigned int ix = 0;ix < pflows.size(); ++ix) {
if(ptotal <= pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal -= pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
diff --git a/Decay/General/StoSFFDecayer.cc b/Decay/General/StoSFFDecayer.cc
--- a/Decay/General/StoSFFDecayer.cc
+++ b/Decay/General/StoSFFDecayer.cc
@@ -1,360 +1,360 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the StoSFFDecayer class.
//
#include "StoSFFDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include <numeric>
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
IBPtr StoSFFDecayer::clone() const {
return new_ptr(*this);
}
IBPtr StoSFFDecayer::fullclone() const {
return new_ptr(*this);
}
void StoSFFDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _fer << _vec << _ten;
}
void StoSFFDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _fer >> _vec >> _ten;
}
ClassDescription<StoSFFDecayer> StoSFFDecayer::initStoSFFDecayer;
// Definition of the static class description member.
void StoSFFDecayer::Init() {
static ClassDocumentation<StoSFFDecayer> documentation
("The StoSFFDecayer class implements the general decay of a scalar to "
"a scalar and two fermions.");
}
WidthCalculatorBasePtr StoSFFDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<StoSFFDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
outgoing()[0]->mass(),outgoing()[1]->mass(),outgoing()[2]->mass(),
relativeError()));
}
void StoSFFDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_fer.resize(ndiags);
_vec.resize(ndiags);
_ten.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( offshell->CC() ) offshell = offshell->CC();
if(offshell->iSpin() == PDT::Spin0) {
AbstractSSSVertexPtr vert1 = dynamic_ptr_cast<AbstractSSSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in StoSFFDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1Half) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a fermion diagram in StoSFFDecayer::doinit()"
<< Exception::runerror;
_fer[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractVSSVertexPtr vert1 = dynamic_ptr_cast<AbstractVSSVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in StoSFFDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractSSTVertexPtr vert1 = dynamic_ptr_cast<AbstractSSTVertexPtr>
(current.vertices.first);
AbstractFFTVertexPtr vert2 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a tensor diagram in StoSFFDecayer::doinit()"
<< Exception::runerror;
_ten[ix] = make_pair(vert1, vert2);
}
}
}
double StoSFFDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
_swave = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),
Helicity::incoming);
}
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
for(unsigned int ix=0;ix<decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin()==PDT::Spin0) {
ScalarWaveFunction::constructSpinInfo(decay[ix],Helicity::outgoing,true);
}
else {
SpinorWaveFunction::
constructSpinInfo(_outspin[ix].first,decay[ix],Helicity::outgoing,true);
}
}
return 0.;
}
// get the wavefunctions for all the particles
ScalarWaveFunction outScalar;
unsigned int isca(0);
for(unsigned int ix=0;ix<decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin()==PDT::Spin0) {
isca = ix;
outScalar = ScalarWaveFunction(decay[ix]->momentum(),
decay[ix]->dataPtr(),Helicity::outgoing);
}
else {
SpinorWaveFunction::
calculateWaveFunctions(_outspin[ix].first,decay[ix],Helicity::outgoing);
_outspin[ix].second.resize(2);
- if(_outspin[ix].first[0].wave().Type() == u_spinortype) {
+ if(_outspin[ix].first[0].wave().Type() == SpinorType::u) {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].second[iy].conjugate();
}
}
}
}
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
Energy2 scale(sqr(inpart.mass()));
const size_t ncf(numberOfFlows());
vector<Complex> flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.));
vector<GeneralDecayMEPtr>
mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0,
isca==0 ? PDT::Spin0 : PDT::Spin1Half,
isca==1 ? PDT::Spin0 : PDT::Spin1Half,
isca==2 ? PDT::Spin0 : PDT::Spin1Half)));
vector<GeneralDecayMEPtr>
mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin0,
isca == 0 ? PDT::Spin0 : PDT::Spin1Half,
isca == 1 ? PDT::Spin0 : PDT::Spin1Half,
isca == 2 ? PDT::Spin0 : PDT::Spin1Half)));
static const unsigned int out2[3]={1,0,0},out3[3]={2,2,1};
for(unsigned int s1 = 0;s1 < 2; ++s1) {
for(unsigned int s2 = 0;s2 < 2; ++s2) {
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag(0);
for(vector<TBDiagram>::const_iterator dit = getProcessInfo().begin();
dit != getProcessInfo().end(); ++dit) {
// channels if selecting
if( ichan >= 0 && diagramMap()[ichan] != idiag ) {
++idiag;
continue;
}
tcPDPtr offshell = dit->intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag;
double sign = out3[dit->channelType] < out2[dit->channelType] ? 1. : -1.;
// intermediate scalar
if (offshell->iSpin() == PDT::Spin0) {
ScalarWaveFunction inters = _sca[idiag].first->
evaluate(scale, widthOption(), offshell, _swave, outScalar);
unsigned int h1(s1),h2(s2);
if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2);
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
diag =-sign*_sca[idiag].second->
evaluate(scale,
_outspin[out2[dit->channelType]].first [h1],
_outspin[out3[dit->channelType]].second[h2],inters);
}
else {
diag = sign*_sca[idiag].second->
evaluate(scale,
_outspin[out3[dit->channelType]].first [h2],
_outspin[out2[dit->channelType]].second[h1],inters);
}
}
// intermediate fermion
else if(offshell->iSpin() == PDT::Spin1Half) {
int iferm =
decay[out2[dit->channelType]]->dataPtr()->iSpin()==PDT::Spin1Half
? out2[dit->channelType] : out3[dit->channelType];
unsigned int h1(s1),h2(s2);
if(dit->channelType>iferm) swap(h1,h2);
sign = iferm<dit->channelType ? 1. : -1.;
if((decay[dit->channelType]->id() < 0 &&decay[iferm]->id() > 0 ) ||
(decay[dit->channelType]->id()*offshell->id()>0)) {
SpinorWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].first [h1],_swave);
diag = -sign*_fer[idiag].second->
evaluate(scale,inters,_outspin[iferm].second[h2],outScalar);
}
else {
SpinorBarWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].second[h1],_swave);
diag = sign*_fer[idiag].second->
evaluate(scale,_outspin[iferm].first [h2],inters,outScalar);
}
}
// intermediate vector
else if(offshell->iSpin() == PDT::Spin1) {
VectorWaveFunction interv = _vec[idiag].first->
evaluate(scale, widthOption(), offshell, _swave, outScalar);
unsigned int h1(s1),h2(s2);
if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2);
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
diag =-sign*_vec[idiag].second->
evaluate(scale,
_outspin[out2[dit->channelType]].first [h1],
_outspin[out3[dit->channelType]].second[h2],interv);
}
else {
diag = sign*_vec[idiag].second->
evaluate(scale,
_outspin[out3[dit->channelType]].first [h2],
_outspin[out2[dit->channelType]].second[h1],interv);
}
}
// intermediate tensor
else if(offshell->iSpin() == PDT::Spin2) {
TensorWaveFunction intert = _ten[idiag].first->
evaluate(scale, widthOption(), offshell, _swave, outScalar);
unsigned int h1(s1),h2(s2);
if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2);
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
diag =-sign*_ten[idiag].second->
evaluate(scale,
_outspin[out2[dit->channelType]].first [h1],
_outspin[out3[dit->channelType]].second[h2],intert);
}
else {
diag = sign*_ten[idiag].second->
evaluate(scale,
_outspin[out3[dit->channelType]].first [h2],
_outspin[out2[dit->channelType]].second[h1],intert);
}
}
// unknown
else throw Exception()
<< "Unknown intermediate in StoSFFDecayer::me2()"
<< Exception::runerror;
// matrix element for the different colour flows
if(ichan < 0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1 != colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
}
for(unsigned int ix = 0; ix < ncf; ++ix) {
if(isca == 0) {
(*mes[ix])(0, 0, s1, s2) = flows[ix];
(*mel[ix])(0, 0, s1, s2) = largeflows[ix];
}
else if(isca == 1 ) {
(*mes[ix])(0, s1, 0, s2) = flows[ix];
(*mel[ix])(0, s1, 0, s2) = largeflows[ix];
}
else if(isca == 2) {
(*mes[ix])(0, s1,s2, 0) = flows[ix];
(*mel[ix])(0, s1,s2, 0) = largeflows[ix] ;
}
}
}
}
double me2(0.);
if(ichan < 0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],_rho)).real();
me2 += con;
if(ix == iy) {
con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *= UseRandom::rnd();
for(unsigned int ix = 0;ix < pflows.size(); ++ix) {
if(ptotal <= pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal -= pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
diff --git a/Decay/General/VtoFFVDecayer.cc b/Decay/General/VtoFFVDecayer.cc
--- a/Decay/General/VtoFFVDecayer.cc
+++ b/Decay/General/VtoFFVDecayer.cc
@@ -1,365 +1,365 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VtoFFVDecayer class.
//
#include "VtoFFVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include <numeric>
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
IBPtr VtoFFVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr VtoFFVDecayer::fullclone() const {
return new_ptr(*this);
}
void VtoFFVDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _fer << _vec << _ten;
}
void VtoFFVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _fer >> _vec >> _ten;
}
ClassDescription<VtoFFVDecayer> VtoFFVDecayer::initVtoFFVDecayer;
// Definition of the static class description member.
void VtoFFVDecayer::Init() {
static ClassDocumentation<VtoFFVDecayer> documentation
("The VtoFFVDecayer class implements the general three-body "
"decay of a vector to a two fermions and a vector.");
}
WidthCalculatorBasePtr VtoFFVDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<VtoFFVDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
outgoing()[0]->mass(),outgoing()[1]->mass(),
outgoing()[2]->mass(),relativeError()));
}
void VtoFFVDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_fer.resize(ndiags);
_vec.resize(ndiags);
_ten.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( offshell->CC() ) offshell = offshell->CC();
if(offshell->iSpin() == PDT::Spin0) {
AbstractVVSVertexPtr vert1 = dynamic_ptr_cast<AbstractVVSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in VtoFFVDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1Half) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a fermion diagram in VtoFFVDecayer::doinit()"
<< Exception::runerror;
_fer[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractVVVVertexPtr vert1 = dynamic_ptr_cast<AbstractVVVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in VtoFFVDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractVVTVertexPtr vert1 = dynamic_ptr_cast<AbstractVVTVertexPtr>
(current.vertices.first);
AbstractFFTVertexPtr vert2 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a tensor diagram in VtoFFVDecayer::doinit()"
<< Exception::runerror;
_ten[ix] = make_pair(vert1, vert2);
}
}
}
double VtoFFVDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
if(meopt==Initialize) {
VectorWaveFunction::
calculateWaveFunctions(_inVector,_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,false);
}
if(meopt==Terminate) {
VectorWaveFunction::
constructSpinInfo(_inVector,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true,false);
for(unsigned int ix=0;ix<decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin()==PDT::Spin1) {
VectorWaveFunction::constructSpinInfo(_outVector,decay[ix],
Helicity::outgoing,true,false);
}
else {
SpinorWaveFunction::
constructSpinInfo(_outspin[ix].first,decay[ix],Helicity::outgoing,true);
}
}
}
unsigned int ivec(0);
bool massless = false;
for(unsigned int ix = 0; ix < decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin() == PDT::Spin1) {
massless = decay[ix]->id()==ParticleID::g || decay[ix]->id()==ParticleID::gamma;
ivec = ix;
VectorWaveFunction::
calculateWaveFunctions(_outVector, decay[ix], Helicity::outgoing, massless );
}
else {
SpinorWaveFunction::
calculateWaveFunctions(_outspin[ix].first,decay[ix],Helicity::outgoing);
_outspin[ix].second.resize(2);
// Need a ubar and a v spinor
- if(_outspin[ix].first[0].wave().Type() == u_spinortype) {
+ if(_outspin[ix].first[0].wave().Type() == SpinorType::u) {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].second[iy].conjugate();
}
}
}
}
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
Energy2 scale(sqr(inpart.mass()));
const size_t ncf(numberOfFlows());
vector<Complex> flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.));
// setup the DecayMatrixElement
vector<GeneralDecayMEPtr>
mes(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1,
ivec == 0 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 1 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 2 ? PDT::Spin1 : PDT::Spin1Half)));
vector<GeneralDecayMEPtr>
mel(ncf,new_ptr(GeneralDecayMatrixElement(PDT::Spin1,
ivec == 0 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 1 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 2 ? PDT::Spin1 : PDT::Spin1Half)));
//the channel possiblities
static const unsigned int out2[3] = {1,0,0}, out3[3] = {2,2,1};
for(unsigned int vi = 0; vi < 3; ++vi) {
for(unsigned int s1 = 0; s1 < 2; ++s1) {
for(unsigned int s2 = 0; s2 < 2; ++s2) {
for(unsigned int v1 = 0; v1 < 3; ++v1) {
if ( massless && v1 == 1 ) continue;
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag(0);
for(vector<TBDiagram>::const_iterator dit=getProcessInfo().begin();
dit!=getProcessInfo().end();++dit) {
// channels if selecting
if( ichan >=0 && diagramMap()[ichan] != idiag ) {
++idiag;
continue;
}
tcPDPtr offshell = dit->intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag;
unsigned int o2(out2[dit->channelType]), o3(out3[dit->channelType]);
double sign = (o3 < o2) ? 1. : -1.;
// intermediate scalar
if(offshell->iSpin() == PDT::Spin0) {
ScalarWaveFunction inters = _sca[idiag].first->
evaluate(scale, widthOption(), offshell, _outVector[v1],
_inVector[vi]);
unsigned int h1(s1),h2(s2);
if(o2 > o3) swap(h1, h2);
if(decay[o2]->id() < 0 && decay[o3]->id() > 0) {
diag = -sign*_sca[idiag].second->
evaluate(scale,_outspin[o2].first[h1],
_outspin[o3].second[h2],inters);
}
else {
diag = sign*_sca[idiag].second->
evaluate(scale, _outspin[o3].first [h2],
_outspin[o2].second[h1],inters);
}
}
// intermediate fermion
else if(offshell->iSpin() == PDT::Spin1Half) {
int iferm = (decay[o2]->dataPtr()->iSpin() == PDT::Spin1Half)
? o2 : o3;
unsigned int h1(s1),h2(s2);
if(dit->channelType > iferm) swap(h1, h2);
sign = iferm < dit->channelType ? 1. : -1.;
if(decay[dit->channelType]->id() < 0 && decay[iferm]->id() > 0 ) {
SpinorWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].first[h1], _inVector[vi]);
diag = -sign*_fer[idiag].second->
evaluate(scale,inters,_outspin[iferm].second[h2], _outVector[v1]);
}
else {
SpinorBarWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].second[h1],_inVector[vi]);
diag = sign*_fer[idiag].second->
evaluate(scale,_outspin[iferm].first [h2],inters, _outVector[v1]);
}
}
// intermediate vector
else if(offshell->iSpin() == PDT::Spin1) {
VectorWaveFunction interv = _vec[idiag].first->
evaluate(scale, widthOption(), offshell, _outVector[v1],
_inVector[vi]);
unsigned int h1(s1),h2(s2);
if(o2 > o3) swap(h1,h2);
if(decay[o2]->id() < 0 && decay[o3]->id() > 0) {
diag =-sign*_vec[idiag].second->
evaluate(scale, _outspin[o2].first[h1],
_outspin[o3].second[h2], interv);
}
else {
diag = sign*_vec[idiag].second->
evaluate(scale, _outspin[o3].first[h2],
_outspin[o2].second[h1], interv);
}
}
else if(offshell->iSpin() == PDT::Spin2) {
TensorWaveFunction intert = _ten[idiag].first->
evaluate(scale, widthOption(), offshell, _inVector[vi],
_outVector[v1]);
unsigned int h1(s1),h2(s2);
if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2);
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
diag =-sign*_ten[idiag].second->
evaluate(scale,
_outspin[out2[dit->channelType]].first [h1],
_outspin[out3[dit->channelType]].second[h2],intert);
}
else {
diag = sign*_ten[idiag].second->
evaluate(scale,
_outspin[out3[dit->channelType]].first [h2],
_outspin[out2[dit->channelType]].second[h1],intert);
}
}
// unknown
else throw Exception()
<< "Unknown intermediate in VtoFFVDecayer::me2()"
<< Exception::runerror;
// matrix element for the different colour flows
if(ichan < 0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1 != colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
} //end of diagrams
// now add the flows to the me2 with appropriate colour factors
for(unsigned int ix = 0; ix < ncf; ++ix) {
if (ivec == 0) {
(*mes[ix])(vi, v1, s1, s2) = flows[ix];
(*mel[ix])(vi, v1, s1, s2) = largeflows[ix];
}
else if(ivec == 1) {
(*mes[ix])(vi, s1, v1, s2) = flows[ix];
(*mel[ix])(vi, s1, v1, s2) = largeflows[ix];
}
else if(ivec == 2) {
(*mes[ix])(vi, s1, s2, v1) = flows[ix];
(*mel[ix])(vi, s1, s2, v1) = largeflows[ix];
}
}
}
}
}
}
double me2(0.);
if(ichan < 0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix]->contract(*mes[iy],_rho)).real();
me2 += con;
if(ix == iy) {
con = nfactors[ix][iy]*(mel[ix]->contract(*mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *= UseRandom::rnd();
for(unsigned int ix = 0;ix < pflows.size(); ++ix) {
if(ptotal <= pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal -= pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow]->contract(*mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
diff --git a/Makefile.am b/Makefile.am
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,29 +1,29 @@
SUBDIRS = include \
Utilities PDT Decay PDF Models \
Shower Hadronization MatrixElement \
UnderlyingEvent Analysis Looptools Sampling \
- lib src Doc Contrib Tests
+ API lib src Doc Contrib Tests
EXTRA_DIST = GUIDELINES
## DISTCHECK_CONFIGURE_FLAGS = --enable-debug --with-thepeg=$(THEPEGPATH) --with-gsl=$(GSLPATH)
ACLOCAL_AMFLAGS = -I m4
DISTCLEANFILES = config.herwig
libclean:
find . -name '*.la' -print0 | xargs -0 rm -rf
cd lib && $(MAKE) $(AM_MAKEFLAGS) clean
cd src && $(MAKE) $(AM_MAKEFLAGS) clean
tests:
cd Tests && $(MAKE) $(AM_MAKEFLAGS) tests
## ThePEG registration
unregister:
cd src && $(MAKE) $(AM_MAKEFLAGS) unregister
register:
cd src && $(MAKE) $(AM_MAKEFLAGS) register
diff --git a/MatrixElement/Matchbox/Base/MatchboxMEBase.cc b/MatrixElement/Matchbox/Base/MatchboxMEBase.cc
--- a/MatrixElement/Matchbox/Base/MatchboxMEBase.cc
+++ b/MatrixElement/Matchbox/Base/MatchboxMEBase.cc
@@ -1,1653 +1,1653 @@
// -*- C++ -*-
//
// MatchboxMEBase.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MatchboxMEBase class.
//
#include "MatchboxMEBase.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDF/PDF.h"
#include "ThePEG/PDT/PDT.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Handlers/StdXCombGroup.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h"
#include "Herwig/MatrixElement/Matchbox/Utility/DiagramDrawer.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
#include "Herwig/MatrixElement/Matchbox/Base/MergerBase.h"
-#include "Herwig/Utilities/RunDirectories.h"
+#include "Herwig/API/RunDirectories.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
#include "Herwig/MatrixElement/HardVertex.h"
#include <cctype>
#include <iterator>
using std::ostream_iterator;
using namespace Herwig;
MatchboxMEBase::MatchboxMEBase()
: MEBase(),
theOneLoop(false),
theOneLoopNoBorn(false),
theOneLoopNoLoops(false),
theNoCorrelations(false),
theHavePDFs(false,false), checkedPDFs(false) {}
MatchboxMEBase::~MatchboxMEBase() {}
Ptr<MatchboxFactory>::tptr MatchboxMEBase::factory() const { return theFactory; }
void MatchboxMEBase::factory(Ptr<MatchboxFactory>::tptr f) { theFactory = f; }
Ptr<Tree2toNGenerator>::tptr MatchboxMEBase::diagramGenerator() const { return factory()->diagramGenerator(); }
Ptr<ProcessData>::tptr MatchboxMEBase::processData() const { return factory()->processData(); }
unsigned int MatchboxMEBase::getNLight() const { return factory()->nLight(); }
vector<long> MatchboxMEBase::getNLightJetVec() const { return factory()->nLightJetVec(); }
vector<long> MatchboxMEBase::getNHeavyJetVec() const { return factory()->nHeavyJetVec(); }
vector<long> MatchboxMEBase::getNLightProtonVec() const { return factory()->nLightProtonVec(); }
double MatchboxMEBase::factorizationScaleFactor() const { return factory()->factorizationScaleFactor(); }
double MatchboxMEBase::renormalizationScaleFactor() const { return factory()->renormalizationScaleFactor(); }
bool MatchboxMEBase::fixedCouplings() const { return factory()->fixedCouplings(); }
bool MatchboxMEBase::fixedQEDCouplings() const { return factory()->fixedQEDCouplings(); }
bool MatchboxMEBase::checkPoles() const { return factory()->checkPoles(); }
bool MatchboxMEBase::verbose() const { return factory()->verbose(); }
bool MatchboxMEBase::initVerbose() const { return factory()->initVerbose(); }
void MatchboxMEBase::getDiagrams() const {
if ( diagramGenerator() && processData() ) {
vector<Ptr<Tree2toNDiagram>::ptr> diags;
vector<Ptr<Tree2toNDiagram>::ptr>& res =
processData()->diagramMap()[subProcess().legs];
if ( res.empty() ) {
res = diagramGenerator()->generate(subProcess().legs,orderInAlphaS(),orderInAlphaEW());
}
copy(res.begin(),res.end(),back_inserter(diags));
processData()->fillMassGenerators(subProcess().legs);
if ( diags.empty() )
return;
for (auto const & d : diags )
add(d);
return;
}
throw Exception()
<< "MatchboxMEBase::getDiagrams() expects a Tree2toNGenerator and ProcessData object.\n"
<< "Please check your setup." << Exception::runerror;
}
Selector<MEBase::DiagramIndex>
MatchboxMEBase::diagrams(const DiagramVector & diags) const {
if ( phasespace() ) {
return phasespace()->selectDiagrams(diags);
}
throw Exception()
<< "MatchboxMEBase::diagrams() expects a MatchboxPhasespace object.\n"
<< "Please check your setup." << Exception::runerror;
return Selector<MEBase::DiagramIndex>();
}
Selector<const ColourLines *>
MatchboxMEBase::colourGeometries(tcDiagPtr diag) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->haveColourFlows() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
return matchboxAmplitude()->colourGeometries(diag);
}
}
Ptr<Tree2toNDiagram>::tcptr tdiag =
dynamic_ptr_cast<Ptr<Tree2toNDiagram>::tcptr>(diag);
assert(diag && processData());
vector<ColourLines*>& flows = processData()->colourFlowMap()[tdiag];
if ( flows.empty() ) {
list<list<list<pair<int,bool> > > > cflows =
ColourBasis::colourFlows(tdiag);
for ( auto const & fit : cflows)
flows.push_back(new ColourLines(ColourBasis::cfstring(fit)));
}
Selector<const ColourLines *> res;
for ( auto const & f : flows ) res.insert(1.0,f);
return res;
}
void MatchboxMEBase::constructVertex(tSubProPtr sub, const ColourLines* cl) {
if ( !canFillRhoMatrix() || !factory()->spinCorrelations() )
return;
assert(matchboxAmplitude());
assert(matchboxAmplitude()->colourBasis());
// get the colour structure for the selected colour flow
size_t cStructure =
matchboxAmplitude()->colourBasis()->tensorIdFromFlow(lastXComb().lastDiagram(),cl);
// hard process for processing the spin info
tPVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
vector<PDT::Spin> out;
for ( auto const & p : sub->outgoing() ) {
out.push_back(p->data().iSpin());
hard.push_back(p);
}
// calculate dummy wave functions to fill the spin info
static vector<VectorWaveFunction> dummyPolarizations;
static vector<SpinorWaveFunction> dummySpinors;
static vector<SpinorBarWaveFunction> dummyBarSpinors;
for ( size_t k = 0; k < hard.size(); ++k ) {
if ( hard[k]->data().iSpin() == PDT::Spin1Half ) {
if ( hard[k]->id() > 0 && k > 1 ) {
SpinorBarWaveFunction(dummyBarSpinors,hard[k],
outgoing, true);
} else if ( hard[k]->id() < 0 && k > 1 ) {
SpinorWaveFunction(dummySpinors,hard[k],
outgoing, true);
} else if ( hard[k]->id() > 0 && k < 2 ) {
SpinorWaveFunction(dummySpinors,hard[k],
incoming, false);
} else if ( hard[k]->id() < 0 && k < 2 ) {
SpinorBarWaveFunction(dummyBarSpinors,hard[k],
incoming, false);
}
}
else if ( hard[k]->data().iSpin() == PDT::Spin1 ) {
VectorWaveFunction(dummyPolarizations,hard[k],
k > 1 ? outgoing : incoming,
k > 1 ? true : false,
hard[k]->data().hardProcessMass() == ZERO);
}
else if (hard[k]->data().iSpin() == PDT::Spin0 ) {
ScalarWaveFunction(hard[k],k > 1 ? outgoing : incoming,
k > 1 ? true : false);
}
else
assert(false);
}
// fill the production matrix element
ProductionMatrixElement pMe(mePartonData()[0]->iSpin(),
mePartonData()[1]->iSpin(),
out);
for ( map<vector<int>,CVector>::const_iterator lamp = lastLargeNAmplitudes().begin();
lamp != lastLargeNAmplitudes().end(); ++lamp ) {
vector<unsigned int> pMeHelicities
= matchboxAmplitude()->physicalHelicities(lamp->first);
pMe(pMeHelicities) = lamp->second[cStructure];
}
// set the spin information
HardVertexPtr hardvertex = new_ptr(HardVertex());
hardvertex->ME(pMe);
if ( sub->incoming().first->spinInfo() )
sub->incoming().first->spinInfo()->productionVertex(hardvertex);
if ( sub->incoming().second->spinInfo() )
sub->incoming().second->spinInfo()->productionVertex(hardvertex);
for ( auto const & p : sub->outgoing() )
if ( p->spinInfo() )
p->spinInfo()->productionVertex(hardvertex);
}
unsigned int MatchboxMEBase::orderInAlphaS() const {
return subProcess().orderInAlphaS;
}
unsigned int MatchboxMEBase::orderInAlphaEW() const {
return subProcess().orderInAlphaEW;
}
void MatchboxMEBase::setXComb(tStdXCombPtr xc) {
MEBase::setXComb(xc);
lastMatchboxXComb(xc);
if ( phasespace() )
phasespace()->setXComb(xc);
if ( scaleChoice() )
scaleChoice()->setXComb(xc);
if ( matchboxAmplitude() )
matchboxAmplitude()->setXComb(xc);
if (theMerger){
theMerger->setME(this);
theMerger->setXComb( xc );
}
}
double MatchboxMEBase::generateIncomingPartons(const double* r1, const double* r2) {
// shamelessly stolen from PartonExtractor.cc
Energy2 shmax = lastCuts().sHatMax();
Energy2 shmin = lastCuts().sHatMin();
Energy2 sh = shmin*pow(shmax/shmin, *r1);
double ymax = lastCuts().yHatMax();
double ymin = lastCuts().yHatMin();
double km = log(shmax/shmin);
ymax = min(ymax, log(lastCuts().x1Max()*sqrt(lastS()/sh)));
ymin = max(ymin, -log(lastCuts().x2Max()*sqrt(lastS()/sh)));
double y = ymin + (*r2)*(ymax - ymin);
double x1 = exp(-0.5*log(lastS()/sh) + y);
double x2 = exp(-0.5*log(lastS()/sh) - y);
Lorentz5Momentum P1 = lastParticles().first->momentum();
LorentzMomentum p1 = lightCone((P1.rho() + P1.e())*x1, Energy());
p1.rotateY(P1.theta());
p1.rotateZ(P1.phi());
meMomenta()[0] = p1;
Lorentz5Momentum P2 = lastParticles().second->momentum();
LorentzMomentum p2 = lightCone((P2.rho() + P2.e())*x2, Energy());
p2.rotateY(P2.theta());
p2.rotateZ(P2.phi());
meMomenta()[1] = p2;
lastXCombPtr()->lastX1X2(make_pair(x1,x2));
lastXCombPtr()->lastSHat((meMomenta()[0]+meMomenta()[1]).m2());
return km*(ymax - ymin);
}
bool MatchboxMEBase::generateKinematics(const double * r) {
if ( phasespace() ) {
jacobian(phasespace()->generateKinematics(r,meMomenta()));
if ( jacobian() == 0.0 )
return false;
setScale();
if (theMerger&&!theMerger->generateKinematics(r)){
return false;
}
logGenerateKinematics(r);
assert(lastMatchboxXComb());
if ( nDimAmplitude() > 0 ) {
amplitudeRandomNumbers().resize(nDimAmplitude());
copy(r + nDimPhasespace(),
r + nDimPhasespace() + nDimAmplitude(),
amplitudeRandomNumbers().begin());
}
if ( nDimInsertions() > 0 ) {
insertionRandomNumbers().resize(nDimInsertions());
copy(r + nDimPhasespace() + nDimAmplitude(),
r + nDimPhasespace() + nDimAmplitude() + nDimInsertions(),
insertionRandomNumbers().begin());
}
return true;
}
throw Exception()
<< "MatchboxMEBase::generateKinematics() expects a MatchboxPhasespace object.\n"
<< "Please check your setup." << Exception::runerror;
return false;
}
int MatchboxMEBase::nDim() const {
if ( lastMatchboxXComb() )
return nDimPhasespace() + nDimAmplitude() + nDimInsertions();
int ampAdd = 0;
if ( matchboxAmplitude() ) {
ampAdd = matchboxAmplitude()->nDimAdditional();
}
int insertionAdd = 0;
for ( auto const & v : virtuals() ) {
insertionAdd = max(insertionAdd,v->nDimAdditional());
}
return nDimBorn() + ampAdd + insertionAdd;
}
int MatchboxMEBase::nDimBorn() const {
if ( lastMatchboxXComb() )
return nDimPhasespace();
if ( phasespace() )
return phasespace()->nDim(diagrams().front()->partons());
throw Exception()
<< "MatchboxMEBase::nDim() expects a MatchboxPhasespace object.\n"
<< "Please check your setup." << Exception::runerror;
return 0;
}
void MatchboxMEBase::setScale(Energy2 ren, Energy2 fac) const {
if ( haveX1X2() ) {
lastXCombPtr()->lastSHat((meMomenta()[0]+meMomenta()[1]).m2());
}
Energy2 fcscale = (fac == ZERO) ? factorizationScale() : fac;
Energy2 fscale = fcscale*sqr(factorizationScaleFactor());
Energy2 rscale = (ren == ZERO ? renormalizationScale() : ren)*sqr(renormalizationScaleFactor());
Energy2 ewrscale = renormalizationScaleQED();
lastXCombPtr()->lastScale(fscale);
lastXCombPtr()->lastCentralScale(fcscale);
lastXCombPtr()->lastShowerScale(showerScale());
lastMatchboxXComb()->lastRenormalizationScale(rscale);
if ( !fixedCouplings() ) {
if ( rscale > lastCuts().scaleMin() )
lastXCombPtr()->lastAlphaS(SM().alphaS(rscale));
else
lastXCombPtr()->lastAlphaS(SM().alphaS(lastCuts().scaleMin()));
} else {
lastXCombPtr()->lastAlphaS(SM().alphaS());
}
if ( !fixedQEDCouplings() ) {
lastXCombPtr()->lastAlphaEM(SM().alphaEMME(ewrscale));
} else {
lastXCombPtr()->lastAlphaEM(SM().alphaEMMZ());
}
logSetScale();
}
Energy2 MatchboxMEBase::factorizationScale() const {
if ( scaleChoice() ) {
return scaleChoice()->factorizationScale();
}
throw Exception()
<< "MatchboxMEBase::factorizationScale() expects a MatchboxScaleChoice object.\n"
<< "Please check your setup." << Exception::runerror;
return ZERO;
}
Energy2 MatchboxMEBase::renormalizationScale() const {
if ( scaleChoice() ) {
return scaleChoice()->renormalizationScale();
}
throw Exception()
<< "MatchboxMEBase::renormalizationScale() expects a MatchboxScaleChoice object.\n"
<< "Please check your setup." << Exception::runerror;
return ZERO;
}
Energy2 MatchboxMEBase::renormalizationScaleQED() const {
if ( scaleChoice() ) {
return scaleChoice()->renormalizationScaleQED();
}
return renormalizationScale();
}
Energy2 MatchboxMEBase::showerScale() const {
if ( scaleChoice() ) {
return scaleChoice()->showerScale();
}
throw Exception()
<< "MatchboxMEBase::showerScale() expects a MatchboxScaleChoice object.\n"
<< "Please check your setup." << Exception::runerror;
return ZERO;
}
void MatchboxMEBase::setVetoScales(tSubProPtr) const {}
bool MatchboxMEBase::havePDFWeight1() const {
if ( checkedPDFs )
return theHavePDFs.first;
theHavePDFs.first =
factory()->isIncoming(mePartonData()[0]) &&
lastXCombPtr()->partonBins().first->pdf();
theHavePDFs.second =
factory()->isIncoming(mePartonData()[1]) &&
lastXCombPtr()->partonBins().second->pdf();
checkedPDFs = true;
return theHavePDFs.first;
}
bool MatchboxMEBase::havePDFWeight2() const {
if ( checkedPDFs )
return theHavePDFs.second;
theHavePDFs.first =
factory()->isIncoming(mePartonData()[0]) &&
lastXCombPtr()->partonBins().first->pdf();
theHavePDFs.second =
factory()->isIncoming(mePartonData()[1]) &&
lastXCombPtr()->partonBins().second->pdf();
checkedPDFs = true;
return theHavePDFs.second;
}
void MatchboxMEBase::getPDFWeight(Energy2 factorizationScale) const {
if ( !havePDFWeight1() && !havePDFWeight2() ) {
lastMEPDFWeight(1.0);
logPDFWeight();
return;
}
double w = 1.;
if ( havePDFWeight1() )
w *= pdf1(factorizationScale);
if ( havePDFWeight2() )
w *= pdf2(factorizationScale);
lastMEPDFWeight(w);
logPDFWeight();
}
double MatchboxMEBase::pdf1(Energy2 fscale, double xEx, double xFactor) const {
assert(lastXCombPtr()->partonBins().first->pdf());
if ( xEx < 1. && lastX1()*xFactor >= xEx ) {
return
( ( 1. - lastX1()*xFactor ) / ( 1. - xEx ) ) *
lastXCombPtr()->partonBins().first->pdf()->xfx(lastParticles().first->dataPtr(),
lastPartons().first->dataPtr(),
fscale == ZERO ? lastScale() : fscale,
xEx)/xEx;
}
return lastXCombPtr()->partonBins().first->pdf()->xfx(lastParticles().first->dataPtr(),
lastPartons().first->dataPtr(),
fscale == ZERO ? lastScale() : fscale,
lastX1()*xFactor)/lastX1()/xFactor;
}
double MatchboxMEBase::pdf2(Energy2 fscale, double xEx, double xFactor) const {
assert(lastXCombPtr()->partonBins().second->pdf());
if ( xEx < 1. && lastX2()*xFactor >= xEx ) {
return
( ( 1. - lastX2()*xFactor ) / ( 1. - xEx ) ) *
lastXCombPtr()->partonBins().second->pdf()->xfx(lastParticles().second->dataPtr(),
lastPartons().second->dataPtr(),
fscale == ZERO ? lastScale() : fscale,
xEx)/xEx;
}
return lastXCombPtr()->partonBins().second->pdf()->xfx(lastParticles().second->dataPtr(),
lastPartons().second->dataPtr(),
fscale == ZERO ? lastScale() : fscale,
lastX2()*xFactor)/lastX2()/xFactor;
}
double MatchboxMEBase::me2() const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->me2()*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::me2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::runerror;
return 0.;
}
double MatchboxMEBase::largeNME2(Ptr<ColourBasis>::tptr largeNBasis) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() ) {
largeNBasis->prepare(mePartonData(),false);
matchboxAmplitude()->prepareAmplitudes(this);
}
double res =
matchboxAmplitude()->largeNME2(largeNBasis)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::largeNME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::runerror;
return 0.;
}
double MatchboxMEBase::finalStateSymmetry() const {
if ( symmetryFactor() > 0.0 )
return symmetryFactor();
double sFactor = 1.;
map<long,int> counts;
cPDVector checkData;
copy(mePartonData().begin()+2,mePartonData().end(),back_inserter(checkData));
cPDVector::iterator p = checkData.begin();
while ( !checkData.empty() ) {
if ( counts.find((**p).id()) != counts.end() ) {
counts[(**p).id()] += 1;
} else {
counts[(**p).id()] = 1;
}
checkData.erase(p);
p = checkData.begin();
continue;
}
for ( auto const & c : counts) {
if ( c.second == 1 )
continue;
if ( c.second == 2 )
sFactor /= 2.;
else if ( c.second == 3 )
sFactor /= 6.;
else if ( c.second == 4 )
sFactor /= 24.;
}
symmetryFactor(sFactor);
return symmetryFactor();
}
double MatchboxMEBase::me2Norm(unsigned int addAlphaS) const {
// assume that we always have incoming
// spin-1/2 or massless spin-1 particles
double fac = 1./4.;
if ( hasInitialAverage() )
fac = 1.;
double couplings = 1.0;
if ( (orderInAlphaS() > 0 || addAlphaS != 0) && !hasRunningAlphaS() ) {
fac *= pow(lastAlphaS()/SM().alphaS(),double(orderInAlphaS()+addAlphaS));
couplings *= pow(lastAlphaS(),double(orderInAlphaS()+addAlphaS));
}
if ( orderInAlphaEW() > 0 && !hasRunningAlphaEW() ) {
fac *= pow(lastAlphaEM()/SM().alphaEMMZ(),double(orderInAlphaEW()));
couplings *= pow(lastAlphaEM(),double(orderInAlphaEW()));
}
lastMECouplings(couplings);
if ( !hasInitialAverage() ) {
if ( mePartonData()[0]->iColour() == PDT::Colour3 ||
mePartonData()[0]->iColour() == PDT::Colour3bar )
fac /= SM().Nc();
else if ( mePartonData()[0]->iColour() == PDT::Colour8 )
fac /= (SM().Nc()*SM().Nc()-1.);
if ( mePartonData()[1]->iColour() == PDT::Colour3 ||
mePartonData()[1]->iColour() == PDT::Colour3bar )
fac /= SM().Nc();
else if ( mePartonData()[1]->iColour() == PDT::Colour8 )
fac /= (SM().Nc()*SM().Nc()-1.);
}
return !hasFinalStateSymmetry() ? finalStateSymmetry()*fac : fac;
}
CrossSection MatchboxMEBase::prefactor()const{
return (sqr(hbarc)/(2.*lastSHat())) *jacobian()* lastMEPDFWeight();
}
CrossSection MatchboxMEBase::dSigHatDRB() const {
getPDFWeight();
lastME2(me2());
return oneLoopNoBorn()?ZERO:prefactor() * lastME2();
}
CrossSection MatchboxMEBase::dSigHatDRV() const {
getPDFWeight();
lastME2(me2());
return ( oneLoop() && !oneLoopNoLoops() )?(prefactor() * oneLoopInterference()):ZERO;
}
CrossSection MatchboxMEBase::dSigHatDRI() const {
getPDFWeight();
lastME2(me2());
CrossSection res=ZERO;
if (oneLoop() &&!onlyOneLoop()) {
for ( auto const & v : virtuals()) {
v->setXComb(lastXCombPtr());
res += v->dSigHatDR();
}
if ( checkPoles() && oneLoop() )
logPoles();
}
return res;
}
CrossSection MatchboxMEBase::dSigHatDRAlphaDiff(double alpha) const {
getPDFWeight();
lastME2(me2());
CrossSection res=ZERO;
for ( auto const & v: virtuals() ) {
v->setXComb(lastXCombPtr());
res+=v->dSigHatDRAlphaDiff( alpha);
}
return res;
}
CrossSection MatchboxMEBase::dSigHatDR() const {
getPDFWeight();
if (theMerger){
lastMECrossSection(theMerger->MergingDSigDR());
return lastMECrossSection();
}else if (lastXCombPtr()->willPassCuts() ) {
lastMECrossSection(dSigHatDRB()+
dSigHatDRV()+
dSigHatDRI());
return lastMECrossSection();
}
lastME2(ZERO);
lastMECrossSection(ZERO);
return lastMECrossSection();
}
double MatchboxMEBase::oneLoopInterference() const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->oneLoopAmplitudes() )
matchboxAmplitude()->prepareOneLoopAmplitudes(this);
double res =
matchboxAmplitude()->oneLoopInterference()*
me2Norm(1);
return res;
}
throw Exception()
<< "MatchboxMEBase::oneLoopInterference() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::runerror;
return 0.;
}
MatchboxMEBase::AccuracyHistogram::AccuracyHistogram(double low,
double up,
unsigned int nbins)
: lower(low), upper(up),
sameSign(0), oppositeSign(0), nans(0),
overflow(0), underflow(0) {
double step = (up-low)/nbins;
for ( unsigned int k = 1; k <= nbins; ++k )
bins[lower + k*step] = 0.0;
}
void MatchboxMEBase::AccuracyHistogram::book(double a, double b) {
if ( ! (isfinite(a) && isfinite(b)) ) {
++nans;
return;
}
if ( a*b >= 0. )
++sameSign;
if ( a*b < 0. )
++oppositeSign;
double r = 1.;
if ( abs(a) != 0.0 )
r = abs(1.-abs(b/a));
else if ( abs(b) != 0.0 )
r = abs(b);
if ( log10(r) < lower || r == 0.0 ) {
++underflow;
return;
}
if ( log10(r) > upper ) {
++overflow;
return;
}
map<double,double>::iterator bin =
bins.upper_bound(log10(r));
if ( bin == bins.end() )
return;
bin->second += 1.;
}
void MatchboxMEBase::AccuracyHistogram::dump(const std::string& folder, const std::string& prefix,
const cPDVector& proc) const {
ostringstream fname("");
for ( cPDVector::const_iterator p = proc.begin();
p != proc.end(); ++p )
fname << (**p).PDGName();
ofstream out((folder+"/"+prefix+fname.str()+".dat").c_str());
out << "# same sign : " << sameSign << " opposite sign : "
<< oppositeSign << " nans : " << nans
<< " overflow : " << overflow
<< " underflow : " << underflow << "\n";
for ( map<double,double>::const_iterator b = bins.begin();
b != bins.end(); ++b ) {
map<double,double>::const_iterator bp = b; --bp;
if ( b->second != 0. ) {
if ( b != bins.begin() )
out << bp->first;
else
out << lower;
out << " " << b->first
<< " " << b->second
<< "\n" << flush;
}
}
ofstream gpout((folder+"/"+prefix+fname.str()+".gp").c_str());
gpout << "set terminal png\n"
<< "set xlabel 'accuracy of pole cancellation [decimal places]'\n"
<< "set ylabel 'counts\n"
<< "set xrange [-20:0]\n"
<< "set output '" << prefix << fname.str() << ".png'\n"
<< "plot '" << prefix << fname.str() << ".dat' using (0.5*($1+$2)):3 with linespoints pt 7 ps 1 not";
}
void MatchboxMEBase::AccuracyHistogram::persistentOutput(PersistentOStream& os) const {
os << lower << upper << bins
<< sameSign << oppositeSign << nans
<< overflow << underflow;
}
void MatchboxMEBase::AccuracyHistogram::persistentInput(PersistentIStream& is) {
is >> lower >> upper >> bins
>> sameSign >> oppositeSign >> nans
>> overflow >> underflow;
}
void MatchboxMEBase::logPoles() const {
double res2me = oneLoopDoublePole();
double res1me = oneLoopSinglePole();
double res2i = 0.;
double res1i = 0.;
for ( auto const & v : virtuals()) {
res2i += v->oneLoopDoublePole();
res1i += v->oneLoopSinglePole();
}
if (res2me != 0.0 || res2i != 0.0) epsilonSquarePoleHistograms[mePartonData()].book(res2me,res2i);
if (res1me != 0.0 || res1i != 0.0) epsilonPoleHistograms[mePartonData()].book(res1me,res1i);
}
bool MatchboxMEBase::haveOneLoop() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->haveOneLoop();
return false;
}
bool MatchboxMEBase::onlyOneLoop() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->onlyOneLoop();
return false;
}
bool MatchboxMEBase::isDRbar() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isDRbar();
return false;
}
bool MatchboxMEBase::isDR() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isDR();
return false;
}
bool MatchboxMEBase::isCS() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isCS();
return false;
}
bool MatchboxMEBase::isBDK() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isBDK();
return false;
}
bool MatchboxMEBase::isExpanded() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isExpanded();
return false;
}
Energy2 MatchboxMEBase::mu2() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->mu2();
return 0*GeV2;
}
double MatchboxMEBase::oneLoopDoublePole() const {
if ( matchboxAmplitude() ) {
return
matchboxAmplitude()->oneLoopDoublePole()*
me2Norm(1);
}
return 0.;
}
double MatchboxMEBase::oneLoopSinglePole() const {
if ( matchboxAmplitude() ) {
return
matchboxAmplitude()->oneLoopSinglePole()*
me2Norm(1);
}
return 0.;
}
vector<SubtractionDipolePtr>
MatchboxMEBase::getDipoles(const vector<SubtractionDipolePtr>& dipoles,
const vector<MatchboxMEBasePtr> & borns,bool slim) const {
vector<SubtractionDipolePtr> res;
// keep track of the dipoles we already did set up
set<pair<pair<pair<int,int>,int>,pair<Ptr<MatchboxMEBase>::tptr,Ptr<SubtractionDipole>::tptr> > > done;
cPDVector rep = diagrams().front()->partons();
int nreal = rep.size();
// now loop over configs
for ( int emitter = 0; emitter < nreal; ++emitter ) {
list<SubtractionDipolePtr> matchDipoles;
for ( auto const & d : dipoles ) {
if ( ! d->canHandleEmitter(rep,emitter) )
continue;
matchDipoles.push_back(d);
}
if ( matchDipoles.empty() )
continue;
for ( int emission = 2; emission < nreal; ++emission ) {
if ( emission == emitter )
continue;
list<SubtractionDipolePtr> matchDipoles2;
for ( auto const & d : matchDipoles ) {
if ( !d->canHandleSplitting(rep,emitter,emission) )
continue;
matchDipoles2.push_back(d);
}
if ( matchDipoles2.empty() )
continue;
map<Ptr<DiagramBase>::ptr,SubtractionDipole::MergeInfo> mergeInfo;
for ( auto const & d : diagrams() ) {
Ptr<Tree2toNDiagram>::ptr check =
new_ptr(Tree2toNDiagram(*dynamic_ptr_cast<Ptr<Tree2toNDiagram>::ptr>(d)));
map<int,int> theMergeLegs;
for ( unsigned int i = 0; i < check->external().size(); ++i )
theMergeLegs[i] = -1;
int theEmitter = check->mergeEmission(emitter,emission,theMergeLegs);
// no underlying Born
if ( theEmitter == -1 )
continue;
SubtractionDipole::MergeInfo info;
info.diagram = check;
info.emitter = theEmitter;
info.mergeLegs = theMergeLegs;
mergeInfo[d] = info;
}
if ( mergeInfo.empty() )
continue;
for ( int spectator = 0; spectator < nreal; ++spectator ) {
if ( spectator == emitter || spectator == emission )
continue;
list<SubtractionDipolePtr> matchDipoles3;
for ( auto const & d : matchDipoles2 ) {
if ( ! d->canHandleSpectator(rep,spectator) )
continue;
matchDipoles3.push_back(d);
}
if ( matchDipoles3.empty() )
continue;
if ( noDipole(emitter,emission,spectator) )
continue;
for ( auto const & d : matchDipoles3 ) {
if ( !d->canHandle(rep,emitter,emission,spectator) )
continue;
for ( auto const & b : borns ) {
if ( b->onlyOneLoop() )
continue;
if ( done.find(make_pair(make_pair(make_pair(emitter,emission),spectator),make_pair(b,d)))
!= done.end() )
continue;
// now get to work
d->clearBookkeeping();
d->factory(factory());
d->realEmitter(emitter);
d->realEmission(emission);
d->realSpectator(spectator);
d->realEmissionME(const_cast<MatchboxMEBase*>(this));
d->underlyingBornME(b);
d->setupBookkeeping(mergeInfo,slim);
if ( ! d->empty() ) {
res.push_back( d->cloneMe() );
Ptr<SubtractionDipole>::tptr nDipole = res.back();
done.insert(make_pair(make_pair(make_pair(emitter,emission),spectator),make_pair(b,d)));
if ( nDipole->isSymmetric() )
done.insert(make_pair(make_pair(make_pair(emission,emitter),spectator),make_pair(b,d)));
ostringstream dname;
if ( theMerger) {
dname << fullName();
if (theOneLoopNoBorn) dname << ".virtual" << "." ;
dname << b->name() << "."
<< d->name() << ".[("
<< emitter << "," << emission << ")," << spectator << "]";
} else {
dname << fullName() << "." << b->name() << "."
<< d->name() << ".[("
<< emitter << "," << emission << ")," << spectator << "]";
}
if ( ! (generator()->preinitRegister(nDipole,dname.str()) ) )
throw Exception() << "MatchboxMEBase::getDipoles(): Dipole " << dname.str() << " already existing." << Exception::runerror;
if ( !factory()->reweighters().empty() ) {
for ( auto const & rw : factory()->reweighters())
nDipole->addReweighter(rw);
}
if ( !factory()->preweighters().empty() ) {
for ( auto const & rw : factory()->preweighters() )
nDipole->addPreweighter(rw);
}
nDipole->cloneDependencies(dname.str(),slim);
}
}
}
}
}
}
vector<Ptr<SubtractionDipole>::tptr> partners;
copy(res.begin(),res.end(),back_inserter(partners));
for ( auto const & d : res )
d->partnerDipoles(partners);
return res;
}
double MatchboxMEBase::colourCorrelatedME2(pair<int,int> ij) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->colourCorrelatedME2(ij)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::colourCorrelatedME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::runerror;
return 0.;
}
double MatchboxMEBase::largeNColourCorrelatedME2(pair<int,int> ij,
Ptr<ColourBasis>::tptr largeNBasis) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() ) {
largeNBasis->prepare(mePartonData(),false);
matchboxAmplitude()->prepareAmplitudes(this);
}
double res =
matchboxAmplitude()->largeNColourCorrelatedME2(ij,largeNBasis)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::largeNColourCorrelatedME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::runerror;
return 0.;
}
double MatchboxMEBase::spinColourCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->spinColourCorrelatedME2(ij,c)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::spinColourCorrelatedME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::runerror;
return 0.;
}
double MatchboxMEBase::spinCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->spinCorrelatedME2(ij,c)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::spinCorrelatedME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::runerror;
return 0.;
}
void MatchboxMEBase::flushCaches() {
MEBase::flushCaches();
if ( matchboxAmplitude() )
matchboxAmplitude()->flushCaches();
for ( auto const & r : reweights() )
r->flushCaches();
for ( auto const & v : virtuals())
v->flushCaches();
// The Merger cache is flushed in
// generateKinematics
}
void MatchboxMEBase::setKinematics() {
MEBase::setKinematics();
if ( theMerger )
theMerger->setKinematics();
}
void MatchboxMEBase::clearKinematics() {
MEBase::clearKinematics();
if ( theMerger )
theMerger->clearKinematics();
}
const MergerBasePtr MatchboxMEBase::merger() const {
return theMerger;
}
MergerBasePtr MatchboxMEBase::merger() {
return theMerger;
}
void MatchboxMEBase::merger(MergerBasePtr v) {
theMerger = v;
}
void MatchboxMEBase::print(ostream& os) const {
os << "--- MatchboxMEBase setup -------------------------------------------------------\n";
os << " '" << name() << "' for subprocess:\n";
os << " ";
for ( PDVector::const_iterator pp = subProcess().legs.begin();
pp != subProcess().legs.end(); ++pp ) {
os << (**pp).PDGName() << " ";
if ( pp == subProcess().legs.begin() + 1 )
os << "-> ";
}
os << "\n";
os << " including " << (oneLoop() ? "" : "no ") << "virtual corrections";
if ( oneLoopNoBorn() )
os << " without Born contributions";
if ( oneLoopNoLoops() )
os << " without loop contributions";
os << "\n";
if ( oneLoop() && !onlyOneLoop() ) {
os << " using insertion operators\n";
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
os << " '" << (**v).name() << "' with "
<< ((**v).isDR() ? "" : "C") << "DR/";
if ( (**v).isCS() )
os << "CS";
if ( (**v).isBDK() )
os << "BDK";
if ( (**v).isExpanded() )
os << "expanded";
os << " conventions\n";
}
}
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
void MatchboxMEBase::printLastEvent(ostream& os) const {
os << "--- MatchboxMEBase last event information --------------------------------------\n";
os << " for matrix element '" << name() << "'\n";
os << " process considered:\n ";
int in = 0;
for ( cPDVector::const_iterator p = mePartonData().begin();
p != mePartonData().end(); ++p ) {
os << (**p).PDGName() << " ";
if ( ++in == 2 )
os << " -> ";
}
os << " kinematic environment as set by the XComb " << lastXCombPtr() << ":\n"
<< " sqrt(shat)/GeV = " << sqrt(lastSHat()/GeV2)
<< " x1 = " << lastX1() << " x2 = " << lastX2()
<< " alphaS = " << lastAlphaS() << "\n";
os << " momenta/GeV generated from random numbers\n ";
copy(lastXComb().lastRandomNumbers().begin(),
lastXComb().lastRandomNumbers().end(),ostream_iterator<double>(os," "));
os << ":\n ";
for ( vector<Lorentz5Momentum>::const_iterator p = meMomenta().begin();
p != meMomenta().end(); ++p ) {
os << (*p/GeV) << "\n ";
}
os << "last cross section/nb calculated was:\n "
<< (lastMECrossSection()/nanobarn) << " (pdf weight " << lastMEPDFWeight() << ")\n";
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
void MatchboxMEBase::logGenerateKinematics(const double * r) const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' generated kinematics\nfrom "
<< nDim() << " random numbers:\n";
copy(r,r+nDim(),ostream_iterator<double>(generator()->log()," "));
generator()->log() << "\n";
generator()->log() << "storing phase space information in XComb "
<< lastXCombPtr() << "\n";
generator()->log() << "generated phase space point (in GeV):\n";
vector<Lorentz5Momentum>::const_iterator pit = meMomenta().begin();
cPDVector::const_iterator dit = mePartonData().begin();
for ( ; pit != meMomenta().end() ; ++pit, ++dit )
generator()->log() << (**dit).PDGName() << " : "
<< (*pit/GeV) << "\n";
generator()->log() << "with x1 = " << lastX1() << " x2 = " << lastX2() << "\n"
<< "and Jacobian = " << jacobian() << " sHat/GeV2 = "
<< (lastSHat()/GeV2) << "\n" << flush;
}
void MatchboxMEBase::logSetScale() const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' set scales using XComb " << lastXCombPtr() << ":\n"
<< "scale/GeV2 = " << (scale()/GeV2) << " xi_R = "
<< renormalizationScaleFactor() << " xi_F = "
<< factorizationScaleFactor() << "\n"
<< "alpha_s = " << lastAlphaS() << "\n" << flush;
}
void MatchboxMEBase::logPDFWeight() const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' calculated pdf weight = "
<< lastMEPDFWeight() << " from XComb "
<< lastXCombPtr() << "\n"
<< "x1 = " << lastX1() << " (" << (mePartonData()[0]->coloured() ? "" : "not ") << "used) "
<< "x2 = " << lastX2() << " (" << (mePartonData()[1]->coloured() ? "" : "not ") << "used)\n"
<< flush;
}
void MatchboxMEBase::logME2() const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' evaluated me2 using XComb "
<< lastXCombPtr() << "\n"
<< "and phase space point (in GeV):\n";
vector<Lorentz5Momentum>::const_iterator pit = meMomenta().begin();
cPDVector::const_iterator dit = mePartonData().begin();
for ( ; pit != meMomenta().end() ; ++pit, ++dit )
generator()->log() << (**dit).PDGName() << " : "
<< (*pit/GeV) << "\n";
generator()->log() << "with x1 = " << lastX1() << " x2 = " << lastX2() << "\n"
<< "sHat/GeV2 = " << (lastSHat()/GeV2) << "\n" << flush;
}
void MatchboxMEBase::logDSigHatDR() const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' evaluated cross section using XComb "
<< lastXCombPtr() << "\n"
<< "Jacobian = " << jacobian() << " sHat/GeV2 = "
<< (lastSHat()/GeV2) << " dsig/nb = "
<< (lastMECrossSection()/nanobarn) << "\n" << flush;
}
void MatchboxMEBase::cloneDependencies(const std::string& prefix,bool slim) {
if ( phasespace() && !slim ) {
Ptr<MatchboxPhasespace>::ptr myPhasespace = phasespace()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myPhasespace->name();
if ( ! (generator()->preinitRegister(myPhasespace,pname.str()) ) )
throw Exception() << "MatchboxMEBase::cloneDependencies(): Phasespace generator " << pname.str() << " already existing." << Exception::runerror;
myPhasespace->cloneDependencies(pname.str());
phasespace(myPhasespace);
}
theAmplitude = dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>(amplitude());
if ( matchboxAmplitude() ) {
Ptr<MatchboxAmplitude>::ptr myAmplitude = matchboxAmplitude()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myAmplitude->name();
if ( ! (generator()->preinitRegister(myAmplitude,pname.str()) ) ){
throw Exception() << "MatchboxMEBase::cloneDependencies(): Amplitude " << pname.str() << " already existing." << Exception::runerror;
}
myAmplitude->cloneDependencies(pname.str(),slim);
matchboxAmplitude(myAmplitude);
amplitude(myAmplitude);
matchboxAmplitude()->orderInGs(orderInAlphaS());
matchboxAmplitude()->orderInGem(orderInAlphaEW());
}
if ( scaleChoice() &&!slim ) {
Ptr<MatchboxScaleChoice>::ptr myScaleChoice = scaleChoice()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myScaleChoice->name();
if ( ! (generator()->preinitRegister(myScaleChoice,pname.str()) ) )
throw Exception() << "MatchboxMEBase::cloneDependencies(): Scale choice " << pname.str() << " already existing." << Exception::runerror;
scaleChoice(myScaleChoice);
}
for ( auto & rw : theReweights ) {
Ptr<MatchboxReweightBase>::ptr myReweight = rw->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << rw->name();
if ( ! (generator()->preinitRegister(myReweight,pname.str()) ) )
throw Exception() << "MatchboxMEBase::cloneDependencies(): Reweight " << pname.str() << " already existing." << Exception::runerror;
myReweight->cloneDependencies(pname.str());
rw = myReweight;
}
for ( auto & v : virtuals()) {
Ptr<MatchboxInsertionOperator>::ptr myIOP = v->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << v->name();
if ( ! (generator()->preinitRegister(myIOP,pname.str()) ) )
throw Exception() << "MatchboxMEBase::cloneDependencies(): Insertion operator " << pname.str() << " already existing." << Exception::runerror;
v = myIOP;
}
}
void MatchboxMEBase::prepareXComb(MatchboxXCombData& xc) const {
// fixme We need to pass on the partons from the xcmob here, not
// assuming one subprocess per matrix element
if ( phasespace() )
xc.nDimPhasespace(phasespace()->nDim(diagrams().front()->partons()));
if ( matchboxAmplitude() ) {
xc.nDimAmplitude(matchboxAmplitude()->nDimAdditional());
if ( matchboxAmplitude()->colourBasis() ) {
size_t cdim =
matchboxAmplitude()->colourBasis()->prepare(diagrams(),noCorrelations());
xc.colourBasisDim(cdim);
}
if ( matchboxAmplitude()->isExternal() ) {
xc.externalId(matchboxAmplitude()->externalId(diagrams().front()->partons()));
}
}
int insertionAdd = 0;
for ( auto const & v : virtuals() )
insertionAdd = max(insertionAdd,v->nDimAdditional());
xc.nDimInsertions(insertionAdd);
xc.nLight(getNLight());
if(xc.nLightJetVec().empty())
for (auto const & id : getNLightJetVec())
xc.nLightJetVec( id );
if(xc.nHeavyJetVec().empty())
for (auto const & id :getNHeavyJetVec())
xc.nHeavyJetVec(id);
if(xc.nLightProtonVec().empty())
for (auto const & id : getNLightProtonVec())
xc.nLightProtonVec(id);
xc.olpId(olpProcess());
if ( initVerbose() ) {
ostringstream fname_strm;
// only allow alphanumeric, / and _ in filename
for (const char c : name()) {
switch (c) {
case '+' : fname_strm << "+"; break;
case '-' : fname_strm << "-"; break;
case '~' : fname_strm << "_tilde"; break;
case ']' : break;
case ',' : fname_strm << "__"; break;
default : fname_strm << (isalnum(c) ? c : '_'); break;
}
}
fname_strm << ".diagrams";
const string fname = fname_strm.str();
ifstream test(fname.c_str());
if ( !test ) {
test.close();
ofstream out(fname.c_str());
for ( vector<Ptr<DiagramBase>::ptr>::const_iterator d = diagrams().begin();
d != diagrams().end(); ++d ) {
DiagramDrawer::drawDiag(out,dynamic_cast<const Tree2toNDiagram&>(**d));
out << "\n";
}
}
}
}
StdXCombPtr MatchboxMEBase::makeXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts,
const DiagramVector & newDiagrams, bool mir,
const PartonPairVec&,
tStdXCombPtr newHead,
tMEPtr newME) {
if ( !newME )
newME = this;
Ptr<MatchboxXComb>::ptr xc =
new_ptr(MatchboxXComb(newMaxEnergy, inc,
newEventHandler, newSubProcessHandler,
newExtractor, newCKKW,
newPartonBins, newCuts, newME,
newDiagrams, mir,
newHead));
prepareXComb(*xc);
return xc;
}
StdXCombPtr MatchboxMEBase::makeXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins,
const DiagramVector & newDiagrams,
tMEPtr newME) {
if ( !newME )
newME = this;
Ptr<MatchboxXComb>::ptr xc =
new_ptr(MatchboxXComb(newHead, newPartonBins, newME, newDiagrams));
prepareXComb(*xc);
return xc;
}
void MatchboxMEBase::persistentOutput(PersistentOStream & os) const {
os << theLastXComb << theFactory << thePhasespace
<< theAmplitude << theScaleChoice << theVirtuals
<< theReweights << theSubprocess << theOneLoop
<< theOneLoopNoBorn << theOneLoopNoLoops
<< epsilonSquarePoleHistograms << epsilonPoleHistograms
<< theMerger
<< theOLPProcess << theNoCorrelations
<< theHavePDFs << checkedPDFs;
}
void MatchboxMEBase::persistentInput(PersistentIStream & is, int) {
is >> theLastXComb >> theFactory >> thePhasespace
>> theAmplitude >> theScaleChoice >> theVirtuals
>> theReweights >> theSubprocess >> theOneLoop
>> theOneLoopNoBorn >> theOneLoopNoLoops
>> epsilonSquarePoleHistograms >> epsilonPoleHistograms
>> theMerger
>> theOLPProcess >> theNoCorrelations
>> theHavePDFs >> checkedPDFs;
lastMatchboxXComb(theLastXComb);
}
void MatchboxMEBase::Init() {
static ClassDocumentation<MatchboxMEBase> documentation
("MatchboxMEBase is the base class for matrix elements "
"in the context of the matchbox NLO interface.");
}
IBPtr MatchboxMEBase::clone() const {
return new_ptr(*this);
}
IBPtr MatchboxMEBase::fullclone() const {
return new_ptr(*this);
}
void MatchboxMEBase::doinit() {
MEBase::doinit();
if ( !theAmplitude )
theAmplitude = dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>(amplitude());
if ( matchboxAmplitude() )
matchboxAmplitude()->init();
if ( phasespace() ) {
phasespace()->init();
matchboxAmplitude()->checkReshuffling(phasespace());
}
if ( scaleChoice() ) {
scaleChoice()->init();
}
for (auto const & rw : theReweights)
rw->init();
for (auto const & v : virtuals() )
v->init();
}
void MatchboxMEBase::doinitrun() {
MEBase::doinitrun();
if ( matchboxAmplitude() )
matchboxAmplitude()->initrun();
if ( phasespace() )
phasespace()->initrun();
if ( scaleChoice() )
scaleChoice()->initrun();
for (auto const & rw : theReweights)
rw->initrun();
for (auto const & v : virtuals() )
v->initrun();
}
void MatchboxMEBase::dofinish() {
MEBase::dofinish();
for (auto const & b : epsilonSquarePoleHistograms ) {
b.second.dump(factory()->poleData(),"epsilonSquarePoles-",b.first);
}
for (auto const & b : epsilonPoleHistograms ) {
b.second.dump(factory()->poleData(),"epsilonPoles-",b.first);
}
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<MatchboxMEBase,MEBase>
describeHerwigMatchboxMEBase("Herwig::MatchboxMEBase", "Herwig.so");
diff --git a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOAmplitude.cc b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOAmplitude.cc
--- a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOAmplitude.cc
+++ b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOAmplitude.cc
@@ -1,461 +1,477 @@
// -*- C++ -*-
//
// VBFNLOAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VBFNLOAmplitude class.
//
#include "VBFNLOAmplitude.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/DynamicLoader.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
#include <cstdlib>
#include "VBFNLO/utilities/BLHAinterface.h"
#define DEFSTR(s) CPPSTR(s)
#define CPPSTR(s) #s
using namespace Herwig;
VBFNLOAmplitude::VBFNLOAmplitude()
: theRanHelSum(false), theAnomCoupl(false), VBFNLOlib_(DEFSTR(VBFNLOLIB))
{}
VBFNLOAmplitude::~VBFNLOAmplitude() {}
IBPtr VBFNLOAmplitude::clone() const {
return new_ptr(*this);
}
IBPtr VBFNLOAmplitude::fullclone() const {
return new_ptr(*this);
}
void VBFNLOAmplitude::signOLP(const string& order, const string& contract) {
int status = 0;
OLP_Order(const_cast<char*>(order.c_str()),
const_cast<char*>(contract.c_str()),&status);
if ( status != 1 )
throw Exception() << "VBFNLOAmplitude: Failed to sign contract with VBFNLO.\n"
<< "The BLHA contract file " << contract << "\n"
<< "may contain further details about the error."
<< Exception::runerror;
}
void VBFNLOAmplitude::setOLPParameter(const string& name, double value) const {
int pStatus = 0;
double zero = 0.0;
OLP_SetParameter(const_cast<char*>(name.c_str()),&value,&zero,&pStatus);
if ( !pStatus )
throw Exception() << "VBFNLOAmplitude: VBFNLO failed to set parameter '"
<< name << "' to " << value << "\n"
<< Exception::runerror;
}
void VBFNLOAmplitude::startOLP(const string& contract, int& status) {
OLP_Start(const_cast<char*>(contract.c_str()), &status);
map<long,Energy>::const_iterator it=reshuffleMasses().find(ParticleID::b);
double bmass;
if(it==reshuffleMasses().end())
bmass = getParticleData(ParticleID::b)->hardProcessMass()/GeV;
else
bmass = it->second/GeV;
setOLPParameter("mass(5)",bmass);
setOLPParameter("mass(6)",getParticleData(ParticleID::t)->hardProcessMass()/GeV);
setOLPParameter("mass(23)",getParticleData(ParticleID::Z0)->hardProcessMass()/GeV);
setOLPParameter("mass(24)",getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV);
setOLPParameter("mass(25)",getParticleData(ParticleID::h0)->hardProcessMass()/GeV);
setOLPParameter("width(23)",getParticleData(ParticleID::Z0)->hardProcessWidth()/GeV);
setOLPParameter("width(24)",getParticleData(ParticleID::Wplus)->hardProcessWidth()/GeV);
setOLPParameter("width(25)",getParticleData(ParticleID::h0)->hardProcessWidth()/GeV);
setOLPParameter("alpha",SM().alphaEMMZ());
setOLPParameter("sw2",SM().sin2ThetaW());
setOLPParameter("Gf",SM().fermiConstant()*GeV2);
setOLPParameter("Nf",factory()->nLight());
setOLPParameter("alphas",SM().alphaS());
setOLPParameter("ranhelsum",theRanHelSum);
setOLPParameter("anomcoupl",theAnomCoupl);
didStartOLP() = true;
}
void VBFNLOAmplitude::loadVBFNLO() {
- if ( ! (DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.so") ||
- DynamicLoader::load("libVBFNLO.so") ||
- DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.dylib") ||
- DynamicLoader::load("libVBFNLO.dylib") ) )
- throw Exception() << "VBFNLOAmplitude: failed to load libVBFNLO.so/dylib\n"
- << DynamicLoader::lastErrorMessage
- << Exception::runerror;
+ if ( ! DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.so") ) {
+ string error1 = DynamicLoader::lastErrorMessage;
+ if ( ! DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.dylib") ) {
+ string error2 = DynamicLoader::lastErrorMessage;
+ if ( ! DynamicLoader::load("libVBFNLO.so") ) {
+ string error3 = DynamicLoader::lastErrorMessage;
+ if ( ! DynamicLoader::load("libVBFNLO.dylib") ) {
+ string error4 = DynamicLoader::lastErrorMessage;
+ throw Exception() << "VBFNLOAmplitude: failed to load libVBFNLO.so/dylib\n"
+ << "Error messages are:\n\n"
+ << "* " << VBFNLOlib_ << "/libVBFNLO.so:\n"
+ << error1 << "\n"
+ << "* " << VBFNLOlib_ << "/libVBFNLO.dylib:\n"
+ << error2 << "\n"
+ << "* libVBFNLO.so:\n"
+ << error3 << "\n"
+ << "* libVBFNLO.dylib:\n"
+ << error4 << "\n"
+ << Exception::runerror;
+ }
+ }
+ }
+ }
}
bool VBFNLOAmplitude::startOLP(const map<pair<Process,int>,int>& procs) {
loadVBFNLO();
string orderFileName = factory()->buildStorage() + name() + ".OLPOrder.lh";
ofstream orderFile(orderFileName.c_str());
olpOrderFileHeader(orderFile);
// add VBFNLO specifics here
olpOrderFileProcesses(orderFile,procs);
orderFile << flush;
orderFile.close();
string contractFileName = factory()->buildStorage() + name() + ".OLPContract.lh";
signOLP(orderFileName, contractFileName);
int status = -1;
startOLP(contractFileName,status);
if ( status != 1 )
return false;
return true;
}
LorentzVector<Complex> VBFNLOAmplitude::plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n,
int inc) const {
// shamelessly stolen from the GoSam interface; mind that we can
// always cast eq (5.7) in the manual into a form that it only uses
// <M-||M_+> and then switch bvetween eps_+ for an outgoing and
// eps_- for an incoming gluon.
double pvec[4] = {p.t()/GeV,p.x()/GeV,p.y()/GeV,p.z()/GeV};
double nvec[4] = {n.t()/GeV,n.x()/GeV,n.y()/GeV,n.z()/GeV};
double out[8] ={ };
OLP_Polvec(pvec,nvec,out);
LorentzVector<Complex> res;
Complex a(out[0],out[1]);
res.setT(a);
Complex b(out[2],out[3]);
res.setX(b);
Complex c(out[4],out[5]);
res.setY(c);
Complex d(out[6],out[7]);
res.setZ(d);
if (inc<2)
return res.conjugate();
else
return res;
}
void VBFNLOAmplitude::evalSubProcess() const {
useMe();
double units = pow(lastSHat()/GeV2,mePartonData().size()-4.);
fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses());
double scale = sqrt(mu2()/GeV2);
if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS());
double acc = -1.0;
double out[4]={};
int id =
olpId()[ProcessType::oneLoopInterference] ?
olpId()[ProcessType::oneLoopInterference] :
olpId()[ProcessType::treeME2];
if (theRanHelSum) {
vector<double> helicityrn = amplitudeRandomNumbers();
if (helicityrn.size()>0) {
setOLPParameter("HelicityRN",helicityrn[0]);
}
}
OLP_EvalSubProcess2(&id, olpMomenta(), &scale, out, &acc);
if ( olpId()[ProcessType::oneLoopInterference] ) {
lastTreeME2(out[3]*units);
lastOneLoopInterference(out[2]*units);
lastOneLoopPoles(pair<double,double>(out[0]*units,out[1]*units));
} else if ( olpId()[ProcessType::treeME2] ) {
lastTreeME2(out[0]*units);
} else assert(false);
}
void VBFNLOAmplitude::evalColourCorrelator(pair<int,int>) const {
double units = pow(lastSHat()/GeV2,mePartonData().size()-4.);
fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses());
double scale = sqrt(mu2()/GeV2);
if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS());
double acc = -1.0;
int n = lastXComb().meMomenta().size();
colourCorrelatorResults.resize(n*(n-1)/2);
int id = olpId()[ProcessType::colourCorrelatedME2];
if ( theRanHelSum ) {
if ( lastHeadMatchboxXComb() ) {
vector<double> helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers();
if (helicityrn.size()>0) {
setOLPParameter("HelicityRN",helicityrn[0]);
}
} else if ( amplitudeRandomNumbers().size() > 0 ) {
vector<double> helicityrn = amplitudeRandomNumbers();
if (helicityrn.size()>0) {
setOLPParameter("HelicityRN",helicityrn[0]);
}
}
}
OLP_EvalSubProcess2(&id, olpMomenta(), &scale, &colourCorrelatorResults[0], &acc);
for ( int i = 0; i < n; ++i )
for ( int j = i+1; j < n; ++j ) {
lastColourCorrelator(make_pair(i,j),colourCorrelatorResults[i+j*(j-1)/2]*units);
}
}
void VBFNLOAmplitude::evalSpinColourCorrelator(pair<int,int>) const {
double units = pow(lastSHat()/GeV2,mePartonData().size()-4.);
fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses());
double scale = sqrt(mu2()/GeV2);
if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS());
double acc = -1.0;
int n = lastXComb().meMomenta().size();
spinColourCorrelatorResults.resize(2*n*n);
int id = olpId()[ProcessType::spinColourCorrelatedME2];
if (theRanHelSum && lastHeadMatchboxXComb()) {
vector<double> helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers();
if (helicityrn.size()>0) {
setOLPParameter("HelicityRN",helicityrn[0]);
}
}
OLP_EvalSubProcess2(&id, olpMomenta(), &scale, &spinColourCorrelatorResults[0], &acc);
for ( int i = 0; i < n; ++i )
for ( int j = 0; j < n; ++j ) {
if ( i == j || mePartonData()[i]->id() != 21 )
continue;
Complex scc(spinColourCorrelatorResults[2*i+2*n*j]*units,
spinColourCorrelatorResults[2*i+2*n*j+1]*units);
lastColourSpinCorrelator(make_pair(i,j),scc);
}
}
double VBFNLOAmplitude::largeNME2(Ptr<ColourBasis>::tptr cptr) const {
if ( calculateLargeNME2() )
evalLargeNSubProcess(cptr);
return lastLargeNME2();
}
void VBFNLOAmplitude::evalLargeNSubProcess(Ptr<ColourBasis>::tptr) const {
double units = pow(lastSHat()/GeV2,mePartonData().size()-4.);
fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses());
double scale = sqrt(mu2()/GeV2);
if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS());
double acc = -1.0;
double out[4]={};
int id =
olpId()[ProcessType::oneLoopInterference] ?
olpId()[ProcessType::oneLoopInterference] :
olpId()[ProcessType::treeME2];
if (theRanHelSum) {
vector<double> helicityrn = amplitudeRandomNumbers();
if (helicityrn.size()>0) {
setOLPParameter("HelicityRN",helicityrn[0]);
}
}
setOLPParameter("Nc",-1); // large-N limit
OLP_EvalSubProcess2(&id, olpMomenta(), &scale, out, &acc);
setOLPParameter("Nc",generator()->standardModel()->Nc());
if ( olpId()[ProcessType::oneLoopInterference] ) {
lastLargeNME2(out[3]*units);
lastOneLoopInterference(out[2]*units);
lastOneLoopPoles(pair<double,double>(out[0]*units,out[1]*units));
} else if ( olpId()[ProcessType::treeME2] ) {
lastLargeNME2(out[0]*units);
} else assert(false);
}
double VBFNLOAmplitude::largeNColourCorrelatedME2(pair<int,int> ij,
Ptr<ColourBasis>::tptr cptr) const {
double cfac = 1.;
double Nc = generator()->standardModel()->Nc();
if ( mePartonData()[ij.first]->iColour() == PDT::Colour8 ) {
cfac = Nc;
} else if ( mePartonData()[ij.first]->iColour() == PDT::Colour3 ||
mePartonData()[ij.first]->iColour() == PDT::Colour3bar ) {
cfac = Nc/2.;
} else assert(false);
if ( calculateLargeNColourCorrelator(ij) )
evalLargeNColourCorrelator(ij,cptr);
return lastLargeNColourCorrelator(ij)/cfac;
}
void VBFNLOAmplitude::evalLargeNColourCorrelator(pair<int,int>,
Ptr<ColourBasis>::tptr) const {
double units = pow(lastSHat()/GeV2,mePartonData().size()-4.);
fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses());
double scale = sqrt(mu2()/GeV2);
if (hasRunningAlphaS()) setOLPParameter("alphas",lastAlphaS());
double acc = -1.0;
int n = lastXComb().meMomenta().size();
colourCorrelatorResults.resize(n*(n-1)/2);
int id = olpId()[ProcessType::colourCorrelatedME2];
if (theRanHelSum && lastHeadMatchboxXComb()) {
vector<double> helicityrn = lastHeadMatchboxXComb()->amplitudeRandomNumbers();
if (helicityrn.size()>0) {
setOLPParameter("HelicityRN",helicityrn[0]);
}
}
setOLPParameter("Nc",-1); // large-N limit
OLP_EvalSubProcess2(&id, olpMomenta(), &scale, &colourCorrelatorResults[0], &acc);
setOLPParameter("Nc",generator()->standardModel()->Nc());
for ( int i = 0; i < n; ++i )
for ( int j = i+1; j < n; ++j ) {
lastLargeNColourCorrelator(make_pair(i,j),colourCorrelatorResults[i+j*(j-1)/2]*units);
}
}
void VBFNLOAmplitude::doinit() {
loadVBFNLO();
MatchboxOLPME::doinit();
}
void VBFNLOAmplitude::doinitrun() {
loadVBFNLO();
MatchboxOLPME::doinitrun();
}
void VBFNLOAmplitude::persistentOutput(PersistentOStream & os) const {
os << colourCorrelatorResults << spinColourCorrelatorResults << theRanHelSum << theAnomCoupl << VBFNLOlib_;
}
void VBFNLOAmplitude::persistentInput(PersistentIStream & is, int) {
is >> colourCorrelatorResults >> spinColourCorrelatorResults >> theRanHelSum >> theAnomCoupl >> VBFNLOlib_;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<VBFNLOAmplitude,MatchboxOLPME>
describeHerwigVBFNLOAmplitude("Herwig::VBFNLOAmplitude", "HwMatchboxVBFNLO.so");
void VBFNLOAmplitude::Init() {
static ClassDocumentation<VBFNLOAmplitude> documentation
("VBFNLOAmplitude implements an interface to VBFNLO.",
"Matrix elements have been calculated using VBFNLO "
"(Ref.~\\cite{VBFNLO} and process-specific references)\n",
"%\\cite{VBFNLO}\n"
"\\bibitem{Arnold:2008rz}\n"
"K.~Arnold, M.~Bahr, G.~Bozzi, F.~Campanario, C.~Englert, T.~Figy, "
"N.~Greiner and C.~Hackstein {\\it et al.},\n"
"``VBFNLO: A Parton level Monte Carlo for processes with electroweak bosons,''\n"
"Comput.\\ Phys.\\ Commun.\\ {\\bf 180} (2009) 1661\n"
"[arXiv:0811.4559 [hep-ph]];\n"
"%%CITATION = ARXIV:0811.4559;%%\n"
"J.~Baglio, J.~Bellm, F.~Campanario, B.~Feigl, J.~Frank, T.~Figy, "
"M.~Kerner and L.~D.~Ninh {\\it et al.},\n"
"``Release Note - VBFNLO 2.7.0,''\n"
"arXiv:1404.3940 [hep-ph].\n"
"%%CITATION = ARXIV:1404.3940;%%\n");
static Switch<VBFNLOAmplitude,bool> interfaceRandomHelicitySummation
("RandomHelicitySummation", "Switch for random helicity summation of leptons and photons",
&VBFNLOAmplitude::theRanHelSum, false, false, false);
static SwitchOption interfaceRandomHelicitySummationTrue
(interfaceRandomHelicitySummation,
"True",
"Perform random helicity summation",
true);
static SwitchOption interfaceRandomHelicitySummationFalse
(interfaceRandomHelicitySummation,
"False",
"Sum over all helicity combinations",
false);
static Switch<VBFNLOAmplitude,bool> interfaceAnomalousCouplings
("AnomalousCouplings", "Switch for anomalous couplings",
&VBFNLOAmplitude::theAnomCoupl, false, false, false);
static SwitchOption interfaceAnomalousCouplingsTrue
(interfaceAnomalousCouplings,
"On",
"Switch anomalous couplings on",
true);
static SwitchOption interfaceAnomalousCouplingsFalse
(interfaceAnomalousCouplings,
"Off",
"Switch anomalous couplings off",
false);
}
diff --git a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.cc b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.cc
--- a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.cc
+++ b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.cc
@@ -1,261 +1,277 @@
// -*- C++ -*-
//
// VBFNLOPhasespace.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VBFNLOPhasespace class.
//
#include "VBFNLOPhasespace.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "Herwig/Utilities/GSLBisection.h"
#include "ThePEG/Utilities/DynamicLoader.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h"
#include "VBFNLO/utilities/BLHAinterface.h"
#define DEFSTR(s) CPPSTR(s)
#define CPPSTR(s) #s
using namespace Herwig;
VBFNLOPhasespace::VBFNLOPhasespace() :
lastSqrtS(0*GeV), needToReshuffle(false), VBFNLOlib_(DEFSTR(VBFNLOLIB))
{}
void VBFNLOPhasespace::loadVBFNLO() {
- if ( ! (DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.so") ||
- DynamicLoader::load("libVBFNLO.so") ||
- DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.dylib") ||
- DynamicLoader::load("libVBFNLO.dylib") ) )
- throw Exception() << "VBFNLOPhasespace::loadVBFNLO(): Failed to load libVBFNLO.so/dylib\n"
- << DynamicLoader::lastErrorMessage
- << Exception::runerror;
+ if ( ! DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.so") ) {
+ string error1 = DynamicLoader::lastErrorMessage;
+ if ( ! DynamicLoader::load(VBFNLOlib_+"/libVBFNLO.dylib") ) {
+ string error2 = DynamicLoader::lastErrorMessage;
+ if ( ! DynamicLoader::load("libVBFNLO.so") ) {
+ string error3 = DynamicLoader::lastErrorMessage;
+ if ( ! DynamicLoader::load("libVBFNLO.dylib") ) {
+ string error4 = DynamicLoader::lastErrorMessage;
+ throw Exception() << "VBFNLOPhasespace: failed to load libVBFNLO.so/dylib\n"
+ << "Error messages are:\n\n"
+ << "* " << VBFNLOlib_ << "/libVBFNLO.so:\n"
+ << error1 << "\n"
+ << "* " << VBFNLOlib_ << "/libVBFNLO.dylib:\n"
+ << error2 << "\n"
+ << "* libVBFNLO.so:\n"
+ << error3 << "\n"
+ << "* libVBFNLO.dylib:\n"
+ << error4 << "\n"
+ << Exception::runerror;
+ }
+ }
+ }
+ }
}
VBFNLOPhasespace::~VBFNLOPhasespace() {}
IBPtr VBFNLOPhasespace::clone() const {
return new_ptr(*this);
}
IBPtr VBFNLOPhasespace::fullclone() const {
return new_ptr(*this);
}
void VBFNLOPhasespace::setXComb(tStdXCombPtr xco) {
MatchboxPhasespace::setXComb(xco);
// test for resuffling
needToReshuffle = false;
if ( xco ) {
for ( cPDVector::const_iterator d = mePartonData().begin();
d != mePartonData().end(); ++d ) {
// Higgs is massive -> does not need reshuffling
if ( ( (**d).id() != ParticleID::h0 ) && ( (**d).hardProcessMass() != ZERO ) ) {
needToReshuffle = true;
break;
}
}
}
// set CMS energy
int pStatus = 0;
double zero = 0.0;
double value = sqrt(lastXCombPtr()->lastS())/GeV;
if (value && (value != lastSqrtS/GeV)) {
lastSqrtS = value*GeV;
string name = "sqrtS";
OLP_SetParameter(const_cast<char*>(name.c_str()),&value,&zero,&pStatus);
if ( !pStatus )
throw Exception() << "VBFNLOPhasespace::setXComb(): VBFNLO failed to set parameter '"
<< name << "' to " << value << "\n"
<< Exception::runerror;
}
}
double VBFNLOPhasespace::generateTwoToNKinematics(const double* random,
vector<Lorentz5Momentum>& momenta) {
double weight;
int id =
olpId()[ProcessType::oneLoopInterference] ?
olpId()[ProcessType::oneLoopInterference] :
olpId()[ProcessType::treeME2];
double* p = new double[4*momenta.size()];
OLP_PhaseSpacePoint(&id, const_cast<double*>(random), const_cast<double*>(random+1), p, &weight);
if (weight < 0) {
throw Exception() << "VBFNLOPhasespace::generateTwoToNKinematics(): Negative weight in VBFNLOPhaseSpace\n"
<< Exception::runerror;
}
if (weight == 0) {
delete[] p;
return 0;
}
for ( size_t i = 0; i < momenta.size(); ++i ) {
momenta[i].setT(p[4*i] *GeV);
momenta[i].setX(p[4*i+1]*GeV);
momenta[i].setY(p[4*i+2]*GeV);
momenta[i].setZ(p[4*i+3]*GeV);
momenta[i].rescaleMass();
}
delete[] p;
Energy beamenergy = sqrt(lastXCombPtr()->lastS())/2.;
double x1 = momenta[0].e()/beamenergy;
double x2 = momenta[1].e()/beamenergy;
Energy2 thisSHat = (momenta[0] + momenta[1]).m2();
// reshuffle so that particles have correct mass
if ( needToReshuffle ) {
// boost final-state into partonic CMS
Boost toCMS = (momenta[0]+momenta[1]).findBoostToCM();
for ( size_t i = 2; i < momenta.size(); ++i ) {
momenta[i].boost(toCMS);
}
// copied from MatchboxRambo phasespace
double xi;
ReshuffleEquation solve(sqrt(thisSHat),mePartonData().begin()+2,mePartonData().end(),
momenta.begin()+2,momenta.end());
GSLBisection solver(1e-10,1e-8,10000);
try {
xi = solver.value(solve,0.0,1.1);
} catch (GSLBisection::GSLerror) {
return 0.;
} catch (GSLBisection::IntervalError) {
return 0.;
}
weight *= pow(xi,3.*(momenta.size()-3.));
Energy num = ZERO;
Energy den = ZERO;
cPDVector::const_iterator d = mePartonData().begin()+2;
for ( vector<Lorentz5Momentum>::iterator k = momenta.begin()+2;
k != momenta.end(); ++k, ++d ) {
num += (*k).vect().mag2()/(*k).t();
Energy q = (*k).t();
(*k).setT(sqrt(sqr((**d).hardProcessMass())+xi*xi*sqr((*k).t())));
(*k).setVect(xi*(*k).vect());
weight *= q/(*k).t();
den += (*k).vect().mag2()/(*k).t();
(*k).setMass((**d).hardProcessMass());
}
// unboost
for ( size_t i = 2; i < momenta.size(); ++i ) {
momenta[i].boost(-toCMS);
}
}
if ( !matchConstraints(momenta) )
return 0.;
lastXCombPtr()->lastX1X2(make_pair(x1,x2));
lastXCombPtr()->lastSHat(thisSHat);
weight /= pow(thisSHat/GeV2,momenta.size()-4);
weight /= x1*x2;
fillDiagramWeights();
return weight;
}
int VBFNLOPhasespace::nDimPhasespace(int nFinal) const {
return 3*nFinal;
//get this from within VBFNLO
int pStatus = 0;
double value, zero;
string name = "PSdimension";
OLP_GetParameter(const_cast<char*>(name.c_str()),&value,&zero,&pStatus);
if ( pStatus != 1) {
throw Exception() << "VBFNLOPhasespace::nDimPhasespace(): Cannot get phasespace dimension in VBFNLOPhaseSpace\n"
<< "error code: " << pStatus << "\n"
<< Exception::runerror;
}
// one additional number (first) needed for channel selection
// one additional number (last) needed for global phi integration
return value+2;
}
Energy VBFNLOPhasespace::ReshuffleEquation::operator() (double xi) const {
cPDVector::const_iterator d = dataBegin;
vector<Lorentz5Momentum>::const_iterator p = momentaBegin;
Energy res = -w;
for ( ; d != dataEnd; ++d, ++p ) {
res += sqrt(sqr((**d).hardProcessMass()) +
xi*xi*sqr(p->t()));
}
return res;
}
void VBFNLOPhasespace::doinit() {
loadVBFNLO();
MatchboxPhasespace::doinit();
}
void VBFNLOPhasespace::doinitrun() {
loadVBFNLO();
MatchboxPhasespace::doinitrun();
}
void VBFNLOPhasespace::persistentOutput(PersistentOStream & os) const {
os << needToReshuffle << theLastXComb;
}
void VBFNLOPhasespace::persistentInput(PersistentIStream & is, int) {
is >> needToReshuffle >> theLastXComb;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<VBFNLOPhasespace,MatchboxPhasespace>
describeHerwigVBFNLOPhasespace("Herwig::VBFNLOPhasespace", "HwMatchboxVBFNLO.so");
void VBFNLOPhasespace::Init() {
static ClassDocumentation<VBFNLOPhasespace> documentation
("VBFNLOPhasespace is an interface to the internal phasespace generator "
"of VBFNLO. It uses the information passed via the BLHA interface to "
"obtain information on the required channels.");
}
diff --git a/MatrixElement/Matchbox/MatchboxFactory.cc b/MatrixElement/Matchbox/MatchboxFactory.cc
--- a/MatrixElement/Matchbox/MatchboxFactory.cc
+++ b/MatrixElement/Matchbox/MatchboxFactory.cc
@@ -1,2202 +1,2202 @@
// -*- C++ -*-
//
// MatchboxFactory.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MatchboxFactory class.
//
#include "MatchboxFactory.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/SamplerBase.h"
#include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h"
#include "Herwig/MatrixElement/Matchbox/Utility/SU2Helper.h"
-#include "Herwig/Utilities/RunDirectories.h"
+#include "Herwig/API/RunDirectories.h"
#include <boost/progress.hpp>
#include <boost/filesystem.hpp>
#include <iterator>
using std::ostream_iterator;
using namespace Herwig;
using std::ostream_iterator;
MatchboxFactory::MatchboxFactory()
: SubProcessHandler(), theNLight(0),
theOrderInAlphaS(0), theOrderInAlphaEW(0),
theBornContributions(true), theVirtualContributions(true),
theRealContributions(true), theIndependentVirtuals(false),
theIndependentPKs(false),
theSubProcessGroups(false),
theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0),
theFixedCouplings(false), theFixedQEDCouplings(false), theVetoScales(false),
theDipoleSet(0), theVerbose(false), theDiagramWeightVerbose(false),
theDiagramWeightVerboseNBins(200),
theInitVerbose(false),
theSubtractionData(""), theSubtractionPlotType(1), theSubtractionScatterPlot(false),
thePoleData(""), theRealEmissionScales(false), theAllProcesses(false),
theMECorrectionsOnly(false), theLoopSimCorrections(false), ranSetup(false),
theFirstPerturbativePDF(true), theSecondPerturbativePDF(true),
inProductionMode(false), theSpinCorrelations(false),theAlphaParameter(1.),
theEnforceChargeConservation(true), theEnforceColourConservation(false),
theEnforceLeptonNumberConservation(false), theEnforceQuarkNumberConservation(false),
theLeptonFlavourDiagonal(false), theQuarkFlavourDiagonal(false) {}
MatchboxFactory::~MatchboxFactory() {}
bool& MatchboxFactory::theIsMatchboxRun() {
static bool flag = false;
return flag;
}
IBPtr MatchboxFactory::clone() const {
return new_ptr(*this);
}
IBPtr MatchboxFactory::fullclone() const {
return new_ptr(*this);
}
void MatchboxFactory::prepareME(Ptr<MatchboxMEBase>::ptr me) {
Ptr<MatchboxAmplitude>::ptr amp =
dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>((*me).amplitude());
me->matchboxAmplitude(amp);
me->factory(this);
if ( phasespace() && !me->phasespace() )
me->phasespace(phasespace());
if ( scaleChoice() && !me->scaleChoice() )
me->scaleChoice(scaleChoice());
if ( !reweighters().empty() ) {
for ( vector<ReweightPtr>::const_iterator rw = reweighters().begin();
rw != reweighters().end(); ++rw )
me->addReweighter(*rw);
}
if ( !preweighters().empty() ) {
for ( vector<ReweightPtr>::const_iterator rw = preweighters().begin();
rw != preweighters().end(); ++rw )
me->addPreweighter(*rw);
}
}
string pid(const PDVector& key) {
ostringstream res;
res << "[" << key[0]->PDGName() << ","
<< key[1]->PDGName() << "->";
for ( PDVector::const_iterator k =
key.begin() + 2; k != key.end(); ++k )
res << (**k).PDGName() << (k != --key.end() ? "," : "");
res << "]";
return res.str();
}
vector<Ptr<MatchboxMEBase>::ptr> MatchboxFactory::
makeMEs(const vector<string>& proc, unsigned int orderas, bool virt) {
generator()->log() << "determining subprocesses for ";
copy(proc.begin(),proc.end(),ostream_iterator<string>(generator()->log()," "));
generator()->log() << "\n" << flush;
map<Ptr<MatchboxAmplitude>::ptr,set<Process> > ampProcs;
map<Process,set<Ptr<MatchboxAmplitude>::ptr> > procAmps;
set<PDVector> processes = makeSubProcesses(proc);
// TODO Fix me for 3.0.x
// At the moment we got troubles with processes with no coloured
// legs so they will not be supported
set<PDVector> colouredProcesses;
for ( set<PDVector>::const_iterator pr = processes.begin();
pr != processes.end(); ++pr ) {
for ( PDVector::const_iterator pp = pr->begin();
pp != pr->end(); ++pp ) {
if ( (**pp).coloured() ) {
colouredProcesses.insert(*pr);
break;
}
}
}
if ( colouredProcesses.size() != processes.size() ) {
generator()->log()
<< "Some or all of the generated subprocesses do not contain coloured legs.\n"
<< "Processes of this kind are currently not supported.\n" << flush;
}
if ( colouredProcesses.empty() ) {
throw Exception() << "MatchboxFactory::makeMEs(): No processes with coloured legs have been found. "
<< "This run will be aborted." << Exception::runerror;
}
processes = colouredProcesses;
// end unsupported processes
// detect external particles with non-zero width for the hard process
bool trouble = false;
string troubleMaker;
for ( set<PDVector>::const_iterator pr = processes.begin();
pr != processes.end(); ++pr ) {
for ( PDVector::const_iterator pp = pr->begin();
pp != pr->end(); ++pp ) {
if ( (**pp).hardProcessWidth() != ZERO ) {
trouble = true;
troubleMaker = (**pp).PDGName();
break;
}
}
}
if ( trouble ) {
throw Exception()
<< "MatchboxFactory::makeMEs(): Particle '"
<< troubleMaker << "' appears as external\nprocess leg with non-zero "
<< "width to be used in the hard process calculation.\n"
<< "Please check your setup and consider setting HardProcessWidth to zero."
<< Exception::runerror;
}
vector<Ptr<MatchboxAmplitude>::ptr> matchAmplitudes;
unsigned int lowestAsOrder =
allProcesses() ? 0 : orderas;
unsigned int highestAsOrder = orderas;
unsigned int lowestAeOrder =
allProcesses() ? 0 : orderInAlphaEW();
unsigned int highestAeOrder = orderInAlphaEW();
for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) {
for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) {
for ( vector<Ptr<MatchboxAmplitude>::ptr>::const_iterator amp
= amplitudes().begin(); amp != amplitudes().end(); ++amp ) {
if ( !theSelectedAmplitudes.empty() ) {
if ( find(theSelectedAmplitudes.begin(),theSelectedAmplitudes.end(),*amp)
== theSelectedAmplitudes.end() )
continue;
}
if ( !theDeselectedAmplitudes.empty() ) {
if ( find(theDeselectedAmplitudes.begin(),theDeselectedAmplitudes.end(),*amp)
!= theDeselectedAmplitudes.end() )
continue;
}
(**amp).orderInGs(oas);
(**amp).orderInGem(oae);
if ( (**amp).orderInGs() != oas ||
(**amp).orderInGem() != oae ) {
continue;
}
matchAmplitudes.push_back(*amp);
}
}
}
size_t combinations = processes.size()*matchAmplitudes.size();
size_t procCount = 0;
generator()->log() << "building matrix elements." << flush;
boost::progress_display * progressBar =
new boost::progress_display(combinations,generator()->log());
for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) {
for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) {
for ( vector<Ptr<MatchboxAmplitude>::ptr>::const_iterator amp
= matchAmplitudes.begin(); amp != matchAmplitudes.end(); ++amp ) {
(**amp).orderInGs(oas);
(**amp).orderInGem(oae);
for ( set<PDVector>::const_iterator p = processes.begin();
p != processes.end(); ++p ) {
++(*progressBar);
if ( !(**amp).canHandle(*p,this,virt) )
continue;
if ( (**amp).isExternal() )
externalAmplitudes().insert(*amp);
++procCount;
Process proc(*p,oas,oae);
ampProcs[*amp].insert(proc);
procAmps[proc].insert(*amp);
}
}
}
}
delete progressBar;
generator()->log() << flush;
bool clash = false;
for ( map<Process,set<Ptr<MatchboxAmplitude>::ptr> >::const_iterator check =
procAmps.begin(); check != procAmps.end(); ++check ) {
if ( check->second.size() > 1 ) {
clash = true;
generator()->log() << "Several different amplitudes have been found for: "
<< check->first.legs[0]->PDGName() << " "
<< check->first.legs[1]->PDGName() << " -> ";
for ( PDVector::const_iterator p = check->first.legs.begin() + 2;
p != check->first.legs.end(); ++p )
generator()->log() << (**p).PDGName() << " ";
generator()->log() << "at alpha_s^" << check->first.orderInAlphaS
<< " and alpha_ew^" << check->first.orderInAlphaEW
<< "\n";
generator()->log() << "The following amplitudes claim responsibility:\n";
for ( set<Ptr<MatchboxAmplitude>::ptr>::const_iterator a = check->second.begin();
a != check->second.end(); ++a ) {
generator()->log() << (**a).name() << " ";
}
generator()->log() << "\n";
}
}
if ( clash ) {
throw Exception() << "MatchboxFactory: Ambiguous amplitude setup - please check your input files.\n"
<< "To avoid this problem use the SelectAmplitudes or DeselectAmplitudes interfaces.\n"
<< Exception::runerror;
}
bool canDoSpinCorrelations = true;
vector<Ptr<MatchboxMEBase>::ptr> res;
for ( map<Ptr<MatchboxAmplitude>::ptr,set<Process> >::const_iterator
ap = ampProcs.begin(); ap != ampProcs.end(); ++ap ) {
canDoSpinCorrelations &= ap->first->canFillRhoMatrix();
for ( set<Process>::const_iterator m = ap->second.begin();
m != ap->second.end(); ++m ) {
Ptr<MatchboxMEBase>::ptr me = ap->first->makeME(m->legs);
me->subProcess() = *m;
me->amplitude(ap->first);
me->matchboxAmplitude(ap->first);
prepareME(me);
string pname = "ME" + pid(m->legs);
if ( ! (generator()->preinitRegister(me,pname) ) )
throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing."
<< Exception::runerror;
if ( me->diagrams().empty() )continue;
res.push_back(me);
if ( theFirstPerturbativePDF )
theIncoming.insert(m->legs[0]->id());
if ( theSecondPerturbativePDF )
theIncoming.insert(m->legs[1]->id());
}
}
if ( spinCorrelations() && !canDoSpinCorrelations ) {
generator()->log() << "Warning: Spin correlations have been requested, but no amplitude is "
<< "capable of performing these.\n";
theSpinCorrelations = false;
}
generator()->log() << "created "
<< procCount << " subprocesses.\n";
generator()->log() << "---------------------------------------------------\n"
<< flush;
return res;
}
int MatchboxFactory::orderOLPProcess(const Process& proc,
Ptr<MatchboxAmplitude>::tptr amp,
int type) {
map<pair<Process,int>,int>& procs =
olpProcesses()[amp];
map<pair<Process,int>,int>::const_iterator it =
procs.find(make_pair(proc,type));
if ( it != procs.end() )
return it->second;
int id = procs.size();
procs[make_pair(proc,type)] = id + 1;
return id + 1;
}
void MatchboxFactory::productionMode() {
if ( inProductionMode )
return;
if ( !bornContributions() && !virtualContributions() && !realContributions() )
throw Exception() << "MatchboxFactory: At least one cross section contribution needs to be enabled.\n"
<< "Please check your setup.\n"
<< Exception::runerror;
bool needTrueVirtuals =
virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections();
for ( vector<Ptr<MatchboxAmplitude>::ptr>::iterator amp
= amplitudes().begin(); amp != amplitudes().end(); ++amp ) {
if ( !needTrueVirtuals && (**amp).oneLoopAmplitude() ) {
Repository::clog() << "One-loop contributions from '"
<< (**amp).name()
<< "' are not required and will be disabled.\n"
<< flush;
(**amp).disableOneLoop();
}
}
if ( subtractionData() != "" && !subProcessGroups() ) {
throw Exception() << "MatchboxFactory: Plain NLO settings are required for subtraction checks.\n"
<< "Please check your setup.\n"
<< Exception::runerror;
}
if ( showerApproximation() && !virtualContributions() && !realContributions() ) {
Repository::clog() << "Warning: Matching requested for LO run. Matching disabled.\n" << flush;
showerApproximation(Ptr<ShowerApproximation>::tptr());
}
if ( showerApproximation() && (subtractionData() != "" || subProcessGroups()) ) {
Repository::clog() << "Warning: Matching requested for plain NLO run. Matching disabled.\n" << flush;
showerApproximation(Ptr<ShowerApproximation>::tptr());
}
if ( showerApproximation() ) {
if ( spinCorrelations() && !showerApproximation()->hasSpinCorrelations() ) {
Repository::clog() << "Warning: Spin correlations have been requested but the matching "
<< "object is not capable of these. Spin correlations will be turned of.\n"
<< flush;
theSpinCorrelations = false;
}
}
inProductionMode = true;
}
void MatchboxFactory::setup() {
useMe();
if ( !ranSetup ) {
if ( !inProductionMode )
throw Exception() << "MatchboxFactory: The MatchboxFactory object '"
<< name() << "' has not been switched to production mode.\n"
<< "Did you use 'do "
<< name() << ":ProductionMode' before isolating the event generator?\n"
<< Exception::runerror;
olpProcesses().clear();
externalAmplitudes().clear();
theHighestVirtualsize = 0;
theIncoming.clear();
bool needTrueVirtuals =
virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections();
for ( vector<Ptr<MatchboxAmplitude>::ptr>::iterator amp
= amplitudes().begin(); amp != amplitudes().end(); ++amp )
(**amp).factory(this);
if ( bornMEs().empty() ) {
if ( particleGroups().find("j") == particleGroups().end() )
throw Exception() << "MatchboxFactory: Could not find a jet particle group named 'j'"
<< Exception::runerror;
// rebind the particle data objects
for ( map<string,PDVector>::iterator g = particleGroups().begin();
g != particleGroups().end(); ++g )
for ( PDVector::iterator p = g->second.begin();
p != g->second.end(); ++p ) {
#ifndef NDEBUG
long checkid = (**p).id();
#endif
*p = getParticleData((**p).id());
assert((**p).id() == checkid);
}
const PDVector& partons = particleGroups()["j"];
unsigned int nl = 0;
for ( PDVector::const_iterator p = partons.begin();
p != partons.end(); ++p ) {
if ( abs((**p).id()) < 7 && (**p).hardProcessMass() == ZERO )
++nl;
if ( (**p).id() > 0 && (**p).id() < 7 && (**p).hardProcessMass() == ZERO )
nLightJetVec( (**p).id() );
if ( (**p).id() > 0 && (**p).id() < 7 && (**p).hardProcessMass() != ZERO )
nHeavyJetVec( (**p).id() );
}
nLight(nl/2);
if ( particleGroups().find("p") == particleGroups().end() )
throw Exception() << "MatchboxFactory: Could not find a hadron particle group named 'p'"
<< Exception::runerror;
const PDVector& partonsInP = particleGroups()["p"];
for ( PDVector::const_iterator pip = partonsInP.begin();
pip != partonsInP.end(); ++pip ) {
if ( (**pip).id() > 0 && (**pip).id() < 7 && (**pip).hardProcessMass() == ZERO )
nLightProtonVec( (**pip).id() );
}
vector<Ptr<MatchboxMEBase>::ptr> mes;
for ( vector<vector<string> >::const_iterator p = processes.begin();
p != processes.end(); ++p ) {
if( needTrueVirtuals ) {
theHighestVirtualsize = max(theHighestVirtualsize,(int((*p).size())));
}
mes = makeMEs(*p,orderInAlphaS(),needTrueVirtuals);
copy(mes.begin(),mes.end(),back_inserter(bornMEs()));
if ( realContributions() || meCorrectionsOnly() ||
(showerApproximation() && virtualContributions()) ||
(showerApproximation() && loopSimCorrections()) ) {
if ( realEmissionProcesses.empty() ) {
vector<string> rproc = *p;
rproc.push_back("j");
mes = makeMEs(rproc,orderInAlphaS()+1,false);
copy(mes.begin(),mes.end(),back_inserter(realEmissionMEs()));
}
}
}
if ( realContributions() || meCorrectionsOnly() ||
(showerApproximation() && virtualContributions()) ||
(showerApproximation() && loopSimCorrections()) ) {
if ( !realEmissionProcesses.empty() ) {
for ( vector<vector<string> >::const_iterator q =
realEmissionProcesses.begin(); q != realEmissionProcesses.end(); ++q ) {
mes = makeMEs(*q,orderInAlphaS()+1,false);
copy(mes.begin(),mes.end(),back_inserter(realEmissionMEs()));
}
}
}
}
if ( loopInducedMEs().empty() ) {
for ( vector<vector<string> >::const_iterator p = loopInducedProcesses.begin();
p != loopInducedProcesses.end(); ++p ) {
vector<Ptr<MatchboxMEBase>::ptr> mes = makeMEs(*p,orderInAlphaS(),false);
copy(mes.begin(),mes.end(),back_inserter(loopInducedMEs()));
}
}
if( bornMEs().empty() && realEmissionMEs().empty() && loopInducedMEs().empty() )
throw Exception() << "MatchboxFactory: No matrix elements have been found.\n\
Please check if your order of Alpha_s and Alpha_ew have the right value.\n"
<< Exception::runerror;
// check if we have virtual contributions
bool haveVirtuals = true;
// check DR conventions of virtual contributions
bool virtualsAreDR = false;
bool virtualsAreCDR = false;
// check finite term conventions of virtual contributions
bool virtualsAreCS = false;
bool virtualsAreBDK = false;
bool virtualsAreExpanded = false;
// renormalization scheme
bool virtualsAreDRbar = false;
// check and prepare the Born and virtual matrix elements
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born ) {
prepareME(*born);
haveVirtuals &= (**born).haveOneLoop();
if ( needTrueVirtuals ) {
if ( (**born).haveOneLoop() ) {
virtualsAreDRbar |= (**born).isDRbar();
virtualsAreDR |= (**born).isDR();
virtualsAreCDR |= !(**born).isDR();
virtualsAreCS |= (**born).isCS();
virtualsAreBDK |= (**born).isBDK();
virtualsAreExpanded |= (**born).isExpanded();
}
}
}
// prepare the loop induced matrix elements
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator looped
= loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) {
prepareME(*looped);
}
if ( needTrueVirtuals ) {
// check the additional insertion operators
if ( !virtuals().empty() )
haveVirtuals = true;
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= virtuals().begin(); virt != virtuals().end(); ++virt ) {
virtualsAreDRbar |= (**virt).isDRbar();
virtualsAreDR |= (**virt).isDR();
virtualsAreCDR |= !(**virt).isDR();
virtualsAreCS |= (**virt).isCS();
virtualsAreBDK |= (**virt).isBDK();
virtualsAreExpanded |= (**virt).isExpanded();
}
// check for consistent conventions on virtuals, if we are to include them
if ( virtualContributions() ) {
if ( !haveVirtuals ) {
throw Exception() << "MatchboxFactory: Could not find amplitudes for all virtual contributions needed.\n"
<< Exception::runerror;
}
if ( virtualsAreDR && virtualsAreCDR ) {
throw Exception() << "MatchboxFactory: Virtual corrections use inconsistent regularization schemes.\n"
<< Exception::runerror;
}
if ( (virtualsAreCS && virtualsAreBDK) ||
(virtualsAreCS && virtualsAreExpanded) ||
(virtualsAreBDK && virtualsAreExpanded) ||
(!virtualsAreCS && !virtualsAreBDK && !virtualsAreExpanded) ) {
throw Exception() << "MatchboxFactory: Virtual corrections use inconsistent conventions on finite terms.\n"
<< Exception::runerror;
}
}
// prepare dipole insertion operators
if ( virtualContributions() ) {
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= DipoleRepository::insertionIOperators(dipoleSet()).begin();
virt != DipoleRepository::insertionIOperators(dipoleSet()).end(); ++virt ) {
(**virt).factory(this);
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= DipoleRepository::insertionPKOperators(dipoleSet()).begin();
virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) {
(**virt).factory(this);
}
}
}
// prepare the real emission matrix elements
if ( realContributions() || meCorrectionsOnly() ||
(showerApproximation() && virtualContributions()) ||
(showerApproximation() && loopSimCorrections()) ) {
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator real
= realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) {
prepareME(*real);
}
}
// start creating matrix elements
MEs().clear();
// setup born and virtual contributions
if ( bornContributions() || virtualContributions() ) {
generator()->log() << "preparing Born"
<< (virtualContributions() ? " and virtual" : "")
<< " matrix elements.\n" << flush;
}
if ( (bornContributions() && !virtualContributions()) ||
(bornContributions() && meCorrectionsOnly()) ||
(bornContributions() && virtualContributions() && independentVirtuals()) ) {
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born ) {
if ( (**born).onlyOneLoop() )
continue;
Ptr<MatchboxMEBase>::ptr bornme = (**born).cloneMe();
string pname = fullName() + "/" + (**born).name();
if ( virtualContributions() && independentVirtuals() )
pname += ".Born";
if ( ! (generator()->preinitRegister(bornme,pname) ) )
throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing."
<< Exception::runerror;
if ( bornme->isOLPTree() ) {
int id = orderOLPProcess(bornme->subProcess(),
(**born).matchboxAmplitude(),
ProcessType::treeME2);
bornme->olpProcess(ProcessType::treeME2,id);
}
bornme->needsNoCorrelations();
bornme->cloneDependencies();
MEs().push_back(bornme);
}
}
if ( bornContributions() && !loopInducedMEs().empty() ) {
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator looped
= loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) {
Ptr<MatchboxMEBase>::ptr loopme = (**looped).cloneMe();
string pname = fullName() + "/" + (**looped).name() + ".LoopInduced";
if ( ! (generator()->preinitRegister(loopme,pname) ) )
throw Exception() << "MatchboxFactory: Matrix element " << pname << " already existing."
<< Exception::runerror;
if ( loopme->isOLPTree() ) {
int id = orderOLPProcess(loopme->subProcess(),
(**looped).matchboxAmplitude(),
ProcessType::loopInducedME2);
loopme->olpProcess(ProcessType::loopInducedME2,id);
}
loopme->needsNoCorrelations();
loopme->cloneDependencies();
MEs().push_back(loopme);
}
}
if ( needTrueVirtuals ) {
bornVirtualMEs().clear();
boost::progress_display * progressBar =
new boost::progress_display(bornMEs().size(),generator()->log());
if ( thePoleData != "" )
if ( thePoleData[thePoleData.size()-1] != '/' )
thePoleData += "/";
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born ) {
Ptr<MatchboxMEBase>::ptr nlo = (**born).cloneMe();
string pname = fullName() + "/" + (**born).name();
if ( !independentVirtuals() && !(!bornContributions() && virtualContributions()) )
pname += ".BornVirtual";
else if ( independentPKs() && !nlo->onlyOneLoop() )
pname += ".VirtualVI";
else
pname += ".Virtual";
if ( ! (generator()->preinitRegister(nlo,pname) ) )
throw Exception() << "MatchboxFactory: NLO ME " << pname << " already existing."
<< Exception::runerror;
nlo->virtuals().clear();
if ( !nlo->onlyOneLoop() ) {
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= virtuals().begin(); virt != virtuals().end(); ++virt ) {
if ( (**virt).apply((**born).diagrams().front()->partons()) )
nlo->virtuals().push_back(*virt);
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= DipoleRepository::insertionIOperators(dipoleSet()).begin();
virt != DipoleRepository::insertionIOperators(dipoleSet()).end(); ++virt ) {
if ( (**virt).apply((**born).diagrams().front()->partons()) )
nlo->virtuals().push_back(*virt);
}
if ( !independentVirtuals() || ( independentVirtuals() && !independentPKs() ) ) {
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= DipoleRepository::insertionPKOperators(dipoleSet()).begin();
virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) {
if ( (**virt).apply((**born).diagrams().front()->partons()) )
nlo->virtuals().push_back(*virt);
}
}
if ( nlo->virtuals().empty() )
throw Exception() << "MatchboxFactory: No insertion operators have been found for "
<< (**born).name() << "\n"
<< Exception::runerror;
if ( checkPoles() ) {
if ( !virtualsAreExpanded ) {
throw Exception()
<< "MatchboxFactory: Cannot check epsilon poles if virtuals are not in `expanded' convention.\n"
<< Exception::runerror;
}
}
}
if ( !bornContributions() || independentVirtuals() ) {
nlo->doOneLoopNoBorn();
} else {
nlo->doOneLoop();
}
if ( nlo->isOLPLoop() ) {
int id = orderOLPProcess(nlo->subProcess(),
(**born).matchboxAmplitude(),
ProcessType::oneLoopInterference);
nlo->olpProcess(ProcessType::oneLoopInterference,id);
if ( !nlo->onlyOneLoop() && nlo->needsOLPCorrelators() ) {
id = orderOLPProcess(nlo->subProcess(),
(**born).matchboxAmplitude(),
ProcessType::colourCorrelatedME2);
nlo->olpProcess(ProcessType::colourCorrelatedME2,id);
}
}
nlo->needsCorrelations();
nlo->cloneDependencies();
bornVirtualMEs().push_back(nlo);
MEs().push_back(nlo);
if ( independentVirtuals() && independentPKs() && !nlo->onlyOneLoop() ) {
Ptr<MatchboxMEBase>::ptr nlopk = (**born).cloneMe();
string pnamepk = fullName() + "/" + (**born).name();
pnamepk += ".VirtualPK";
if ( ! (generator()->preinitRegister(nlopk,pnamepk) ) )
throw Exception() << "MatchboxFactory: NLO ME " << pnamepk << " already existing."
<< Exception::runerror;
nlopk->virtuals().clear();
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= DipoleRepository::insertionPKOperators(dipoleSet()).begin();
virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) {
if ( (**virt).apply((**born).diagrams().front()->partons()) )
nlopk->virtuals().push_back(*virt);
}
if ( !nlopk->virtuals().empty() ) {
nlopk->doOneLoopNoBorn();
nlopk->doOneLoopNoLoops();
if ( nlopk->isOLPLoop() ) {
int id = orderOLPProcess(nlopk->subProcess(),
(**born).matchboxAmplitude(),
ProcessType::treeME2);
nlopk->olpProcess(ProcessType::treeME2,id);
if ( nlopk->needsOLPCorrelators() ) {
id = orderOLPProcess(nlopk->subProcess(),
(**born).matchboxAmplitude(),
ProcessType::colourCorrelatedME2);
nlopk->olpProcess(ProcessType::colourCorrelatedME2,id);
}
}
nlopk->needsCorrelations();
nlopk->cloneDependencies();
bornVirtualMEs().push_back(nlopk);
MEs().push_back(nlopk);
}
}
++(*progressBar);
}
delete progressBar;
generator()->log() << "---------------------------------------------------\n"
<< flush;
}
theSplittingDipoles.clear();
set<cPDVector> bornProcs;
if ( showerApproximation() ) {
if ( showerApproximation()->needsSplittingGenerator() ) {
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born )
for ( MEBase::DiagramVector::const_iterator d = (**born).diagrams().begin();
d != (**born).diagrams().end(); ++d )
bornProcs.insert((**d).partons());
}
}
if ( realContributions() || meCorrectionsOnly() ||
(showerApproximation() && virtualContributions()) ||
(showerApproximation() && loopSimCorrections()) ) {
generator()->log() << "preparing subtracted matrix elements.\n" << flush;
if ( theSubtractionData != "" )
if ( theSubtractionData[theSubtractionData.size()-1] != '/' )
theSubtractionData += "/";
subtractedMEs().clear();
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born ) {
if ( (**born).onlyOneLoop() )
continue;
(**born).needsCorrelations();
if ( (**born).isOLPTree() ) {
int id = orderOLPProcess((**born).subProcess(),
(**born).matchboxAmplitude(),
ProcessType::colourCorrelatedME2);
(**born).olpProcess(ProcessType::colourCorrelatedME2,id);
bool haveGluon = false;
for ( PDVector::const_iterator p = (**born).subProcess().legs.begin();
p != (**born).subProcess().legs.end(); ++p )
if ( (**p).id() == 21 ) {
haveGluon = true;
break;
}
if ( haveGluon ) {
id = orderOLPProcess((**born).subProcess(),
(**born).matchboxAmplitude(),
ProcessType::spinColourCorrelatedME2);
(**born).olpProcess(ProcessType::spinColourCorrelatedME2,id);
}
if ( showerApproximation() ) {
id = orderOLPProcess((**born).subProcess(),
(**born).matchboxAmplitude(),
ProcessType::treeME2);
(**born).olpProcess(ProcessType::treeME2,id);
}
}
}
boost::progress_display * progressBar =
new boost::progress_display(realEmissionMEs().size(),generator()->log());
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator real
= realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) {
Ptr<SubtractedME>::ptr sub = new_ptr(SubtractedME());
string pname = fullName() + "/" + (**real).name() + ".SubtractedReal";
if ( ! (generator()->preinitRegister(sub,pname) ) )
throw Exception() << "MatchboxFactory: Subtracted ME " << pname << " already existing."
<< Exception::runerror;
sub->factory(this);
(**real).needsNoCorrelations();
if ( (**real).isOLPTree() ) {
int id = orderOLPProcess((**real).subProcess(),
(**real).matchboxAmplitude(),
ProcessType::treeME2);
(**real).olpProcess(ProcessType::treeME2,id);
}
sub->head(*real);
sub->dependent().clear();
sub->getDipoles();
if ( sub->dependent().empty() ) {
// finite real contribution
if ( realContributions() ) {
Ptr<MatchboxMEBase>::ptr fme =
dynamic_ptr_cast<Ptr<MatchboxMEBase>::ptr>(sub->head())->cloneMe();
string qname = fullName() + "/" + (**real).name() + ".FiniteReal";
if ( ! (generator()->preinitRegister(fme,qname) ) )
throw Exception() << "MatchboxFactory: ME " << qname << " already existing."
<< Exception::runerror;
MEs().push_back(fme);
finiteRealMEs().push_back(fme);
}
sub->head(tMEPtr());
++(*progressBar);
continue;
}
if ( realEmissionScales() )
sub->doRealEmissionScales();
subtractedMEs().push_back(sub);
if ( realContributions() )
if ( !showerApproximation() || (showerApproximation() && showerApproximation()->hasHEvents()) )
MEs().push_back(sub);
if ( showerApproximation() ) {
if ( virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections() ) {
Ptr<SubtractedME>::ptr subv = new_ptr(*sub);
string vname = sub->fullName() + ".SubtractionIntegral";
if ( ! (generator()->preinitRegister(subv,vname) ) )
throw Exception() << "MatchboxFactory: Subtracted ME " << vname << " already existing."
<< Exception::runerror;
subv->cloneDependencies(vname);
subv->doVirtualShowerSubtraction();
subtractedMEs().push_back(subv);
MEs().push_back(subv);
}
if ( loopSimCorrections() ) {
Ptr<SubtractedME>::ptr subv = new_ptr(*sub);
string vname = sub->fullName() + ".SubtractionIntegral";
if ( ! (generator()->preinitRegister(subv,vname) ) )
throw Exception() << "MatchboxFactory: Subtracted ME " << vname << " already existing."
<< Exception::runerror;
subv->cloneDependencies(vname);
subv->doLoopSimSubtraction();
subtractedMEs().push_back(subv);
MEs().push_back(subv);
}
sub->doRealShowerSubtraction();
if ( showerApproximation()->needsSplittingGenerator() )
for ( set<cPDVector>::const_iterator p = bornProcs.begin();
p != bornProcs.end(); ++p ) {
vector<Ptr<SubtractionDipole>::ptr> sdip = sub->splitDipoles(*p);
set<Ptr<SubtractionDipole>::ptr>& dips = theSplittingDipoles[*p];
copy(sdip.begin(),sdip.end(),inserter(dips,dips.begin()));
}
}
++(*progressBar);
}
delete progressBar;
generator()->log() << "---------------------------------------------------\n"
<< flush;
}
if ( !theSplittingDipoles.empty() ) {
map<Ptr<SubtractionDipole>::ptr,Ptr<SubtractionDipole>::ptr> cloneMap;
for ( map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::const_iterator sd = theSplittingDipoles.begin();
sd != theSplittingDipoles.end(); ++sd ) {
for ( set<Ptr<SubtractionDipole>::ptr>::const_iterator d = sd->second.begin();
d != sd->second.end(); ++d ) {
cloneMap[*d] = Ptr<SubtractionDipole>::ptr();
}
}
for ( map<Ptr<SubtractionDipole>::ptr,Ptr<SubtractionDipole>::ptr>::iterator cd =
cloneMap.begin(); cd != cloneMap.end(); ++cd ) {
Ptr<SubtractionDipole>::ptr cloned = cd->first->cloneMe();
string dname = cd->first->fullName() + ".splitting";
if ( ! (generator()->preinitRegister(cloned,dname)) )
throw Exception() << "MatchboxFactory: Dipole '" << dname << "' already existing."
<< Exception::runerror;
cloned->cloneDependencies();
cloned->showerApproximation(Ptr<ShowerApproximation>::tptr());
cloned->doSplitting();
cd->second = cloned;
}
for ( map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::iterator sd = theSplittingDipoles.begin();
sd != theSplittingDipoles.end(); ++sd ) {
set<Ptr<SubtractionDipole>::ptr> cloned;
for ( set<Ptr<SubtractionDipole>::ptr>::iterator d = sd->second.begin();
d != sd->second.end(); ++d ) {
cloned.insert(cloneMap[*d]);
}
sd->second = cloned;
}
}
if ( !externalAmplitudes().empty() ) {
generator()->log() << "Initializing external amplitudes.\n" << flush;
for ( set<Ptr<MatchboxAmplitude>::tptr>::const_iterator ext =
externalAmplitudes().begin(); ext != externalAmplitudes().end(); ++ext ) {
if ( !(**ext).initializeExternal() ) {
throw Exception() << "Failed to initialize amplitude '" << (**ext).name() << "'\n"
<< Exception::runerror;
}
}
generator()->log() << "---------------------------------------------------\n"
<< flush;
}
if ( !olpProcesses().empty() ) {
generator()->log() << "Initializing one-loop provider(s).\n" << flush;
map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> > olps;
for ( map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> >::const_iterator
oit = olpProcesses().begin(); oit != olpProcesses().end(); ++oit ) {
olps[oit->first] = oit->second;
}
for ( map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> >::const_iterator
olpit = olps.begin(); olpit != olps.end(); ++olpit ) {
if ( !olpit->first->startOLP(olpit->second) ) {
throw Exception() << "MatchboxFactory: Failed to start OLP for amplitude '" << olpit->first->name() << "'\n"
<< Exception::runerror;
}
}
generator()->log() << "---------------------------------------------------\n"
<< flush;
}
generator()->log() << "Process setup finished.\n" << flush;
ranSetup = true;
}
}
void MatchboxFactory::SplittingChannel::print(ostream& os) const {
os << "--- SplittingChannel setup -----------------------------------------------------\n";
os << " Born process ";
const StandardXComb& bxc = *bornXComb;
os << bxc.mePartonData()[0]->PDGName() << " "
<< bxc.mePartonData()[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator p = bxc.mePartonData().begin() + 2;
p != bxc.mePartonData().end(); ++p ) {
os << (**p).PDGName() << " ";
}
os << "\n";
os << " to real emission process ";
const StandardXComb& rxc = *realXComb;
os << rxc.mePartonData()[0]->PDGName() << " "
<< rxc.mePartonData()[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator p = rxc.mePartonData().begin() + 2;
p != rxc.mePartonData().end(); ++p ) {
os << (**p).PDGName() << " ";
}
os << "\n";
os << " with dipole:\n";
dipole->print(os);
os << "---------------------------------------------------\n";
os << flush;
}
list<MatchboxFactory::SplittingChannel>
MatchboxFactory::getSplittingChannels(tStdXCombPtr xcptr) const {
if ( xcptr->lastProjector() )
xcptr = xcptr->lastProjector();
const StandardXComb& xc = *xcptr;
cPDVector proc = xc.mePartonData();
map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::const_iterator splitEntries
= splittingDipoles().find(proc);
list<SplittingChannel> res;
if ( splitEntries == splittingDipoles().end() )
return res;
const set<Ptr<SubtractionDipole>::ptr>& splitDipoles = splitEntries->second;
SplittingChannel channel;
if ( !splitDipoles.empty() ) {
Ptr<MatchboxMEBase>::tptr bornME =
const_ptr_cast<Ptr<MatchboxMEBase>::tptr>((**splitDipoles.begin()).underlyingBornME());
channel.bornXComb =
bornME->makeXComb(xc.maxEnergy(),xc.particles(),xc.eventHandlerPtr(),
const_ptr_cast<tSubHdlPtr>(xc.subProcessHandler()),
xc.pExtractor(),xc.CKKWHandler(),
xc.partonBins(),xc.cuts(),xc.diagrams(),xc.mirror(),
PartonPairVec());
}
for ( set<Ptr<SubtractionDipole>::ptr>::const_iterator sd =
splitDipoles.begin(); sd != splitDipoles.end(); ++sd ) {
channel.dipole = *sd;
vector<StdXCombPtr> realXCombs = (**sd).makeRealXCombs(channel.bornXComb);
for ( vector<StdXCombPtr>::const_iterator rxc = realXCombs.begin();
rxc != realXCombs.end(); ++rxc ) {
channel.realXComb = *rxc;
if ( showerApproximation()->needsTildeXCombs() ) {
channel.tildeXCombs.clear();
assert(!channel.dipole->partnerDipoles().empty());
for ( vector<Ptr<SubtractionDipole>::tptr>::const_iterator p =
channel.dipole->partnerDipoles().begin();
p != channel.dipole->partnerDipoles().end(); ++p ) {
StdXCombPtr txc = channel.dipole->makeBornXComb(channel.realXComb);
if ( txc )
channel.tildeXCombs.push_back(txc);
}
}
res.push_back(channel);
}
}
if ( initVerbose() ) {
generator()->log()
<< "--- MatchboxFactory splitting channels ----------------------------------------------\n";
const StandardXComb& bxc = *xcptr;
generator()->log() << " hard process handled is: ";
generator()->log() << bxc.mePartonData()[0]->PDGName() << " "
<< bxc.mePartonData()[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator p = bxc.mePartonData().begin() + 2;
p != bxc.mePartonData().end(); ++p ) {
generator()->log() << (**p).PDGName() << " ";
}
generator()->log() << "\n";
for ( list<MatchboxFactory::SplittingChannel>::const_iterator sp =
res.begin(); sp != res.end(); ++sp ) {
sp->print(generator()->log());
}
generator()->log()
<< "--------------------------------------------------------\n"
<< flush;
}
return res;
}
void MatchboxFactory::print(ostream& os) const {
os << "--- MatchboxFactory setup -----------------------------------------------------------\n";
if ( !amplitudes().empty() ) {
os << " generated Born matrix elements:\n";
for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator m = bornMEs().begin();
m != bornMEs().end(); ++m ) {
(**m).print(os);
}
os << flush;
os << " generated real emission matrix elements:\n";
for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator m = realEmissionMEs().begin();
m != realEmissionMEs().end(); ++m ) {
(**m).print(os);
}
os << flush;
}
os << " generated Born+virtual matrix elements:\n";
for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator bv
= bornVirtualMEs().begin(); bv != bornVirtualMEs().end(); ++bv ) {
(**bv).print(os);
}
os << " generated subtracted matrix elements:\n";
for ( vector<Ptr<SubtractedME>::ptr>::const_iterator sub
= subtractedMEs().begin(); sub != subtractedMEs().end(); ++sub ) {
os << " '" << (**sub).name() << "'\n";
}
os << "---------------------------------------------------\n";
os << flush;
}
void MatchboxFactory::summary(ostream& os) const {
os << "\n\n================================================================================\n"
<< " Matchbox hard process summary\n"
<< "================================================================================\n\n";
os << " Electro-weak parameter summary:\n"
<< "---------------------------------------------------\n\n";
os << " Electro-weak scheme : ";
switch ( SM().ewScheme() ) {
case 0: os << "Default"; break;
case 1: os << "GMuScheme"; break;
case 2: os << "alphaMZScheme"; break;
case 3: os << "NoMass"; break;
case 4: os << "mW"; break;
case 5: os << "mZ"; break;
case 6: os << "Independent"; break;
case 7: os << "FeynRulesUFO"; break;
default: assert(false);
}
os << "\n";
os << " alphaEM is "
<< (SM().ewScheme() == 0 && !theFixedQEDCouplings ? "running" : "fixed at alphaEM(m(Z))") << "\n";
if ( SM().ewScheme() == 0 && !theFixedQEDCouplings )
os << " alphaEM is running at " << SM().alphaEMPtr()->nloops()
<< " loops\n\n";
else
os << "\n";
os << (SM().ewScheme() != 0 ? " Tree level relations " : " Best values ")
<< "yield:\n\n"
<< " m(Z)/GeV = "
<< getParticleData(ParticleID::Z0)->hardProcessMass()/GeV
<< "\n"
<< " g(Z)/GeV = "
<< getParticleData(ParticleID::Z0)->hardProcessWidth()/GeV
<< "\n"
<< " m(W)/GeV = "
<< getParticleData(ParticleID::Wplus)->hardProcessMass()/GeV
<< "\n"
<< " g(W)/GeV = "
<< getParticleData(ParticleID::Wplus)->hardProcessWidth()/GeV
<< "\n"
<< " m(H)/GeV = "
<< getParticleData(ParticleID::h0)->hardProcessMass()/GeV
<< "\n"
<< " g(H)/GeV = "
<< getParticleData(ParticleID::h0)->hardProcessWidth()/GeV
<< "\n"
<< " alphaEM(m(Z)) = "
<< SM().alphaEMME(sqr(getParticleData(ParticleID::Z0)->hardProcessMass())) << "\n"
<< " sin^2(theta) = " << SM().sin2ThetaW()
<< "\n"
<< " GeV^2 GF = " << GeV2*SM().fermiConstant()
<< "\n\n";
os << " Quark masses and widths are:\n"
<< "---------------------------------------------------\n\n"
<< " m(u)/GeV = " << getParticleData(ParticleID::u)->hardProcessMass()/GeV << "\n"
<< " m(d)/GeV = " << getParticleData(ParticleID::d)->hardProcessMass()/GeV << "\n"
<< " m(c)/GeV = " << getParticleData(ParticleID::c)->hardProcessMass()/GeV << "\n"
<< " m(s)/GeV = " << getParticleData(ParticleID::s)->hardProcessMass()/GeV << "\n"
<< " m(t)/GeV = " << getParticleData(ParticleID::t)->hardProcessMass()/GeV << "\n"
<< " g(t)/GeV = " << getParticleData(ParticleID::t)->hardProcessWidth()/GeV << "\n"
<< " m(b)/GeV = " << getParticleData(ParticleID::b)->hardProcessMass()/GeV << "\n\n";
os << " Lepton masses and widths are:\n"
<< "---------------------------------------------------\n\n"
<< " m(n_e)/GeV = " << getParticleData(ParticleID::nu_e)->hardProcessMass()/GeV << "\n"
<< " m(e)/GeV = " << getParticleData(ParticleID::eminus)->hardProcessMass()/GeV << "\n"
<< " m(n_mu)/GeV = " << getParticleData(ParticleID::nu_mu)->hardProcessMass()/GeV << "\n"
<< " m(mu)/GeV = " << getParticleData(ParticleID::muminus)->hardProcessMass()/GeV << "\n"
<< " m(nu_tau)/GeV = " << getParticleData(ParticleID::nu_tau)->hardProcessMass()/GeV << "\n"
<< " m(tau)/GeV = " << getParticleData(ParticleID::tauminus)->hardProcessMass()/GeV << "\n\n";
os << " Strong coupling summary:\n"
<< "---------------------------------------------------\n\n";
os << " alphaS is";
if ( !theFixedCouplings ) {
os << " running at " << SM().alphaSPtr()->nloops()
<< " loops with\n"
<< " alphaS(m(Z)) = " << SM().alphaSPtr()->value(sqr(getParticleData(ParticleID::Z0)->mass()))
<< "\n\n";
} else {
os << " fixed at "
<< SM().alphaS()
<< "\n\n";
}
if ( !theFixedCouplings ) {
os << " flavour thresholds are matched at\n";
for ( long id = 1; id <= 6; ++id ) {
os << " m(" << id << ")/GeV = "
<< (SM().alphaSPtr()->quarkMasses().empty() ?
getParticleData(id)->mass()/GeV :
SM().alphaSPtr()->quarkMasses()[id-1]/GeV)
<< "\n";
}
}
os << "\n\n" << flush;
}
void MatchboxFactory::doinit() {
theIsMatchboxRun() = true;
if ( RunDirectories::empty() )
RunDirectories::pushRunId(generator()->runName());
setup();
if ( theShowerApproximation )
theShowerApproximation->init();
if ( initVerbose() && !ranSetup )
print(Repository::clog());
Ptr<StandardEventHandler>::tptr eh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler());
assert(eh);
if ( initVerbose() && !ranSetup ) {
assert(standardModel());
standardModel()->init();
summary(Repository::clog());
}
SubProcessHandler::doinit();
}
void MatchboxFactory::doinitrun() {
theIsMatchboxRun() = true;
if ( theShowerApproximation )
theShowerApproximation->initrun();
Ptr<StandardEventHandler>::tptr eh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler());
assert(eh);
SubProcessHandler::doinitrun();
}
const string& MatchboxFactory::buildStorage() {
return RunDirectories::buildStorage();
}
const string& MatchboxFactory::runStorage() {
return RunDirectories::runStorage();
}
void MatchboxFactory::persistentOutput(PersistentOStream & os) const {
os << theDiagramGenerator << theProcessData
<< theNLight
<< theNLightJetVec << theNHeavyJetVec << theNLightProtonVec
<< theOrderInAlphaS << theOrderInAlphaEW
<< theBornContributions << theVirtualContributions
<< theRealContributions << theIndependentVirtuals << theIndependentPKs
<< theSubProcessGroups
<< thePhasespace << theScaleChoice
<< theFactorizationScaleFactor << theRenormalizationScaleFactor
<< theFixedCouplings << theFixedQEDCouplings << theVetoScales
<< theAmplitudes
<< theBornMEs << theVirtuals << theRealEmissionMEs << theLoopInducedMEs
<< theBornVirtualMEs << theSubtractedMEs << theFiniteRealMEs
<< theVerbose<<theDiagramWeightVerbose
<<theDiagramWeightVerboseNBins
<< theInitVerbose << theSubtractionData << theSubtractionPlotType
<< theSubtractionScatterPlot << thePoleData
<< theParticleGroups << processes << loopInducedProcesses << realEmissionProcesses
<< theShowerApproximation << theSplittingDipoles
<< theRealEmissionScales << theAllProcesses
<< theOLPProcesses << theExternalAmplitudes
<< theSelectedAmplitudes << theDeselectedAmplitudes
<< theDipoleSet << theReweighters << thePreweighters
<< theMECorrectionsOnly<< theLoopSimCorrections<<theHighestVirtualsize << ranSetup
<< theIncoming << theFirstPerturbativePDF << theSecondPerturbativePDF
<< inProductionMode << theSpinCorrelations << theAlphaParameter
<< theEnforceChargeConservation << theEnforceColourConservation
<< theEnforceLeptonNumberConservation << theEnforceQuarkNumberConservation
<< theLeptonFlavourDiagonal << theQuarkFlavourDiagonal;
}
void MatchboxFactory::persistentInput(PersistentIStream & is, int) {
is >> theDiagramGenerator >> theProcessData
>> theNLight
>> theNLightJetVec >> theNHeavyJetVec >> theNLightProtonVec
>> theOrderInAlphaS >> theOrderInAlphaEW
>> theBornContributions >> theVirtualContributions
>> theRealContributions >> theIndependentVirtuals >> theIndependentPKs
>> theSubProcessGroups
>> thePhasespace >> theScaleChoice
>> theFactorizationScaleFactor >> theRenormalizationScaleFactor
>> theFixedCouplings >> theFixedQEDCouplings >> theVetoScales
>> theAmplitudes
>> theBornMEs >> theVirtuals >> theRealEmissionMEs >> theLoopInducedMEs
>> theBornVirtualMEs >> theSubtractedMEs >> theFiniteRealMEs
>> theVerbose >> theDiagramWeightVerbose
>> theDiagramWeightVerboseNBins
>> theInitVerbose >> theSubtractionData >> theSubtractionPlotType
>> theSubtractionScatterPlot >> thePoleData
>> theParticleGroups >> processes >> loopInducedProcesses >> realEmissionProcesses
>> theShowerApproximation >> theSplittingDipoles
>> theRealEmissionScales >> theAllProcesses
>> theOLPProcesses >> theExternalAmplitudes
>> theSelectedAmplitudes >> theDeselectedAmplitudes
>> theDipoleSet >> theReweighters >> thePreweighters
>> theMECorrectionsOnly>> theLoopSimCorrections>>theHighestVirtualsize >> ranSetup
>> theIncoming >> theFirstPerturbativePDF >> theSecondPerturbativePDF
>> inProductionMode >> theSpinCorrelations >> theAlphaParameter
>> theEnforceChargeConservation >> theEnforceColourConservation
>> theEnforceLeptonNumberConservation >> theEnforceQuarkNumberConservation
>> theLeptonFlavourDiagonal >> theQuarkFlavourDiagonal;
}
string MatchboxFactory::startParticleGroup(string name) {
particleGroupName = StringUtils::stripws(name);
particleGroup.clear();
return "";
}
string MatchboxFactory::endParticleGroup(string) {
if ( particleGroup.empty() )
throw Exception() << "MatchboxFactory: Empty particle group."
<< Exception::runerror;
particleGroups()[particleGroupName] = particleGroup;
particleGroup.clear();
return "";
}
vector<string> MatchboxFactory::parseProcess(string in) {
vector<string> process = StringUtils::split(in);
if ( process.size() < 3 )
throw Exception() << "MatchboxFactory: Invalid process."
<< Exception::runerror;
for ( vector<string>::iterator p = process.begin();
p != process.end(); ++p ) {
*p = StringUtils::stripws(*p);
}
vector<string> pprocess;
for ( vector<string>::const_iterator p = process.begin();
p != process.end(); ++p ) {
if ( *p == "->" )
continue;
pprocess.push_back(*p);
}
return pprocess;
}
string MatchboxFactory::doProcess(string in) {
processes.push_back(parseProcess(in));
return "";
}
string MatchboxFactory::doLoopInducedProcess(string in) {
loopInducedProcesses.push_back(parseProcess(in));
return "";
}
string MatchboxFactory::doSingleRealProcess(string in) {
realEmissionProcesses.push_back(parseProcess(in));
return "";
}
struct SortPID {
inline bool operator()(PDPtr a, PDPtr b) const {
return a->id() < b->id();
}
};
//
// @TODO
//
// SP: After improving this for standard model process building this should
// actually got into a separate process builder class or something along these
// lines to have it better factored for use with BSM models.
//
//
set<PDVector> MatchboxFactory::
makeSubProcesses(const vector<string>& proc) const {
if ( proc.empty() )
throw Exception() << "MatchboxFactory: No process specified."
<< Exception::runerror;
vector<PDVector> groups;
typedef map<string,PDVector>::const_iterator GroupIterator;
for ( vector<string>::const_iterator gr = proc.begin();
gr != proc.end(); ++gr ) {
GroupIterator git = particleGroups().find(*gr);
if ( git == particleGroups().end() ) {
throw Exception() << "MatchboxFactory: Particle group '"
<< *gr << "' not defined." << Exception::runerror;
}
groups.push_back(git->second);
}
vector<size_t> counts(groups.size(),0);
PDVector proto(groups.size());
set<PDVector> allProcs;
while ( true ) {
for ( size_t k = 0; k < groups.size(); ++k )
proto[k] = groups[k][counts[k]];
int charge = 0;
int colour = 0;
int nleptons = 0;
int nquarks = 0;
int ncolour = 0;
int nleptonsGen[4];
int nquarksGen[4];
for ( size_t i = 0; i < 4; ++i ) {
nleptonsGen[i] = 0;
nquarksGen[i] = 0;
}
for ( size_t k = 0; k < proto.size(); ++k ) {
int sign = k > 1 ? 1 : -1;
charge += sign * proto[k]->iCharge();
colour += sign * proto[k]->iColour();
if ( abs(proto[k]->id()) <= 8 ) {
int generation = (abs(proto[k]->id()) - 1)/2;
nquarks += sign * ( proto[k]->id() < 0 ? -1 : 1);
nquarksGen[generation] += sign * ( proto[k]->id() < 0 ? -1 : 1);
}
if ( abs(proto[k]->id()) > 10 &&
abs(proto[k]->id()) <= 18 ) {
int generation = (abs(proto[k]->id()) - 11)/2;
nleptons += sign * ( proto[k]->id() < 0 ? -1 : 1);
nleptonsGen[generation] += sign * ( proto[k]->id() < 0 ? -1 : 1);
}
if ( proto[k]->coloured() )
++ncolour;
}
bool pass = true;
if ( theEnforceChargeConservation )
pass &= (charge == 0);
if ( theEnforceColourConservation )
pass &= (colour % 8 == 0) && (ncolour > 1);
if ( theEnforceLeptonNumberConservation ) {
pass &= (nleptons == 0);
if ( theLeptonFlavourDiagonal ) {
for ( size_t i = 0; i < 4; ++i )
pass &= (nleptonsGen[i] == 0);
}
}
if ( theEnforceQuarkNumberConservation ) {
pass &= (nquarks == 0);
if ( theQuarkFlavourDiagonal ) {
for ( size_t i = 0; i < 4; ++i )
pass &= (nquarksGen[i] == 0);
}
}
if ( pass ) {
for ( int i = 0; i < 2; ++i ) {
if ( proto[i]->coloured() &&
proto[i]->hardProcessMass() != ZERO )
throw Exception()
<< "Inconsistent flavour scheme detected with massive incoming "
<< proto[i]->PDGName() << ". Check your setup."
<< Exception::runerror;
}
sort(proto.begin()+2,proto.end(),SortPID());
allProcs.insert(proto);
}
vector<size_t>::reverse_iterator c = counts.rbegin();
vector<PDVector>::const_reverse_iterator g = groups.rbegin();
while ( c != counts.rend() ) {
if ( ++(*c) == g->size() ) {
*c = 0;
++c; ++g;
} else {
break;
}
}
if ( c == counts.rend() )
break;
}
return allProcs;
}
void MatchboxFactory::Init() {
static ClassDocumentation<MatchboxFactory> documentation
("MatchboxFactory",
"NLO QCD corrections have been calculated "
"using Matchbox \\cite{Platzer:2011bc}, \\cite{Matchbox:2015}",
"%\\cite{Platzer:2011bc}\n"
"\\bibitem{Platzer:2011bc}\n"
"S.~Platzer and S.~Gieseke,\n"
"``Dipole Showers and Automated NLO Matching in Herwig,''\n"
"arXiv:1109.6256 [hep-ph].\n"
"%%CITATION = ARXIV:1109.6256;%%\n"
"%\\cite{Matchbox:2015}\n"
"\\bibitem{Matchbox:2015}\n"
"Herwig collaboration,\n"
"``Precision LHC Event Generation with Herwig,''\n"
"in preparation.");
static Reference<MatchboxFactory,Tree2toNGenerator> interfaceDiagramGenerator
("DiagramGenerator",
"Set the diagram generator.",
&MatchboxFactory::theDiagramGenerator, false, false, true, true, false);
static Reference<MatchboxFactory,ProcessData> interfaceProcessData
("ProcessData",
"Set the process data object to be used.",
&MatchboxFactory::theProcessData, false, false, true, true, false);
static Parameter<MatchboxFactory,unsigned int> interfaceOrderInAlphaS
("OrderInAlphaS",
"The order in alpha_s to consider.",
&MatchboxFactory::theOrderInAlphaS, 0, 0, 0,
false, false, Interface::lowerlim);
static Parameter<MatchboxFactory,unsigned int> interfaceOrderInAlphaEW
("OrderInAlphaEW",
"The order in alpha_EW",
&MatchboxFactory::theOrderInAlphaEW, 2, 0, 0,
false, false, Interface::lowerlim);
static Switch<MatchboxFactory,bool> interfaceBornContributions
("BornContributions",
"Switch on or off the Born contributions.",
&MatchboxFactory::theBornContributions, true, false, false);
static SwitchOption interfaceBornContributionsOn
(interfaceBornContributions,
"On",
"Switch on Born contributions.",
true);
static SwitchOption interfaceBornContributionsOff
(interfaceBornContributions,
"Off",
"Switch off Born contributions.",
false);
static Switch<MatchboxFactory,bool> interfaceVirtualContributions
("VirtualContributions",
"Switch on or off the virtual contributions.",
&MatchboxFactory::theVirtualContributions, true, false, false);
static SwitchOption interfaceVirtualContributionsOn
(interfaceVirtualContributions,
"On",
"Switch on virtual contributions.",
true);
static SwitchOption interfaceVirtualContributionsOff
(interfaceVirtualContributions,
"Off",
"Switch off virtual contributions.",
false);
static Switch<MatchboxFactory,bool> interfaceRealContributions
("RealContributions",
"Switch on or off the real contributions.",
&MatchboxFactory::theRealContributions, true, false, false);
static SwitchOption interfaceRealContributionsOn
(interfaceRealContributions,
"On",
"Switch on real contributions.",
true);
static SwitchOption interfaceRealContributionsOff
(interfaceRealContributions,
"Off",
"Switch off real contributions.",
false);
static Switch<MatchboxFactory,bool> interfaceIndependentVirtuals
("IndependentVirtuals",
"Switch on or off virtual contributions as separate subprocesses.",
&MatchboxFactory::theIndependentVirtuals, true, false, false);
static SwitchOption interfaceIndependentVirtualsOn
(interfaceIndependentVirtuals,
"On",
"Switch on virtual contributions as separate subprocesses.",
true);
static SwitchOption interfaceIndependentVirtualsOff
(interfaceIndependentVirtuals,
"Off",
"Switch off virtual contributions as separate subprocesses.",
false);
static Switch<MatchboxFactory,bool> interfaceIndependentPKs
("IndependentPKOperators",
"Switch on or off PK oeprators as separate subprocesses.",
&MatchboxFactory::theIndependentPKs, true, false, false);
static SwitchOption interfaceIndependentPKsOn
(interfaceIndependentPKs,
"On",
"Switch on PK operators as separate subprocesses.",
true);
static SwitchOption interfaceIndependentPKsOff
(interfaceIndependentPKs,
"Off",
"Switch off PK operators as separate subprocesses.",
false);
static Switch<MatchboxFactory,bool> interfaceSubProcessGroups
("SubProcessGroups",
"Switch on or off production of sub-process groups.",
&MatchboxFactory::theSubProcessGroups, false, false, false);
static SwitchOption interfaceSubProcessGroupsOn
(interfaceSubProcessGroups,
"On",
"On",
true);
static SwitchOption interfaceSubProcessGroupsOff
(interfaceSubProcessGroups,
"Off",
"Off",
false);
static Reference<MatchboxFactory,MatchboxPhasespace> interfacePhasespace
("Phasespace",
"Set the phasespace generator.",
&MatchboxFactory::thePhasespace, false, false, true, true, false);
static Reference<MatchboxFactory,MatchboxScaleChoice> interfaceScaleChoice
("ScaleChoice",
"Set the scale choice object.",
&MatchboxFactory::theScaleChoice, false, false, true, true, false);
static Parameter<MatchboxFactory,double> interfaceFactorizationScaleFactor
("FactorizationScaleFactor",
"The factorization scale factor.",
&MatchboxFactory::theFactorizationScaleFactor, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<MatchboxFactory,double> interfaceRenormalizationScaleFactor
("RenormalizationScaleFactor",
"The renormalization scale factor.",
&MatchboxFactory::theRenormalizationScaleFactor, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
static Switch<MatchboxFactory,bool> interfaceFixedCouplings
("FixedCouplings",
"Switch on or off fixed couplings.",
&MatchboxFactory::theFixedCouplings, true, false, false);
static SwitchOption interfaceFixedCouplingsOn
(interfaceFixedCouplings,
"On",
"On",
true);
static SwitchOption interfaceFixedCouplingsOff
(interfaceFixedCouplings,
"Off",
"Off",
false);
static Switch<MatchboxFactory,bool> interfaceFixedQEDCouplings
("FixedQEDCouplings",
"Switch on or off fixed QED couplings.",
&MatchboxFactory::theFixedQEDCouplings, true, false, false);
static SwitchOption interfaceFixedQEDCouplingsOn
(interfaceFixedQEDCouplings,
"On",
"On",
true);
static SwitchOption interfaceFixedQEDCouplingsOff
(interfaceFixedQEDCouplings,
"Off",
"Off",
false);
static Switch<MatchboxFactory,bool> interfaceVetoScales
("VetoScales",
"Switch on or setting veto scales.",
&MatchboxFactory::theVetoScales, false, false, false);
static SwitchOption interfaceVetoScalesOn
(interfaceVetoScales,
"On",
"On",
true);
static SwitchOption interfaceVetoScalesOff
(interfaceVetoScales,
"Off",
"Off",
false);
static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceAmplitudes
("Amplitudes",
"The amplitude objects.",
&MatchboxFactory::theAmplitudes, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxMEBase> interfaceBornMEs
("BornMEs",
"The Born matrix elements to be used",
&MatchboxFactory::theBornMEs, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxInsertionOperator> interfaceVirtuals
("Virtuals",
"The virtual corrections to include",
&MatchboxFactory::theVirtuals, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxMEBase> interfaceRealEmissionMEs
("RealEmissionMEs",
"The RealEmission matrix elements to be used",
&MatchboxFactory::theRealEmissionMEs, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxMEBase> interfaceBornVirtuals
("BornVirtualMEs",
"The generated Born/virtual contributions",
&MatchboxFactory::theBornVirtualMEs, -1, false, true, true, true, false);
static RefVector<MatchboxFactory,SubtractedME> interfaceSubtractedMEs
("SubtractedMEs",
"The generated subtracted real emission contributions",
&MatchboxFactory::theSubtractedMEs, -1, false, true, true, true, false);
static RefVector<MatchboxFactory,MatchboxMEBase> interfaceFiniteRealMEs
("FiniteRealMEs",
"The generated finite real contributions",
&MatchboxFactory::theFiniteRealMEs, -1, false, true, true, true, false);
static Switch<MatchboxFactory,bool> interfaceVerbose
("Verbose",
"Print full infomation on each evaluated phase space point.",
&MatchboxFactory::theVerbose, false, false, false);
static SwitchOption interfaceVerboseOn
(interfaceVerbose,
"On",
"On",
true);
static SwitchOption interfaceVerboseOff
(interfaceVerbose,
"Off",
"Off",
false);
static Switch<MatchboxFactory,bool> interfaceVerboseDia
("DiagramWeightVerbose",
"Print full infomation on each evaluated phase space point.",
&MatchboxFactory::theDiagramWeightVerbose, false, false, false);
static SwitchOption interfaceVerboseDiaOn
(interfaceVerboseDia,
"On",
"On",
true);
static SwitchOption interfaceVerboseDiaOff
(interfaceVerboseDia,
"Off",
"Off",
false);
static Parameter<MatchboxFactory,int> interfaceVerboseDiaNbins
("DiagramWeightVerboseNBins",
"No. of Bins for DiagramWeightVerbose Diagrams.",
&MatchboxFactory::theDiagramWeightVerboseNBins, 200, 0, 0,
false, false, Interface::lowerlim);
static Switch<MatchboxFactory,bool> interfaceInitVerbose
("InitVerbose",
"Print setup information.",
&MatchboxFactory::theInitVerbose, false, false, false);
static SwitchOption interfaceInitVerboseOn
(interfaceInitVerbose,
"On",
"On",
true);
static SwitchOption interfaceInitVerboseOff
(interfaceInitVerbose,
"Off",
"Off",
false);
static Parameter<MatchboxFactory,string> interfaceSubtractionData
("SubtractionData",
"Prefix for subtraction check data.",
&MatchboxFactory::theSubtractionData, "",
false, false);
static Switch<MatchboxFactory,int> interfaceSubtractionPlotType
("SubtractionPlotType",
"Switch for controlling what kind of plot is generated for checking the subtraction",
&MatchboxFactory::theSubtractionPlotType, 1, false, false);
static SwitchOption interfaceSubtractionPlotTypeLinearRatio
(interfaceSubtractionPlotType,
"LinRatio",
"Switch on the linear plot of the ratio",
1);
static SwitchOption interfaceSubtractionPlotTypeLogRelDiff
(interfaceSubtractionPlotType,
"LogRelDiff",
"Switch on the logarithmic plot of the relative difference",
2);
static Switch<MatchboxFactory,bool> interfaceSubtractionScatterPlot
("SubtractionScatterPlot",
"Switch for controlling whether subtraction data should be plotted for each phase space point individually",
&MatchboxFactory::theSubtractionScatterPlot, false, false, false);
static SwitchOption interfaceSubtractionScatterPlotOff
(interfaceSubtractionScatterPlot,
"Off", "Switch off the scatter plot", false);
static SwitchOption interfaceSubtractionScatterPlotOn
(interfaceSubtractionScatterPlot,
"On", "Switch on the scatter plot", true);
static Parameter<MatchboxFactory,string> interfacePoleData
("PoleData",
"Prefix for subtraction check data.",
&MatchboxFactory::thePoleData, "",
false, false);
static RefVector<MatchboxFactory,ParticleData> interfaceParticleGroup
("ParticleGroup",
"The particle group just started.",
&MatchboxFactory::particleGroup, -1, false, false, true, false, false);
static Command<MatchboxFactory> interfaceStartParticleGroup
("StartParticleGroup",
"Start a particle group.",
&MatchboxFactory::startParticleGroup, false);
static Command<MatchboxFactory> interfaceEndParticleGroup
("EndParticleGroup",
"End a particle group.",
&MatchboxFactory::endParticleGroup, false);
static Command<MatchboxFactory> interfaceProcess
("Process",
"Set the process(es) to consider.",
&MatchboxFactory::doProcess, false);
static Command<MatchboxFactory> interfaceLoopInducedProcess
("LoopInducedProcess",
"Set the loop induced process(es) to consider.",
&MatchboxFactory::doLoopInducedProcess, false);
static Command<MatchboxFactory> interfaceSingleRealProcess
("SingleRealProcess",
"Set the real emission process(es) to consider.",
&MatchboxFactory::doSingleRealProcess, false);
static Reference<MatchboxFactory,ShowerApproximation> interfaceShowerApproximation
("ShowerApproximation",
"Set the shower approximation to be considered.",
&MatchboxFactory::theShowerApproximation, false, false, true, true, false);
static Switch<MatchboxFactory,bool> interfaceRealEmissionScales
("RealEmissionScales",
"Switch on or off calculation of subtraction scales from real emission kinematics.",
&MatchboxFactory::theRealEmissionScales, false, false, false);
static SwitchOption interfaceRealEmissionScalesOn
(interfaceRealEmissionScales,
"On",
"On",
true);
static SwitchOption interfaceRealEmissionScalesOff
(interfaceRealEmissionScales,
"Off",
"Off",
false);
static Switch<MatchboxFactory,bool> interfaceAllProcesses
("AllProcesses",
"Consider all processes up to a maximum coupling order specified by the coupling order interfaces.",
&MatchboxFactory::theAllProcesses, false, false, false);
static SwitchOption interfaceAllProcessesYes
(interfaceAllProcesses,
"Yes",
"Include all processes.",
true);
static SwitchOption interfaceAllProcessesNo
(interfaceAllProcesses,
"No",
"Only consider processes matching the exact order in the couplings.",
false);
static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceSelectAmplitudes
("SelectAmplitudes",
"The amplitude objects to be favoured in clashing responsibilities.",
&MatchboxFactory::theSelectedAmplitudes, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceDeselectAmplitudes
("DeselectAmplitudes",
"The amplitude objects to be disfavoured in clashing responsibilities.",
&MatchboxFactory::theDeselectedAmplitudes, -1, false, false, true, true, false);
static Switch<MatchboxFactory,int> interfaceDipoleSet
("DipoleSet",
"The set of subtraction terms to be considered.",
&MatchboxFactory::theDipoleSet, 0, false, false);
static SwitchOption interfaceDipoleSetCataniSeymour
(interfaceDipoleSet,
"CataniSeymour",
"Use default Catani-Seymour dipoles.",
0);
static RefVector<MatchboxFactory,ReweightBase> interfaceReweighters
("Reweighters",
"Reweight objects for matrix elements.",
&MatchboxFactory::theReweighters, -1, false, false, true, false, false);
static RefVector<MatchboxFactory,ReweightBase> interfacePreweighters
("Preweighters",
"Preweight objects for matrix elements.",
&MatchboxFactory::thePreweighters, -1, false, false, true, false, false);
static Switch<MatchboxFactory,bool> interfaceMECorrectionsOnly
("MECorrectionsOnly",
"Prepare only ME corrections, but no NLO calculation.",
&MatchboxFactory::theMECorrectionsOnly, false, false, false);
static SwitchOption interfaceMECorrectionsOnlyYes
(interfaceMECorrectionsOnly,
"Yes",
"Produce only ME corrections.",
true);
static SwitchOption interfaceMECorrectionsOnlyNo
(interfaceMECorrectionsOnly,
"No",
"Produce full NLO.",
false);
static Switch<MatchboxFactory,bool> interfaceLoopSimCorrections
("LoopSimCorrections",
"Prepare LoopSim corrections.",
&MatchboxFactory::theLoopSimCorrections, false, false, false);
static SwitchOption interfaceLoopSimCorrectionsYes
(interfaceLoopSimCorrections,
"Yes",
"Produce loopsim corrections.",
true);
static SwitchOption interfaceLoopSimCorrectionsNo
(interfaceLoopSimCorrections,
"No",
"Produce full NLO.",
false);
static Switch<MatchboxFactory,bool> interfaceFirstPerturbativePDF
("FirstPerturbativePDF",
"",
&MatchboxFactory::theFirstPerturbativePDF, true, false, false);
static SwitchOption interfaceFirstPerturbativePDFYes
(interfaceFirstPerturbativePDF,
"Yes",
"",
true);
static SwitchOption interfaceFirstPerturbativePDFNo
(interfaceFirstPerturbativePDF,
"No",
"",
false);
static Switch<MatchboxFactory,bool> interfaceSecondPerturbativePDF
("SecondPerturbativePDF",
"",
&MatchboxFactory::theSecondPerturbativePDF, true, false, false);
static SwitchOption interfaceSecondPerturbativePDFYes
(interfaceSecondPerturbativePDF,
"Yes",
"",
true);
static SwitchOption interfaceSecondPerturbativePDFNo
(interfaceSecondPerturbativePDF,
"No",
"",
false);
static Command<MatchboxFactory> interfaceProductionMode
("ProductionMode",
"Switch this factory to production mode.",
&MatchboxFactory::doProductionMode, false);
static Switch<MatchboxFactory,bool> interfaceSpinCorrelations
("SpinCorrelations",
"Fill information for the spin correlations, if possible.",
&MatchboxFactory::theSpinCorrelations, false, false, false);
static SwitchOption interfaceSpinCorrelationsYes
(interfaceSpinCorrelations,
"Yes",
"",
true);
static SwitchOption interfaceSpinCorrelationsNo
(interfaceSpinCorrelations,
"No",
"",
false);
static Parameter<MatchboxFactory,double> interfaceAlphaParameter
("AlphaParameter",
"Nagy-AlphaParameter.",
&MatchboxFactory::theAlphaParameter, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
static Switch<MatchboxFactory,bool> interfaceEnforceChargeConservation
("EnforceChargeConservation",
"Enforce charge conservation while generating the hard process.",
&MatchboxFactory::theEnforceChargeConservation, true, false, false);
static SwitchOption interfaceEnforceChargeConservationYes
(interfaceEnforceChargeConservation,
"Yes",
"Enforce charge conservation.",
true);
static SwitchOption interfaceEnforceChargeConservationNo
(interfaceEnforceChargeConservation,
"No",
"Do not enforce charge conservation.",
false);
static Switch<MatchboxFactory,bool> interfaceEnforceColourConservation
("EnforceColourConservation",
"Enforce colour conservation while generating the hard process.",
&MatchboxFactory::theEnforceColourConservation, false, false, false);
static SwitchOption interfaceEnforceColourConservationYes
(interfaceEnforceColourConservation,
"Yes",
"Enforce colour conservation.",
true);
static SwitchOption interfaceEnforceColourConservationNo
(interfaceEnforceColourConservation,
"No",
"Do not enforce colour conservation.",
false);
static Switch<MatchboxFactory,bool> interfaceEnforceLeptonNumberConservation
("EnforceLeptonNumberConservation",
"Enforce lepton number conservation while generating the hard process.",
&MatchboxFactory::theEnforceLeptonNumberConservation, false, false, false);
static SwitchOption interfaceEnforceLeptonNumberConservationYes
(interfaceEnforceLeptonNumberConservation,
"Yes",
"Enforce lepton number conservation.",
true);
static SwitchOption interfaceEnforceLeptonNumberConservationNo
(interfaceEnforceLeptonNumberConservation,
"No",
"Do not enforce lepton number conservation.",
false);
static Switch<MatchboxFactory,bool> interfaceEnforceQuarkNumberConservation
("EnforceQuarkNumberConservation",
"Enforce quark number conservation while generating the hard process.",
&MatchboxFactory::theEnforceQuarkNumberConservation, false, false, false);
static SwitchOption interfaceEnforceQuarkNumberConservationYes
(interfaceEnforceQuarkNumberConservation,
"Yes",
"Enforce quark number conservation.",
true);
static SwitchOption interfaceEnforceQuarkNumberConservationNo
(interfaceEnforceQuarkNumberConservation,
"No",
"Do not enforce quark number conservation.",
false);
static Switch<MatchboxFactory,bool> interfaceLeptonFlavourDiagonal
("LeptonFlavourDiagonal",
"Assume that lepton interactions are flavour diagonal while generating the hard process.",
&MatchboxFactory::theLeptonFlavourDiagonal, false, false, false);
static SwitchOption interfaceLeptonFlavourDiagonalYes
(interfaceLeptonFlavourDiagonal,
"Yes",
"Assume that lepton interactions are flavour diagonal.",
true);
static SwitchOption interfaceLeptonFlavourDiagonalNo
(interfaceLeptonFlavourDiagonal,
"No",
"Do not assume that lepton interactions are flavour diagonal.",
false);
static Switch<MatchboxFactory,bool> interfaceQuarkFlavourDiagonal
("QuarkFlavourDiagonal",
"Assume that quark interactions are flavour diagonal while generating the hard process.",
&MatchboxFactory::theQuarkFlavourDiagonal, false, false, false);
static SwitchOption interfaceQuarkFlavourDiagonalYes
(interfaceQuarkFlavourDiagonal,
"Yes",
"Assume that quark interactions are flavour diagonal.",
true);
static SwitchOption interfaceQuarkFlavourDiagonalNo
(interfaceQuarkFlavourDiagonal,
"No",
"Do not assume that quark interactions are flavour diagonal.",
false);
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<MatchboxFactory,SubProcessHandler>
describeHerwigMatchboxFactory("Herwig::MatchboxFactory", "Herwig.so");
diff --git a/MatrixElement/Matchbox/Utility/ColourBasis.cc b/MatrixElement/Matchbox/Utility/ColourBasis.cc
--- a/MatrixElement/Matchbox/Utility/ColourBasis.cc
+++ b/MatrixElement/Matchbox/Utility/ColourBasis.cc
@@ -1,1278 +1,1282 @@
// -*- C++ -*-
//
// ColourBasis.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ColourBasis class.
//
#include "ColourBasis.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Handlers/SamplerBase.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <iterator>
using std::ostream_iterator;
#include "DiagramDrawer.h"
using namespace Herwig;
using boost::numeric::ublas::trans;
// default gcc on SLC6 confuses this with std::conj,
// use explicit namespacing in the code instead
//
// using boost::numeric::ublas::conj;
using boost::numeric::ublas::row;
using boost::numeric::ublas::column;
using boost::numeric::ublas::prod;
Ptr<MatchboxFactory>::tptr ColourBasis::factory() const {
return theFactory;
}
void ColourBasis::factory(Ptr<MatchboxFactory>::tptr f) {
theFactory = f;
}
ColourBasis::ColourBasis()
: theLargeN(false), didRead(false), didWrite(false), theSearchPath("") {}
ColourBasis::~ColourBasis() {
for ( map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >::iterator cl =
theColourLineMap.begin(); cl != theColourLineMap.end(); ++cl ) {
for ( vector<ColourLines*>::iterator c = cl->second.begin();
c != cl->second.end(); ++c ) {
if ( *c )
delete *c;
}
}
theColourLineMap.clear();
}
void ColourBasis::clear() {
theLargeN = false;
theNormalOrderedLegs.clear();
theIndexMap.clear();
theScalarProducts.clear();
theCharges.clear();
theChargeNonZeros.clear();
theCorrelators.clear();
theFlowMap.clear();
theColourLineMap.clear();
theOrderingStringIdentifiers.clear();
theOrderingIdentifiers.clear();
didRead = false;
didWrite = false;
tmp.clear();
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
bool ColourBasis::colourConnected(const cPDVector& sub,
const vector<PDT::Colour>& basis,
const pair<int,bool>& i,
const pair<int,bool>& j,
size_t a) const {
// translate process to basis ids
map<cPDVector,map<size_t,size_t> >::const_iterator trans
= indexMap().find(sub);
assert(trans != indexMap().end());
int idColoured = i.second ? j.first : i.first;
idColoured = trans->second.find(idColoured)->second;
int idAntiColoured = i.second ? i.first : j.first;
idAntiColoured = trans->second.find(idAntiColoured)->second;
return colourConnected(basis,idColoured,idAntiColoured,a);
}
const string& ColourBasis::orderingString(const cPDVector& sub,
const map<size_t,size_t>& colourToAmplitude,
size_t tensorId) {
map<size_t,string>& tensors = theOrderingStringIdentifiers[sub];
if ( !tensors.empty() ) {
assert(tensors.find(tensorId) != tensors.end());
return tensors[tensorId];
}
const set<vector<size_t> >& xordering = ordering(sub,colourToAmplitude,tensorId);
ostringstream os;
os << "[";
for ( set<vector<size_t> >::const_iterator t = xordering.begin();
t != xordering.end(); ++t ) {
os << "[";
for ( vector<size_t>::const_iterator s = t->begin();
s != t->end(); ++s ) {
os << *s << (s != --t->end() ? "," : "");
}
os << "]" << (t != --xordering.end() ? "," : "");
}
os << "]";
tensors[tensorId] = os.str();
return tensors[tensorId];
}
const set<vector<size_t> >& ColourBasis::ordering(const cPDVector& sub,
const map<size_t,size_t>& colourToAmplitude,
size_t tensorId, size_t shift) {
map<size_t,set<vector<size_t> > >& tensors = theOrderingIdentifiers[sub];
if ( !tensors.empty() ) {
assert(tensors.find(tensorId) != tensors.end());
return tensors[tensorId];
}
const vector<PDT::Colour>& basisId = normalOrderedLegs(sub);
map<size_t,vector<vector<size_t> > > labels = basisList(basisId);
for ( map<size_t,vector<vector<size_t> > >::const_iterator t =
labels.begin(); t != labels.end(); ++t ) {
set<vector<size_t> > xordering;
for ( vector<vector<size_t> >::const_iterator s = t->second.begin();
s != t->second.end(); ++s ) {
vector<size_t> crossed;
for ( vector<size_t>::const_iterator l = s->begin();
l != s->end(); ++l ) {
map<size_t,size_t>::const_iterator trans =
colourToAmplitude.find(*l);
assert(trans != colourToAmplitude.end());
crossed.push_back(trans->second + shift);
}
xordering.insert(crossed);
}
tensors[t->first] = xordering;
}
assert(tensors.find(tensorId) != tensors.end());
return tensors[tensorId];
}
vector<PDT::Colour> ColourBasis::normalOrderMap(const cPDVector& sub) {
vector<PDT::Colour> allLegs = projectColour(sub);
vector<PDT::Colour> legs = normalOrder(allLegs);
if ( allLegs[0] == PDT::Colour3 )
allLegs[0] = PDT::Colour3bar;
else if ( allLegs[0] == PDT::Colour3bar )
allLegs[0] = PDT::Colour3;
if ( allLegs[1] == PDT::Colour3 )
allLegs[1] = PDT::Colour3bar;
else if ( allLegs[1] == PDT::Colour3bar )
allLegs[1] = PDT::Colour3;
if ( theIndexMap.find(sub) == theIndexMap.end() ) {
map<size_t,size_t> trans;
vector<PDT::Colour> checkLegs = legs;
size_t n = checkLegs.size();
for ( size_t i = 0; i < allLegs.size(); ++i ) {
size_t j = 0;
while ( checkLegs[j] != allLegs[i] ) {
++j; if ( j == n ) break;
}
if ( j == n ) continue;
trans[i] = j;
checkLegs[j] = PDT::ColourUndefined;
}
theIndexMap[sub] = trans;
}
return legs;
}
const vector<PDT::Colour>& ColourBasis::normalOrderedLegs(const cPDVector& sub) const {
static vector<PDT::Colour> empty;
map<cPDVector,vector<PDT::Colour> >::const_iterator n =
theNormalOrderedLegs.find(sub);
if ( n != theNormalOrderedLegs.end() )
return n->second;
return empty;
}
size_t ColourBasis::prepare(const cPDVector& sub,
bool noCorrelations) {
vector<PDT::Colour> legs = normalOrderMap(sub);
bool doPrepare = false;
if ( theNormalOrderedLegs.find(sub) == theNormalOrderedLegs.end() )
theNormalOrderedLegs[sub] = legs;
if ( theScalarProducts.find(legs) == theScalarProducts.end() )
doPrepare = true;
if ( doPrepare )
doPrepare = !readBasis(legs);
size_t dim = doPrepare ? prepareBasis(legs) : theScalarProducts[legs].size1();
if ( theCharges.find(legs) != theCharges.end() )
return dim;
if ( !doPrepare && noCorrelations )
return dim;
symmetric_matrix<double,upper>& sp =
theScalarProducts.insert(make_pair(legs,symmetric_matrix<double,upper>(dim,dim))).first->second;
for ( size_t a = 0; a < dim; ++a )
for ( size_t b = a; b < dim; ++b )
sp(a,b) = scalarProduct(a,b,legs);
if ( noCorrelations )
return dim;
vector<PDT::Colour> legsPlus = legs;
legsPlus.push_back(PDT::Colour8);
legsPlus = normalOrder(legsPlus);
bool doPreparePlus = theScalarProducts.find(legsPlus) == theScalarProducts.end();
size_t dimPlus = doPreparePlus ? prepareBasis(legsPlus) : theScalarProducts[legsPlus].size1();
symmetric_matrix<double,upper>& spPlus =
doPreparePlus ?
theScalarProducts.insert(make_pair(legsPlus,symmetric_matrix<double,upper>(dimPlus,dimPlus))).first->second :
theScalarProducts[legsPlus];
if ( doPreparePlus ) {
for ( size_t a = 0; a < dimPlus; ++a )
for ( size_t b = a; b < dimPlus; ++b )
spPlus(a,b) = scalarProduct(a,b,legsPlus);
}
typedef map<size_t,compressed_matrix<double> > cMap;
cMap& cm = theCharges.insert(make_pair(legs,cMap())).first->second;
typedef map<size_t,vector<pair<size_t,size_t> > > ccMap;
ccMap& ccm = theChargeNonZeros.insert(make_pair(legs,ccMap())).first->second;
tmp.resize(dimPlus,dim);
for ( size_t i = 0; i < legs.size(); ++i ) {
size_t nonZero = 0;
vector<pair<size_t,size_t> > nonZeros;
for ( size_t a = 0; a < dimPlus; ++a )
for ( size_t b = 0; b < dim; ++b ) {
tmp(a,b) = tMatrixElement(i,a,b,legsPlus,legs);
if ( tmp(a,b) != 0. ) {
++nonZero;
nonZeros.push_back(make_pair(a,b));
}
}
ccm.insert(make_pair(i,nonZeros));
compressed_matrix<double>& tm =
cm.insert(make_pair(i,compressed_matrix<double>(dimPlus,dim,nonZero))).first->second;
for ( size_t a = 0; a < dimPlus; ++a )
for ( size_t b = 0; b < dim; ++b ) {
if ( tmp(a,b) != 0. )
tm(a,b) = tmp(a,b);
}
}
map<pair<size_t,size_t>,symmetric_matrix<double,upper> >& xm = theCorrelators[legs];
for ( size_t i = 0; i < legs.size(); ++i )
for ( size_t j = i+1; j < legs.size(); ++j ) {
symmetric_matrix<double,upper>& mm =
xm.insert(make_pair(make_pair(i,j),symmetric_matrix<double,upper>(dim,dim))).first->second;
chargeProduct(cm[i],ccm[i],spPlus,cm[j],ccm[j],mm);
}
return dim;
}
void ColourBasis::chargeProduct(const compressed_matrix<double>& ti,
const vector<pair<size_t,size_t> >& tiNonZero,
const symmetric_matrix<double,upper>& X,
const compressed_matrix<double>& tj,
const vector<pair<size_t,size_t> >& tjNonZero,
symmetric_matrix<double,upper>& result) const {
for ( size_t i = 0; i < result.size1(); ++i )
for ( size_t j = i; j < result.size1(); ++j )
result(i,j) = 0.;
for ( vector<pair<size_t,size_t> >::const_iterator i = tiNonZero.begin();
i != tiNonZero.end(); ++i )
for ( vector<pair<size_t,size_t> >::const_iterator j = tjNonZero.begin();
j != tjNonZero.end(); ++j ) {
if ( j->second < i->second )
continue;
result(i->second,j->second) +=
ti(i->first,i->second)*tj(j->first,j->second)*X(i->first,j->first);
}
}
void ColourBasis::chargeProductAdd(const compressed_matrix<double>& ti,
const vector<pair<size_t,size_t> >& tiNonZero,
const matrix<Complex>& X,
const compressed_matrix<double>& tj,
const vector<pair<size_t,size_t> >& tjNonZero,
matrix<Complex>& result,
double factor) const {
for ( vector<pair<size_t,size_t> >::const_iterator i = tiNonZero.begin();
i != tiNonZero.end(); ++i )
for ( vector<pair<size_t,size_t> >::const_iterator j = tjNonZero.begin();
j != tjNonZero.end(); ++j ) {
result(i->first,j->first) += factor*
ti(i->first,i->second)*tj(j->first,j->second)*X(i->second,j->second);
}
}
string ColourBasis::cfstring(const list<list<pair<int,bool> > >& flow) {
ostringstream out("");
for ( list<list<pair<int,bool> > >::const_iterator line =
flow.begin(); line != flow.end(); ++line ) {
for ( list<pair<int,bool> >::const_iterator node =
line->begin(); node != line->end(); ++node ) {
out << (node->second ? "-" : "") << (node->first+1) << " ";
}
if ( line != --(flow.end()) )
out << ", ";
}
return out.str();
}
vector<string> ColourBasis::makeFlows(Ptr<Tree2toNDiagram>::tcptr diag,
size_t dim) const {
vector<string> res(dim);
list<list<list<pair<int,bool> > > > fdata =
colourFlows(diag);
cPDVector ext;
tcPDVector dext = diag->external();
copy(dext.begin(),dext.end(),back_inserter(ext));
vector<PDT::Colour> colouredLegs =
normalOrder(projectColour(ext));
for ( list<list<list<pair<int,bool> > > >::const_iterator flow =
fdata.begin(); flow != fdata.end(); ++flow ) {
for ( size_t i = 0; i < dim; ++i ) {
bool matches = true;
for ( list<list<pair<int,bool> > >::const_iterator line =
flow->begin(); line != flow->end(); ++line ) {
pair<int,bool> front(diag->externalId(line->front().first),line->front().second);
if ( front.first < 2 )
front.second = !front.second;
pair<int,bool> back(diag->externalId(line->back().first),line->back().second);
if ( back.first < 2 )
back.second = !back.second;
if ( !colourConnected(ext,colouredLegs,front,back,i) ) {
matches = false;
break;
}
}
if ( matches ) {
assert(res[i] == "" &&
"only support colour bases with unique mapping to large-N colour flows");
res[i] = cfstring(*flow);
}
}
}
bool gotone = false;
for ( vector<string>::const_iterator f = res.begin();
f != res.end(); ++f ) {
if ( *f != "" ) {
gotone = true;
break;
}
}
if ( !gotone ) {
generator()->log() << "warning no color flow found for diagram\n";
DiagramDrawer::drawDiag(generator()->log(),*diag);
}
return res;
}
size_t ColourBasis::prepare(const MEBase::DiagramVector& diags,
bool noCorrelations) {
size_t dim = 0;
for ( MEBase::DiagramVector::const_iterator d = diags.begin();
d != diags.end(); ++d ) {
Ptr<Tree2toNDiagram>::tcptr dd = dynamic_ptr_cast<Ptr<Tree2toNDiagram>::ptr>(*d);
assert(dd);
dim = prepare(dd->partons(),noCorrelations);
if ( !haveColourFlows() || theFlowMap.find(dd) != theFlowMap.end() )
continue;
theFlowMap[dd] = makeFlows(dd,dim);
}
return dim;
}
bool matchEnd(int a, pair<int,bool> b,
Ptr<Tree2toNDiagram>::tcptr diag) {
if ( a != b.first )
return false;
if ( b.first != diag->nSpace()-1 ) {
return
!b.second ?
diag->allPartons()[b.first]->hasColour() :
diag->allPartons()[b.first]->hasAntiColour();
} else {
return
!b.second ?
diag->allPartons()[b.first]->hasAntiColour() :
diag->allPartons()[b.first]->hasColour();
}
return false;
}
bool findPath(pair<int,bool> a, pair<int,bool> b,
Ptr<Tree2toNDiagram>::tcptr diag,
list<pair<int,bool> >& path,
bool backward) {
assert(a.first==0 ? !backward : true);
if ( path.empty() )
path.push_back(a);
if ( !backward ) {
if ( diag->children(a.first).first == -1 )
return matchEnd(a.first,b,diag);
pair<int,int> children = diag->children(a.first);
bool cc = (children.first == diag->nSpace()-1);
if ( diag->allPartons()[children.first]->coloured() )
if ( !cc ?
(!a.second ?
diag->allPartons()[children.first]->hasColour() :
diag->allPartons()[children.first]->hasAntiColour()) :
(!a.second ?
diag->allPartons()[children.first]->hasAntiColour() :
diag->allPartons()[children.first]->hasColour()) ) {
pair<int,bool> next(children.first,a.second);
path.push_back(next);
if ( !findPath(next,b,diag,path,false) ) {
path.pop_back();
} else return true;
}
cc = (children.second == diag->nSpace()-1);
if ( diag->allPartons()[children.second]->coloured() )
if ( !cc ?
(!a.second ?
diag->allPartons()[children.second]->hasColour() :
diag->allPartons()[children.second]->hasAntiColour()) :
(!a.second ?
diag->allPartons()[children.second]->hasAntiColour() :
diag->allPartons()[children.second]->hasColour()) ) {
pair<int,bool> next(children.second,a.second);
path.push_back(next);
if ( !findPath(next,b,diag,path,false) ) {
path.pop_back();
} else return true;
}
if ( path.size() == 1 )
path.pop_back();
return false;
} else {
int parent = diag->parent(a.first);
pair<int,int> neighbours = diag->children(parent);
int neighbour = a.first == neighbours.first ? neighbours.second : neighbours.first;
if ( matchEnd(parent,b,diag) ) {
path.push_back(b);
return true;
}
if ( matchEnd(neighbour,b,diag) ) {
path.push_back(b);
return true;
}
if ( diag->allPartons()[neighbour]->coloured() )
if ( a.second ?
diag->allPartons()[neighbour]->hasColour() :
diag->allPartons()[neighbour]->hasAntiColour() ) {
pair<int,bool> next(neighbour,!a.second);
path.push_back(next);
if ( !findPath(next,b,diag,path,false) ) {
path.pop_back();
} else return true;
}
if ( parent == 0 ) {
if ( path.size() == 1 )
path.pop_back();
return false;
}
if ( diag->allPartons()[parent]->coloured() )
if ( !a.second ?
diag->allPartons()[parent]->hasColour() :
diag->allPartons()[parent]->hasAntiColour() ) {
pair<int,bool> next(parent,a.second);
path.push_back(next);
if ( !findPath(next,b,diag,path,true) ) {
path.pop_back();
} else return true;
}
if ( path.size() == 1 )
path.pop_back();
return false;
}
return false;
}
list<pair<int,bool> > ColourBasis::colouredPath(pair<int,bool> a, pair<int,bool> b,
Ptr<Tree2toNDiagram>::tcptr diag) {
list<pair<int,bool> > res;
if ( a.first == b.first )
return res;
bool aIn = (a.first < 2);
bool bIn = (b.first < 2);
if ( (aIn && bIn) || (!aIn && !bIn) )
if ( (a.second && b.second) ||
(!a.second && !b.second) )
return res;
if ( (aIn && !bIn) || (!aIn && bIn) )
if ( (!a.second && b.second) ||
(a.second && !b.second) )
return res;
if ( a.first > b.first )
swap(a,b);
a.first = diag->diagramId(a.first);
b.first = diag->diagramId(b.first);
if ( a.first == diag->nSpace()-1 )
a.second = !a.second;
if ( b.first == diag->nSpace()-1 )
b.second = !b.second;
if ( !findPath(a,b,diag,res,a.first != 0) )
return res;
if ( b.first == diag->nSpace()-1 ) {
res.back().second = !res.back().second;
}
if ( a.first == diag->nSpace()-1 ) {
res.front().second = !res.front().second;
}
return res;
}
list<list<list<pair<int,bool> > > >
ColourBasis::colourFlows(Ptr<Tree2toNDiagram>::tcptr diag) {
vector<pair<int,bool> > connectSource;
vector<pair<int,bool> > connectSink;
for ( size_t i = 0; i != diag->partons().size(); ++i ) {
if ( i < 2 && diag->partons()[i]->hasAntiColour() )
connectSource.push_back(make_pair(i,true));
if ( i < 2 && diag->partons()[i]->hasColour() )
connectSink.push_back(make_pair(i,false));
if ( i > 1 && diag->partons()[i]->hasColour() )
connectSource.push_back(make_pair(i,false));
if ( i > 1 && diag->partons()[i]->hasAntiColour() )
connectSink.push_back(make_pair(i,true));
}
assert(connectSource.size() == connectSink.size());
list<list<list<pair<int,bool> > > > ret;
do {
vector<pair<int,bool> >::iterator source =
connectSource.begin();
vector<pair<int,bool> >::iterator sink =
connectSink.begin();
list<list<pair<int,bool> > > res;
for ( ; source != connectSource.end(); ++source, ++sink ) {
if ( source->first == sink->first ) {
res.clear();
break;
}
list<pair<int,bool> > line =
colouredPath(*source,*sink,diag);
if ( line.empty() ) {
res.clear();
break;
}
res.push_back(line);
}
if ( !res.empty() ) {
// check, if all dressed properly
vector<pair<int,int> > dressed((*diag).allPartons().size(),make_pair(0,0));
for ( size_t p = 0; p < diag->allPartons().size(); ++p ) {
if ( diag->allPartons()[p]->hasColour() &&
!diag->allPartons()[p]->hasAntiColour() )
dressed[p].first = 1;
if ( diag->allPartons()[p]->hasAntiColour() &&
!diag->allPartons()[p]->hasColour() )
dressed[p].second = 1;
if ( diag->allPartons()[p]->hasAntiColour() &&
diag->allPartons()[p]->hasColour() ) {
dressed[p].first = 1; dressed[p].second = 1;
}
}
for ( list<list<pair<int,bool> > >::const_iterator l = res.begin();
l != res.end(); ++l ) {
for ( list<pair<int,bool> >::const_iterator n = l->begin();
n != l->end(); ++n ) {
if ( !(n->second) )
dressed[n->first].first -= 1;
else
dressed[n->first].second -= 1;
}
}
for ( vector<pair<int,int> >::const_iterator d = dressed.begin();
d != dressed.end(); ++d ) {
if ( d->first != 0 || d->second != 0 ) {
res.clear();
break;
}
}
if ( !res.empty() )
ret.push_back(res);
}
} while ( std::next_permutation(connectSink.begin(),connectSink.end()) );
return ret;
}
void ColourBasis::updateColourLines(Ptr<Tree2toNDiagram>::tcptr dd) {
map<Ptr<Tree2toNDiagram>::tcptr,vector<string> >::const_iterator cl =
theFlowMap.find(dd);
assert(cl != theFlowMap.end());
vector<ColourLines*> clines(cl->second.size());
for ( size_t k = 0; k < cl->second.size(); ++k ) {
if ( cl->second[k] == "" ) {
clines[k] = 0;
continue;
}
clines[k] = new ColourLines(cl->second[k]);
}
theColourLineMap[cl->first] = clines;
}
map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >&
ColourBasis::colourLineMap() {
if ( !theColourLineMap.empty() )
return theColourLineMap;
for ( map<Ptr<Tree2toNDiagram>::tcptr,vector<string> >::const_iterator cl =
theFlowMap.begin(); cl != theFlowMap.end(); ++cl ) {
vector<ColourLines*> clines(cl->second.size());
for ( size_t k = 0; k < cl->second.size(); ++k ) {
if ( cl->second[k] == "" ) {
clines[k] = 0;
continue;
}
clines[k] = new ColourLines(cl->second[k]);
}
theColourLineMap[cl->first] = clines;
}
return theColourLineMap;
}
Selector<const ColourLines *> ColourBasis::colourGeometries(tcDiagPtr diag,
const map<vector<int>,CVector>& amps) {
Ptr<Tree2toNDiagram>::tcptr dd =
dynamic_ptr_cast<Ptr<Tree2toNDiagram>::tcptr>(diag);
assert(dd && theFlowMap.find(dd) != theFlowMap.end());
map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >::const_iterator colit =
colourLineMap().find(dd);
if ( colit == colourLineMap().end() ) {
updateColourLines(dd);
colit = colourLineMap().find(dd);
}
const vector<ColourLines*>& cl = colit->second;
Selector<const ColourLines *> sel;
size_t dim = amps.begin()->second.size();
assert(dim == cl.size());
double w = 0.;
for ( size_t i = 0; i < dim; ++i ) {
if ( !cl[i] )
continue;
w = 0.;
for ( map<vector<int>,CVector>::const_iterator a = amps.begin();
a != amps.end(); ++a )
w += real(conj((a->second)(i))*((a->second)(i)));
if ( w > 0. )
sel.insert(w,cl[i]);
}
assert(!sel.empty());
return sel;
}
size_t ColourBasis::tensorIdFromFlow(tcDiagPtr diag, const ColourLines * flow) {
Ptr<Tree2toNDiagram>::tcptr dd =
dynamic_ptr_cast<Ptr<Tree2toNDiagram>::tcptr>(diag);
assert(dd && theFlowMap.find(dd) != theFlowMap.end());
map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >::const_iterator colit =
colourLineMap().find(dd);
if ( colit == colourLineMap().end() ) {
updateColourLines(dd);
colit = colourLineMap().find(dd);
}
const vector<ColourLines*>& cl = colit->second;
size_t res = 0;
for ( ; res < cl.size(); ++res ) {
if ( flow == cl[res] )
break;
}
assert(res < cl.size());
return res;
}
const symmetric_matrix<double,upper>& ColourBasis::scalarProducts(const cPDVector& sub) const {
map<cPDVector,vector<PDT::Colour> >::const_iterator lit =
theNormalOrderedLegs.find(sub);
assert(lit != theNormalOrderedLegs.end());
ScalarProductMap::const_iterator spit =
theScalarProducts.find(lit->second);
assert(spit != theScalarProducts.end());
return spit->second;
}
const compressed_matrix<double>& ColourBasis::charge(const cPDVector& sub, size_t iIn) const {
map<cPDVector,vector<PDT::Colour> >::const_iterator lit =
theNormalOrderedLegs.find(sub);
assert(lit != theNormalOrderedLegs.end());
ChargeMap::const_iterator ct =
theCharges.find(lit->second);
assert(ct != theCharges.end());
map<cPDVector,map<size_t,size_t> >::const_iterator trans
= theIndexMap.find(sub);
assert(trans != theIndexMap.end());
size_t i = trans->second.find(iIn)->second;
map<size_t,compressed_matrix<double> >::const_iterator cit
= ct->second.find(i);
assert(cit != ct->second.end());
return cit->second;
}
const vector<pair<size_t,size_t> >& ColourBasis::chargeNonZero(const cPDVector& sub, size_t iIn) const {
map<cPDVector,vector<PDT::Colour> >::const_iterator lit =
theNormalOrderedLegs.find(sub);
assert(lit != theNormalOrderedLegs.end());
ChargeNonZeroMap::const_iterator ct =
theChargeNonZeros.find(lit->second);
assert(ct != theChargeNonZeros.end());
map<cPDVector,map<size_t,size_t> >::const_iterator trans
= theIndexMap.find(sub);
assert(trans != theIndexMap.end());
size_t i = trans->second.find(iIn)->second;
map<size_t,vector<pair<size_t,size_t> > >::const_iterator cit
= ct->second.find(i);
assert(cit != ct->second.end());
return cit->second;
}
const symmetric_matrix<double,upper>& ColourBasis::correlator(const cPDVector& sub,
const pair<size_t,size_t>& ijIn) const {
map<cPDVector,vector<PDT::Colour> >::const_iterator lit =
theNormalOrderedLegs.find(sub);
assert(lit != theNormalOrderedLegs.end());
CorrelatorMap::const_iterator cit =
theCorrelators.find(lit->second);
assert(cit != theCorrelators.end());
map<cPDVector,map<size_t,size_t> >::const_iterator trans
= theIndexMap.find(sub);
assert(trans != theIndexMap.end());
pair<size_t,size_t> ij(trans->second.find(ijIn.first)->second,
trans->second.find(ijIn.second)->second);
if ( ij.first > ij.second )
swap(ij.first,ij.second);
map<pair<size_t,size_t>,symmetric_matrix<double,upper> >::const_iterator cijit
= cit->second.find(ij);
assert(cijit != cit->second.end());
return cijit->second;
}
double ColourBasis::me2(const cPDVector& sub,
const map<vector<int>,CVector>& amps) const {
const symmetric_matrix<double,upper>& sp = scalarProducts(sub);
double res = 0.;
for ( map<vector<int>,CVector>::const_iterator a = amps.begin();
a != amps.end(); ++a ) {
res += real(inner_prod(boost::numeric::ublas::conj(a->second),prod(sp,a->second)));
}
return res;
}
double ColourBasis::interference(const cPDVector& sub,
const map<vector<int>,CVector>& amps1,
const map<vector<int>,CVector>& amps2) const {
const symmetric_matrix<double,upper>& sp = scalarProducts(sub);
double res = 0.;
map<vector<int>,CVector>::const_iterator a = amps1.begin();
map<vector<int>,CVector>::const_iterator b = amps2.begin();
for ( ; a != amps1.end(); ++a, ++b ) {
assert(a->first == b->first);
res += 2.*real(inner_prod(boost::numeric::ublas::conj(a->second),prod(sp,b->second)));
}
assert(!std::isnan(res));
return res;
}
double ColourBasis::colourCorrelatedME2(const pair<size_t,size_t>& ij,
const cPDVector& sub,
const map<vector<int>,CVector>& amps) const {
const symmetric_matrix<double,upper>& cij = correlator(sub,ij);
double res = 0.;
for ( map<vector<int>,CVector>::const_iterator a = amps.begin();
a != amps.end(); ++a ) {
res += real(inner_prod(boost::numeric::ublas::conj(a->second),prod(cij,a->second)));
}
return res;
}
Complex ColourBasis::interference(const cPDVector& sub,
const CVector& left,
const CVector& right) const {
const symmetric_matrix<double,upper>& sp = scalarProducts(sub);
return inner_prod(boost::numeric::ublas::conj(left),prod(sp,right));
}
Complex ColourBasis::colourCorrelatedInterference(const pair<size_t,size_t>& ij,
const cPDVector& sub,
const CVector& left,
const CVector& right) const {
const symmetric_matrix<double,upper>& cij = correlator(sub,ij);
return inner_prod(boost::numeric::ublas::conj(left),prod(cij,right));
}
double ColourBasis::me2(const cPDVector& sub,
const matrix<Complex>& amp) const {
const symmetric_matrix<double,upper>& sp = scalarProducts(sub);
double tr = 0;
size_t n = amp.size1();
for ( size_t i = 0; i < n; ++i ) {
tr += real(inner_prod(row(sp,i),column(amp,i)));
}
return tr;
}
double ColourBasis::colourCorrelatedME2(const pair<size_t,size_t>& ij,
const cPDVector& sub,
const matrix<Complex>& amp) const {
const symmetric_matrix<double,upper>& cij = correlator(sub,ij);
double tr = 0;
size_t n = amp.size1();
for ( size_t i = 0; i < n; ++i ) {
tr += real(inner_prod(row(cij,i),column(amp,i)));
}
return tr;
}
struct pickColour {
PDT::Colour operator()(tcPDPtr p) const {
return p->iColour();
}
};
vector<PDT::Colour> ColourBasis::projectColour(const cPDVector& sub) const {
vector<PDT::Colour> res(sub.size());
transform(sub.begin(),sub.end(),res.begin(),pickColour());
return res;
}
vector<PDT::Colour> ColourBasis::normalOrder(const vector<PDT::Colour>& legs) const {
vector<PDT::Colour> crosslegs = legs;
if ( crosslegs[0] == PDT::Colour3 )
crosslegs[0] = PDT::Colour3bar;
else if ( crosslegs[0] == PDT::Colour3bar )
crosslegs[0] = PDT::Colour3;
if ( crosslegs[1] == PDT::Colour3 )
crosslegs[1] = PDT::Colour3bar;
else if ( crosslegs[1] == PDT::Colour3bar )
crosslegs[1] = PDT::Colour3;
int n3 = count_if(crosslegs.begin(),crosslegs.end(),matchRep(PDT::Colour3));
int n8 = count_if(crosslegs.begin(),crosslegs.end(),matchRep(PDT::Colour8));
vector<PDT::Colour> ordered(2*n3+n8,PDT::Colour8);
int i = 0;
while ( i < 2*n3 ) {
ordered[i] = PDT::Colour3;
ordered[i+1] = PDT::Colour3bar;
i+=2;
}
return ordered;
}
string ColourBasis::file(const vector<PDT::Colour>& sub) const {
string res = name() + "-";
for ( vector<PDT::Colour>::const_iterator lit = sub.begin();
lit != sub.end(); ++lit ) {
if ( *lit == PDT::Colour3 )
res += "3";
if ( *lit == PDT::Colour3bar )
res += "3bar";
if ( *lit == PDT::Colour8 )
res += "8";
}
if ( largeN() )
res += "largeN";
return res;
}
void ColourBasis::writeBasis(const string& prefix) const {
if ( didWrite )
return;
set<vector<PDT::Colour> > legs;
for ( map<cPDVector,vector<PDT::Colour> >::const_iterator lit
= theNormalOrderedLegs.begin(); lit != theNormalOrderedLegs.end(); ++lit ) {
legs.insert(lit->second);
}
string searchPath = theSearchPath;
if ( searchPath != "" )
if ( *(--searchPath.end()) != '/' )
searchPath += "/";
for ( set<vector<PDT::Colour> >::const_iterator known = legs.begin();
known != legs.end(); ++known ) {
string fname = searchPath + prefix + file(*known) + ".cdat";
- ifstream check(fname.c_str());
- if ( check ) continue;
+ if ( !( SamplerBase::runLevel() == SamplerBase::ReadMode ||
+ SamplerBase::runLevel() == SamplerBase::BuildMode ) ) {
+ ifstream check(fname.c_str());
+ if ( check ) continue;
+ }
ofstream out(fname.c_str());
if ( !out )
throw Exception() << "ColourBasis: Failed to open "
<< fname << " for storing colour basis information."
<< Exception::runerror;
out << setprecision(18);
const symmetric_matrix<double,upper>& sp =
theScalarProducts.find(*known)->second;
write(sp,out);
if ( theCharges.find(*known) != theCharges.end() ) {
out << "#charges\n";
const map<size_t,compressed_matrix<double> >& tm =
theCharges.find(*known)->second;
const map<size_t,vector<pair<size_t,size_t> > >& tc =
theChargeNonZeros.find(*known)->second;
map<size_t,vector<pair<size_t,size_t> > >::const_iterator kc =
tc.begin();
for ( map<size_t,compressed_matrix<double> >::const_iterator k = tm.begin();
k != tm.end(); ++k, ++kc ) {
out << k->first << "\n";
write(k->second,out,kc->second);
}
const map<pair<size_t,size_t>,symmetric_matrix<double,upper> >& cm =
theCorrelators.find(*known)->second;
for ( map<pair<size_t,size_t>,symmetric_matrix<double,upper> >::const_iterator k =
cm.begin(); k != cm.end(); ++k ) {
out << k->first.first << "\n" << k->first.second << "\n";
write(k->second,out);
}
} else {
out << "#nocharges\n";
}
out << flush;
}
didWrite = true;
}
bool ColourBasis::readBasis(const vector<PDT::Colour>& legs) {
string searchPath = theSearchPath;
if ( searchPath != "" )
if ( *(--searchPath.end()) != '/' )
searchPath += "/";
string fname = searchPath + file(legs) + ".cdat";
ifstream in(fname.c_str());
if ( !in )
return false;
read(theScalarProducts[legs],in);
string tag; in >> tag;
if ( tag != "#nocharges" ) {
for ( size_t k = 0; k < legs.size(); ++k ) {
size_t i; in >> i;
read(theCharges[legs][i],in,theChargeNonZeros[legs][i]);
}
for ( size_t k = 0; k < legs.size()*(legs.size()-1)/2; ++k ) {
size_t i,j; in >> i >> j;
read(theCorrelators[legs][make_pair(i,j)],in);
}
}
readBasisDetails(legs);
return true;
}
void ColourBasis::readBasis() {
if ( didRead )
return;
string searchPath = theSearchPath;
if ( searchPath != "" )
if ( *(--searchPath.end()) != '/' )
searchPath += "/";
set<vector<PDT::Colour> > legs;
for ( map<cPDVector,vector<PDT::Colour> >::const_iterator lit
= theNormalOrderedLegs.begin(); lit != theNormalOrderedLegs.end(); ++lit )
legs.insert(lit->second);
for ( set<vector<PDT::Colour> >::const_iterator known = legs.begin();
known != legs.end(); ++known ) {
if ( theScalarProducts.find(*known) != theScalarProducts.end() )
continue;
string fname = searchPath + file(*known) + ".cdat";
if ( !readBasis(*known) )
throw Exception() << "ColourBasis: Failed to open "
<< fname << " for reading colour basis information."
<< Exception::runerror;
}
didRead = true;
}
void ColourBasis::write(const symmetric_matrix<double,upper>& m, ostream& os) const {
os << m.size1() << "\n";
for ( size_t i = 0; i < m.size1(); ++i )
for ( size_t j = i; j < m.size1(); ++j )
os << m(i,j) << "\n";
os << flush;
}
void ColourBasis::read(symmetric_matrix<double,upper>& m, istream& is) {
size_t s; is >> s;
m.resize(s);
for ( size_t i = 0; i < m.size1(); ++i )
for ( size_t j = i; j < m.size1(); ++j )
is >> m(i,j);
}
void ColourBasis::write(const compressed_matrix<double>& m, ostream& os,
const vector<pair<size_t,size_t> >& nonZeros) const {
os << nonZeros.size() << "\n"
<< m.size1() << "\n"
<< m.size2() << "\n";
for ( vector<pair<size_t,size_t> >::const_iterator nz = nonZeros.begin();
nz != nonZeros.end(); ++nz )
os << nz->first << "\n" << nz->second << "\n"
<< m(nz->first,nz->second) << "\n";
os << flush;
}
void ColourBasis::read(compressed_matrix<double>& m, istream& is,
vector<pair<size_t,size_t> >& nonZeros) {
size_t nonZero, size1, size2;
is >> nonZero >> size1 >> size2;
nonZeros.resize(nonZero);
m = compressed_matrix<double>(size1,size2,nonZero);
for ( size_t k = 0; k < nonZero; ++k ) {
size_t i,j; double val;
is >> i >> j >> val;
nonZeros[k] = make_pair(i,j);
m(i,j) = val;
}
}
void ColourBasis::doinit() {
HandlerBase::doinit();
if ( theSearchPath.empty() && factory() )
theSearchPath = factory()->runStorage();
readBasis();
}
void ColourBasis::dofinish() {
HandlerBase::dofinish();
writeBasis();
}
void ColourBasis::doinitrun() {
HandlerBase::doinitrun();
if ( theSearchPath.empty() && factory() )
theSearchPath = factory()->runStorage();
readBasis();
}
void ColourBasis::persistentOutput(PersistentOStream & os) const {
os << theLargeN << theNormalOrderedLegs
<< theIndexMap << theFlowMap << theOrderingStringIdentifiers
<< theOrderingIdentifiers << theFactory << theSearchPath;
writeBasis();
}
void ColourBasis::persistentInput(PersistentIStream & is, int) {
is >> theLargeN >> theNormalOrderedLegs
>> theIndexMap >> theFlowMap >> theOrderingStringIdentifiers
>> theOrderingIdentifiers >> theFactory >> theSearchPath;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeAbstractClass<ColourBasis,HandlerBase>
describeColourBasis("Herwig::ColourBasis", "Herwig.so");
void ColourBasis::Init() {
static ClassDocumentation<ColourBasis> documentation
("ColourBasis is an interface to a colour basis "
"implementation.");
static Switch<ColourBasis,bool> interfaceLargeN
("LargeN",
"Switch on or off large-N evaluation.",
&ColourBasis::theLargeN, false, false, false);
static SwitchOption interfaceLargeNOn
(interfaceLargeN,
"On",
"Work in N=infinity",
true);
static SwitchOption interfaceLargeNOff
(interfaceLargeN,
"Off",
"Work in N=3",
false);
}
diff --git a/Models/General/BSMModel.cc b/Models/General/BSMModel.cc
--- a/Models/General/BSMModel.cc
+++ b/Models/General/BSMModel.cc
@@ -1,366 +1,410 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the BSMModel class.
//
#include "BSMModel.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/MassGenerator.h"
#include "ThePEG/PDT/WidthGenerator.h"
#include "ThePEG/PDT/DecayMode.h"
+#include "PrototypeVertex.h"
+
using namespace Herwig;
BSMModel::BSMModel() : decayFile_(), readDecays_(true),
topModesFromFile_(false),
tolerance_(1e-6)
{}
void BSMModel::persistentOutput(PersistentOStream & os) const {
os << decayFile_ << topModesFromFile_ << tolerance_;
}
void BSMModel::persistentInput(PersistentIStream & is, int) {
is >> decayFile_ >> topModesFromFile_ >> tolerance_;
}
DescribeAbstractClass<BSMModel,Herwig::StandardModel>
describeHerwigBSMModel("Herwig::BSMModel", "Herwig.so");
void BSMModel::Init() {
static ClassDocumentation<BSMModel> documentation
("The BSMModel class provides a base class for BSM models including the"
" features to read decays in the SLHA format");
static Parameter<BSMModel,string> interfaceDecayFileName
("DecayFileName",
"Name of the file from which to read decays in the SLHA format",
&BSMModel::decayFile_, "",
false, false);
static Switch<BSMModel,bool> interfaceTopModes
("TopModes",
"Whether ro use the Herwig SM top decays or those from the SLHA file",
&BSMModel::topModesFromFile_, false, false, false);
static SwitchOption interfaceTopModesFile
(interfaceTopModes,
"File",
"Take the modes from the files",
true);
static SwitchOption interfaceTopModesHerwig
(interfaceTopModes,
"Herwig",
"Use the SM ones", false);
static Parameter<BSMModel,double> interfaceBRTolerance
("BRTolerance",
"Tolerance for the sum of branching ratios to be difference from one.",
&BSMModel::tolerance_, 1e-6, 1e-8, 0.01,
false, false, Interface::limited);
}
void BSMModel::doinit() {
StandardModel::doinit();
// check if need to read decays
if(decayFile()==""||!readDecays_) return;
decayRead();
}
void BSMModel::decayRead() {
// read decays
CFileLineReader cfile;
cfile.open(decayFile_);
if( !cfile ) throw SetupException()
<< "BSMModel::doinit - An error occurred in opening the "
<< "decay file \"" << decayFile_ << "\"."
<< Exception::runerror;
//Before reading the spectrum/decay files the SM higgs
//decay modes, mass and width generators need to be turned off.
PDPtr h0 = getParticleData(ParticleID::h0);
h0->widthGenerator(WidthGeneratorPtr());
h0->massGenerator(MassGenPtr());
h0->width(ZERO);
h0->stable(true);
DecaySet::const_iterator dit = h0->decayModes().begin();
DecaySet::const_iterator dend = h0->decayModes().end();
for( ; dit != dend; ++dit ) {
generator()->preinitInterface(*dit, "BranchingRatio", "set", "0.");
generator()->preinitInterface(*dit, "OnOff", "set", "Off");
}
// if taking the top modes from the file
// delete the SM stuff
if(topModesFromFile_) {
PDPtr top = getParticleData(ParticleID::t);
top->widthGenerator(WidthGeneratorPtr());
top->massGenerator(MassGenPtr());
DecaySet::const_iterator dit = top->decayModes().begin();
DecaySet::const_iterator dend = top->decayModes().end();
for( ; dit != dend; ++dit ) {
generator()->preinitInterface(*dit, "BranchingRatio", "set", "0.");
generator()->preinitInterface(*dit, "OnOff", "set", "Off");
}
}
// read first line and check if this is a Les Houches event file
cfile.readline();
bool lesHouches = cfile.find("<LesHouchesEvents");
bool reading = !lesHouches;
if(lesHouches) cfile.readline();
// function pointer for putting all characters to lower case.
int (*pf)(int) = tolower;
while (true) {
string line = cfile.getline();
// check for start of slha block in SLHA files
if(lesHouches && !reading) {
if(line.find("<slha")==0) reading = true;
if(!cfile.readline()) break;
continue;
}
// ignore comment lines
if(line[0] == '#') {
if(!cfile.readline()) break;
continue;
}
// make everything lower case
transform(line.begin(), line.end(), line.begin(), pf);
// start of a block
if(line.find("decay") == 0) {
readDecay(cfile, line);
if(!cfile) break;
continue;
}
else if( lesHouches && line.find("</slha") == 0 ) {
break;
}
if(!cfile.readline()) break;
}
}
void BSMModel::readDecay(CFileLineReader & cfile,
string decay) const{
// extract parent PDG code and width
long parent(0);
Energy width(ZERO);
istringstream iss(decay);
string dummy;
iss >> dummy >> parent >> iunit(width, GeV);
PDPtr inpart = getBSMParticleData(parent);
+ // check this ain't a SM particle
+ if(abs(parent)<=5||abs(parent)==23||abs(parent)==24||
+ (abs(parent)>=11&&abs(parent)<=16))
+ cerr << "BSMModel::readDecay() Resetting width of "
+ << inpart->PDGName() << " using SLHA "
+ << "file,\nthis can affect parts of the Standard Model simulation and"
+ << " is strongly discouraged.\n";
if(!topModesFromFile_&&abs(parent)==ParticleID::t) {
cfile.readline();
return;
}
if(!inpart) throw SetupException()
<< "BSMModel::readDecay() - "
<< "A ParticleData object with the PDG code "
<< parent << " does not exist. "
<< Exception::runerror;
inpart->width(width);
if( width > ZERO ) inpart->cTau(hbarc/width);
inpart->widthCut(5.*width);
Energy inMass = inpart->mass();
string prefix(inpart->name() + "->");
double brsum(0.);
unsigned int nmode = 0;
while(cfile.readline()) {
string line = cfile.getline();
line = StringUtils::stripws(line);
// skip comments
if(line[0] == '#') continue;
// reached the end
if( line[0] == 'B' || line[0] == 'b' ||
line[0] == 'D' || line[0] == 'd' ||
line[0] == '<' ) {
cfile.resetline();
break;
}
// read the mode
// get the branching ratio and no of decay products
istringstream is(line);
double brat(0.);
unsigned int nda(0),npr(0);
is >> brat >> nda;
vector<tcPDPtr> products,bosons;
Energy mout(ZERO),moutnoWZ(ZERO);
string tag = prefix;
+ multiset<tcPDPtr,ParticleOrdering> outgoing;
int charge = -inpart->iCharge();
while( true ) {
long t;
is >> t;
if( is.fail() ) break;
if( t == abs(parent) ) {
throw SetupException()
<< "An error occurred while read a decay of the "
<< inpart->PDGName() << ". One of its products has the same PDG code "
<< "as the parent particle. Please check the SLHA file.\n"
<< Exception::runerror;
}
tcPDPtr p = getBSMParticleData(t);
if( !p ) {
throw SetupException()
<< "BSMModel::readDecay() - An unknown PDG code has been encounterd "
<< "while reading a decay mode. ID: " << t
<< Exception::runerror;
}
charge += p->iCharge();
++npr;
- tag += p->name() + ",";
+ outgoing.insert(p);
Energy mass = p->mass();
mout += mass;
if(abs(p->id())==ParticleID::Wplus||p->id()==ParticleID::Z0) {
bosons.push_back(p);
}
else {
products.push_back(p);
moutnoWZ += mass;
}
}
if( npr != nda ) {
throw SetupException()
<< "BSMModel::readDecay - While reading a decay of the "
<< inpart->PDGName() << " from an SLHA file, an inconsistency "
<< "between the number of decay products and the value in "
<< "the 'NDA' column was found. Please check if the spectrum "
<< "file is correct.\n"
<< Exception::warning;
}
- if( npr > 1 ) {
- tag.replace(tag.size() - 1, 1, ";");
- if(charge!=0) {
+
+ // must be at least two decay products
+ if(npr<=1) continue;
+
+ // create the tag
+ for(multiset<tcPDPtr,ParticleOrdering>::iterator it=outgoing.begin();
+ it!=outgoing.end();++it)
+ tag += (**it).name() + ",";
+ tag.replace(tag.size() - 1, 1, ";");
+ if(charge!=0) {
+ cerr << "BSMModel::readDecay() "
+ << "Decay mode " << tag << " read from SLHA file does not conserve charge,"
+ << "\nare you really sure you want to do this?\n";
+ }
+ ++nmode;
+ if(nmode==1) {
+ if(abs(parent)<=5||abs(parent)==23||abs(parent)==24||
+ (abs(parent)>=11&&abs(parent)<=16)) {
+ cerr << "BSMModel::readDecay() Resetting the decays of "
+ << inpart->PDGName() << " using SLHA "
+ << "file,\nthis can affect parts of the Standard Model simulation,"
+ << " give unexpected results and"
+ << " is strongly discouraged.\n";
+ cerr << "Switching off all the internal modes so only those from the SLHA file "
+ << "are used, this may have unintended consequences\n";
+ for(DecaySet::iterator it=inpart->decayModes().begin();
+ it!=inpart->decayModes().end();++it) {
+ generator()->preinitInterface(*it, "OnOff", "set", "Off");
+ }
+ if(inpart->CC()) {
+ for(DecaySet::iterator it=inpart->CC()->decayModes().begin();
+ it!=inpart->CC()->decayModes().end();++it) {
+ generator()->preinitInterface(*it, "OnOff", "set", "Off");
+ }
+ }
+ }
+ }
+ // normal option
+ if(mout<=inMass) {
+ inpart->stable(false);
+ brsum += brat;
+ createDecayMode(tag, brat);
+ }
+ // no possible off-shell gauge bosons throw it away
+ else if(bosons.empty() || bosons.size()>2 ||
+ moutnoWZ>=inMass) {
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell "
+ << "particles, skipping it.\n";
+ }
+ else {
+ Energy maxMass = inMass - moutnoWZ;
+ string newTag = prefix;
+ for(unsigned int ix=0;ix<products.size();++ix)
+ newTag += products[ix]->name() + ",";
+ if(bosons.size()==1) {
cerr << "BSMModel::readDecay() "
- << "Decay mode " << tag << " read from SLHA file does not conserve charge,"
- << "\nare you really sure you want to do this?\n";
+ << "The decay " << tag << " cannot proceed for on-shell\n"
+ << "particles, replacing gauge boson with its decay products\n";
+ vector<pair<double,string> > modes =
+ createWZDecayModes(newTag,brat,bosons[0],maxMass);
+ for(unsigned int ix=0;ix<modes.size();++ix) {
+ modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
+ createDecayMode(modes[ix].second,modes[ix].first);
+ brsum += modes[ix].first;
+ }
}
- ++nmode;
- // normal option
- if(mout<=inMass) {
- inpart->stable(false);
- brsum += brat;
- createDecayMode(tag, brat);
- }
- // no possible off-shell gauge bosons throw it away
- else if(bosons.empty() || bosons.size()>2 ||
- moutnoWZ>=inMass) {
- cerr << "BSMModel::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell "
- << "particles, skipping it.\n";
+ else if(bosons.size()==2) {
+ bool identical = bosons[0]->id()==bosons[1]->id();
+ if(maxMass>bosons[0]->mass()&&maxMass>bosons[1]->mass()) {
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell\n"
+ << "particles, replacing one of the gauge bosons"
+ << " with its decay products\n";
+ unsigned int imax = identical ? 1 : 2;
+ if(imax==2) brat *= 0.5;
+ for(unsigned int ix=0;ix<imax;++ix) {
+ string newTag2 = newTag+bosons[ix]->name()+',';
+ unsigned int iother = ix==0 ? 1 : 0;
+ vector<pair<double,string> > modes =
+ createWZDecayModes(newTag2,brat,bosons[iother],maxMass);
+ for(unsigned int ix=0;ix<modes.size();++ix) {
+ modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
+ createDecayMode(modes[ix].second,modes[ix].first);
+ brsum += modes[ix].first;
+ }
+ }
+ }
+ else {
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell\n"
+ << "particles, and has too many off-shell gauge bosons,"
+ << " skipping it.\n";
+ }
}
else {
- Energy maxMass = inMass - moutnoWZ;
- string newTag = prefix;
- for(unsigned int ix=0;ix<products.size();++ix)
- newTag += products[ix]->name() + ",";
- if(bosons.size()==1) {
- cerr << "BSMModel::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell\n"
- << "particles, replacing gauge boson with its decay products\n";
- vector<pair<double,string> > modes =
- createWZDecayModes(newTag,brat,bosons[0],maxMass);
- for(unsigned int ix=0;ix<modes.size();++ix) {
- modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
- createDecayMode(modes[ix].second,modes[ix].first);
- brsum += modes[ix].first;
- }
- }
- else if(bosons.size()==2) {
- bool identical = bosons[0]->id()==bosons[1]->id();
- if(maxMass>bosons[0]->mass()&&maxMass>bosons[1]->mass()) {
- cerr << "BSMModel::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell\n"
- << "particles, replacing one of the gauge bosons"
- << " with its decay products\n";
- unsigned int imax = identical ? 1 : 2;
- if(imax==2) brat *= 0.5;
- for(unsigned int ix=0;ix<imax;++ix) {
- string newTag2 = newTag+bosons[ix]->name()+',';
- unsigned int iother = ix==0 ? 1 : 0;
- vector<pair<double,string> > modes =
- createWZDecayModes(newTag2,brat,bosons[iother],maxMass);
- for(unsigned int ix=0;ix<modes.size();++ix) {
- modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
- createDecayMode(modes[ix].second,modes[ix].first);
- brsum += modes[ix].first;
- }
- }
- }
- else {
- cerr << "BSMModel::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell\n"
- << "particles, and has too many off-shell gauge bosons,"
- << " skipping it.\n";
- }
- }
- else {
- cerr << "BSMModel::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell\n"
- << "particles, and has too many outgoing gauge bosons skipping it.\n";
- }
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell\n"
+ << "particles, and has too many outgoing gauge bosons skipping it.\n";
}
}
}
if( abs(brsum - 1.) > tolerance_ && nmode!=0 ) {
cerr << "Warning: The total branching ratio for " << inpart->PDGName()
<< " from the spectrum file does not sum to 1.\nThe branching fractions"
<< " will be rescaled. Difference from 1 is "
<< abs(brsum - 1.) << "\n";
}
if(nmode>0) {
inpart->update();
- if(inpart->CC()) inpart->CC()->update();
+ inpart->reset();
+ if(inpart->CC()) {
+ inpart->CC()->update();
+ inpart->CC()->reset();
+ }
+ if(inpart->massGenerator())
+ inpart->massGenerator()->reset();
+ if(inpart->widthGenerator())
+ inpart->widthGenerator()->reset();
}
}
void BSMModel::createDecayMode(string tag, double brat) const {
tDMPtr dm = generator()->findDecayMode(tag);
- if(!dm) {
- dm = generator()->preinitCreateDecayMode(tag);
- }
+ if(!dm) dm = generator()->preinitCreateDecayMode(tag);
generator()->preinitInterface(dm, "OnOff", "set", "On");
generator()->preinitInterface(dm, "Decayer", "set","/Herwig/Decays/Mambo");
ostringstream brf;
brf << setprecision(13)<< brat;
generator()->preinitInterface(dm, "BranchingRatio","set", brf.str());
if(dm->CC()) {
generator()->preinitInterface(dm->CC(), "OnOff", "set", "On");
generator()->preinitInterface(dm->CC(), "Decayer", "set","/Herwig/Decays/Mambo");
generator()->preinitInterface(dm->CC(), "BranchingRatio","set", brf.str());
}
}
vector<pair<double,string> >
BSMModel::createWZDecayModes(string tag, double brat,
tcPDPtr boson, Energy maxMass) const {
vector<pair<double,string> > modes;
double sum(0.);
for(DecaySet::const_iterator dit=boson->decayModes().begin();
dit!=boson->decayModes().end();++dit) {
tcDMPtr mode = *dit;
if(!mode->on()) continue;
string extra;
Energy outMass(ZERO);
for(ParticleMSet::const_iterator pit=mode->products().begin();
pit!=mode->products().end();++pit) {
extra += (**pit).name() + ",";
outMass += (**pit).mass();
}
if(outMass<maxMass) {
sum += mode->brat();
modes.push_back(make_pair(mode->brat(),tag+extra));
}
}
for(unsigned int ix=0;ix<modes.size();++ix)
modes[ix].first *= brat/sum;
return modes;
}
diff --git a/Models/General/PrototypeVertex.h b/Models/General/PrototypeVertex.h
--- a/Models/General/PrototypeVertex.h
+++ b/Models/General/PrototypeVertex.h
@@ -1,477 +1,477 @@
// -*- C++ -*-
//
// PrototypeVertex.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2007 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_PrototypeVertex_H
#define HERWIG_PrototypeVertex_H
#include <stack>
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "NBodyDecayConstructorBase.fh"
//
// This is the declaration of the PrototypeVertex class.
//
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
class PrototypeVertex;
ThePEG_DECLARE_POINTERS(Herwig::PrototypeVertex,PrototypeVertexPtr);
/** Pair of int,double */
typedef pair<unsigned int, double> CFPair;
/**
- * A struct to order the particles in the same way as in the DecayMode's
+ * A struct to order the particles in the same way as in the DecayModes
*/
struct ParticleOrdering {
/**
* Operator for the ordering
* @param p1 The first ParticleData object
* @param p2 The second ParticleData object
*/
- bool operator() (PDPtr p1, PDPtr p2) {
+ bool operator() (tcPDPtr p1, tcPDPtr p2) {
return abs(p1->id()) > abs(p2->id()) ||
( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) ||
( p1->id() == p2->id() && p1->fullName() > p2->fullName() );
}
};
/**
* A struct to order the particles in the same way as in the DecayMode's
*/
struct VertexOrdering {
/**
* Operator for the ordering
* @param p1 The first ParticleData object
* @param p2 The second ParticleData object
*/
bool operator() (const pair< tPDPtr, PrototypeVertexPtr > & p1,
const pair< tPDPtr, PrototypeVertexPtr > & p2) const {
return abs(p1.first->id()) > abs(p2.first->id()) ||
( abs(p1.first->id()) == abs(p2.first->id()) && p1.first->id() > p2.first->id() ) ||
( p1.first->id() == p2.first->id() && p1.first->fullName() > p2.first->fullName() );
}
};
typedef multiset<pair< tPDPtr, PrototypeVertexPtr >,VertexOrdering > OrderedVertices;
/**
* A set of ParticleData objects ordered as for the DecayMode's
*/
typedef multiset<PDPtr,ParticleOrdering> OrderedParticles;
/**
* Storage of a potenital n-body decay
*/
class PrototypeVertex : public Base {
public:
/**
* Default Constructor
*/
PrototypeVertex() : npart(0), possibleOnShell(false) {}
/**
* Constructor
*/
PrototypeVertex(tPDPtr in, OrderedVertices out,
VertexBasePtr v, int n) :
incoming(in), outgoing(out), vertex(v), npart(n),
possibleOnShell(false) {}
/**
* Incoming particle
*/
tPDPtr incoming;
/**
* Outgoing particles
*/
OrderedVertices outgoing;
/**
* The vertex for the interaction
*/
VertexBasePtr vertex;
/**
* The parent of the vertex
*/
tPrototypeVertexPtr parent;
/**
* Number of particles
*/
unsigned int npart;
/**
* Outgoing particles
*/
mutable OrderedParticles outPart;
/**
* Can have on-shell intermediates
*/
bool possibleOnShell;
/**
* Increment the number of particles
*/
void incrementN(int in) {
npart += in;
if(parent) parent->incrementN(in);
}
/**
* Mass of the incoming particle
*/
Energy incomingMass() {
return incoming->mass();
}
/**
* Total mass of all the outgoing particles
*/
Energy outgoingMass() {
Energy mass(ZERO);
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
mass += it->second ?
it->second->outgoingMass() : it->first->mass();
}
return mass;
}
/**
* Total constituent mass of all the outgoing particles
*/
Energy outgoingConstituentMass() {
Energy mass(ZERO);
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
mass += it->second ?
it->second->outgoingConstituentMass() : it->first->constituentMass();
}
return mass;
}
/**
* Check the external particles
*/
bool checkExternal(bool first=true) {
if(outPart.empty()) setOutgoing();
if(first&&outPart.find(incoming)!=outPart.end()) return false;
bool output = true;
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
if(it->second&& !it->second->checkExternal(false)) output = false;
}
return output;
}
/**
* Set the outgoing particles
*/
void setOutgoing() const {
assert(outPart.empty());
for(OrderedVertices::const_iterator it = outgoing.begin();
it!=outgoing.end();++it) {
if(it->second) {
it->second->setOutgoing();
outPart.insert(it->second->outPart.begin(),
it->second->outPart.end());
}
else
outPart.insert(it->first);
}
}
/**
* Are there potential on-shell intermediates?
*/
bool canBeOnShell(unsigned int opt,Energy maxMass,bool first);
/**
* Check if same external particles
*/
bool sameDecay(const PrototypeVertex & x) const;
/**
* Create a \f$1\to2\f$ prototype
*/
static void createPrototypes(tPDPtr inpart, VertexBasePtr vertex,
std::stack<PrototypeVertexPtr> & prototypes,
NBodyDecayConstructorBasePtr decayCon);
/**
* Expand the prototypes by adding more legs
*/
static void expandPrototypes(PrototypeVertexPtr proto, VertexBasePtr vertex,
std::stack<PrototypeVertexPtr> & prototypes,
const set<PDPtr> & excluded,
NBodyDecayConstructorBasePtr decayCon);
/**
* Copy the whole structure with a new branching
*/
static PrototypeVertexPtr replicateTree(PrototypeVertexPtr parent,
PrototypeVertexPtr oldChild,
PrototypeVertexPtr & newChild);
};
/**
* Output to a stream
*/
inline ostream & operator<<(ostream & os, const PrototypeVertex & diag) {
os << diag.incoming->PDGName() << " -> ";
bool seq=false;
for(OrderedVertices::const_iterator it = diag.outgoing.begin();
it!=diag.outgoing.end();++it) {
os << it->first->PDGName() << " ";
if(it->second) seq = true;
}
os << " decays via "
<< diag.vertex->fullName() << " in a "
<< diag.npart << "-body decay\n";
if(!seq) return os;
os << "Followed by\n";
for(OrderedVertices::const_iterator it = diag.outgoing.begin();
it!=diag.outgoing.end();++it) {
if(it->second) os << *it->second;
}
return os;
}
/**
* Test whether two diagrams are identical.
*/
inline bool operator==(const PrototypeVertex & x, const PrototypeVertex & y) {
if(x.incoming != y.incoming) return false;
if(x.vertex != y.vertex) return false;
if(x.npart != y.npart) return false;
if(x.outgoing.empty()&&y.outgoing.empty()) return true;
if(x.outgoing.size() != y.outgoing.size()) return false;
OrderedVertices::const_iterator xt = x.outgoing.begin();
OrderedVertices::const_iterator yt = y.outgoing.begin();
while(xt!=x.outgoing.end()) {
if(xt->first != yt->first) return false;
// special for identical particles
OrderedVertices::const_iterator lxt = x.outgoing.lower_bound(*xt);
OrderedVertices::const_iterator uxt = x.outgoing.upper_bound(*xt);
--uxt;
// just one particle
if(lxt==uxt) {
if(xt->second && yt->second) {
if(*(xt->second)==*(yt->second)) {
++xt;
++yt;
continue;
}
else return false;
}
else if(xt->second || yt->second)
return false;
++xt;
++yt;
}
// identical particles
else {
++uxt;
OrderedVertices::const_iterator lyt = y.outgoing.lower_bound(*xt);
OrderedVertices::const_iterator uyt = y.outgoing.upper_bound(*xt);
unsigned int nx=0;
for(OrderedVertices::const_iterator ixt=lxt;ixt!=uxt;++ixt) {++nx;}
unsigned int ny=0;
for(OrderedVertices::const_iterator iyt=lyt;iyt!=uyt;++iyt) {++ny;}
if(nx!=ny) return false;
vector<bool> matched(ny,false);
for(OrderedVertices::const_iterator ixt=lxt;ixt!=uxt;++ixt) {
bool found = false;
unsigned int iy=0;
for(OrderedVertices::const_iterator iyt=lyt;iyt!=uyt;++iyt) {
if(matched[iy]) {
++iy;
continue;
}
if( (!ixt->second &&!iyt->second) ||
( ixt->second&&iyt->second &&
*(ixt->second)==*(iyt->second)) ) {
matched[iy] = true;
found = true;
break;
}
++iy;
}
if(!found) return false;
}
xt=uxt;
yt=uyt;
}
}
return true;
}
/**
* A simple vertex for the N-body diagram
*/
struct NBVertex {
/**
* Constructor taking a prototype vertex as the arguments
*/
NBVertex(PrototypeVertexPtr proto = PrototypeVertexPtr() );
/**
* Incoming particle
*/
tPDPtr incoming;
/**
* Outgoing particles
*/
mutable OrderedParticles outgoing;
/**
* The vertices
*/
list<pair<PDPtr,NBVertex> > vertices;
/**
* The vertex
*/
VertexBasePtr vertex;
};
/**
* The NBDiagram struct contains information about a \f$1\to n\f$ decay
* that has been automatically generated.
*/
struct NBDiagram : public NBVertex {
/**
* Constructor taking a prototype vertex as the arguments*/
NBDiagram(PrototypeVertexPtr proto=PrototypeVertexPtr());
/**
* The type of channel
*/
vector<unsigned int> channelType;
/** Store colour flow at \f$N_c=3\f$ information */
mutable vector<CFPair> colourFlow;
/** Store colour flow at \f$N_c=\infty\f$ information */
mutable vector<CFPair> largeNcColourFlow;
};
/**
* Output operator to allow the structure to be persistently written
* @param os The output stream
* @param x The NBVertex
*/
inline PersistentOStream & operator<<(PersistentOStream & os,
const NBVertex & x) {
os << x.incoming << x.outgoing << x.vertices << x.vertex;
return os;
}
/**
* Input operator to allow persistently written data to be read in
* @param is The input stream
* @param x The NBVertex
*/
inline PersistentIStream & operator>>(PersistentIStream & is,
NBVertex & x) {
is >> x.incoming >> x.outgoing >> x.vertices >> x.vertex;
return is;
}
/**
* Output operator to allow the structure to be persistently written
* @param os The output stream
* @param x The NBDiagram
*/
inline PersistentOStream & operator<<(PersistentOStream & os,
const NBDiagram & x) {
os << x.incoming << x.channelType << x.outgoing << x.vertices << x.vertex
<< x.colourFlow << x.largeNcColourFlow;
return os;
}
/**
* Input operator to allow persistently written data to be read in
* @param is The input stream
* @param x The NBDiagram
*/
inline PersistentIStream & operator>>(PersistentIStream & is,
NBDiagram & x) {
is >> x.incoming >> x.channelType >> x.outgoing >> x.vertices >> x.vertex
>> x.colourFlow >> x.largeNcColourFlow;
return is;
}
/**
* Output a NBVertex to a stream
*/
inline ostream & operator<<(ostream & os, const NBVertex & vertex) {
os << vertex.incoming->PDGName() << " -> ";
bool seq=false;
for(list<pair<PDPtr,NBVertex> >::const_iterator it=vertex.vertices.begin();
it!=vertex.vertices.end();++it) {
os << it->first->PDGName() << " ";
if(it->second.incoming) seq = true;
}
os << "via vertex " << vertex.vertex->fullName() << "\n";
if(!seq) return os;
os << "Followed by\n";
for(list<pair<PDPtr,NBVertex> >::const_iterator it=vertex.vertices.begin();
it!=vertex.vertices.end();++it) {
if(it->second.incoming) os << it->second;
}
return os;
}
/**
* Output a NBDiagram to a stream
*/
inline ostream & operator<<(ostream & os, const NBDiagram & diag) {
os << diag.incoming->PDGName() << " -> ";
for(OrderedParticles::const_iterator it=diag.outgoing.begin();
it!=diag.outgoing.end();++it) {
os << (**it).PDGName() << " ";
}
os << " has order ";
for(unsigned int ix=0;ix<diag.channelType.size();++ix)
os << diag.channelType[ix] << " ";
os << "\n";
os << "First decay " << diag.incoming->PDGName() << " -> ";
bool seq=false;
for(list<pair<PDPtr,NBVertex> >::const_iterator it=diag.vertices.begin();
it!=diag.vertices.end();++it) {
os << it->first->PDGName() << " ";
if(it->second.incoming) seq = true;
}
os << "via vertex " << diag.vertex->fullName() << "\n";
if(!seq) return os;
os << "Followed by\n";
for(list<pair<PDPtr,NBVertex> >::const_iterator it=diag.vertices.begin();
it!=diag.vertices.end();++it) {
if(it->second.incoming) os << it->second;
}
return os;
}
}
#endif /* HERWIG_PrototypeVertex_H */
diff --git a/Sampling/BinSampler.h b/Sampling/BinSampler.h
--- a/Sampling/BinSampler.h
+++ b/Sampling/BinSampler.h
@@ -1,587 +1,592 @@
// -*- C++ -*-
//
// BinSampler.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef Herwig_BinSampler_H
#define Herwig_BinSampler_H
//
// This is the declaration of the BinSampler class.
//
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Utilities/Exception.h"
#include "ThePEG/Repository/UseRandom.h"
#include "MultiIterationStatistics.h"
#include "Remapper.h"
namespace Herwig {
using namespace ThePEG;
class GeneralSampler;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief BinSampler samples XCombs bins. This default implementation
* performs flat MC integration.
*
* @see \ref BinSamplerInterfaces "The interfaces"
* defined for BinSampler.
*/
class BinSampler: public Herwig::MultiIterationStatistics {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
BinSampler();
/**
* The destructor.
*/
virtual ~BinSampler();
//@}
public:
/**
* Clone this object.
*/
Ptr<BinSampler>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<BinSampler>::ptr>(clone());
}
public:
/**
* Evaluate the cross section
*/
double evaluate(vector<double> p,
bool remap = true);
/**
* Return the bias with which this sampler is selected. The sampler
* needs to divide out this bias in its weight calculation.
*/
double bias() const { return theBias; }
/**
* Set the bias with which this sampler is selected.
*/
void bias(double b) { theBias = b; }
/**
* Set the event handler
*/
void eventHandler(tStdEHPtr eh) { theEventHandler = eh; }
/**
* Return the event handler
*/
tStdEHPtr eventHandler() const { return theEventHandler; }
/**
* Set the containing sampler
*/
void sampler(Ptr<GeneralSampler>::tptr);
/**
* Get the containing sampler
*/
Ptr<GeneralSampler>::tptr sampler() const;
/**
* Return the bin
*/
int bin() const { return theBin; }
/**
* Set the bin
*/
void bin(int b) { theBin = b; }
/**
* Return a string describing the process handled by this sampler.
*/
string process() const;
/**
* Return a short string describing the process handled by this sampler.
*/
string shortprocess() const;
/**
* Return a string identifying the process handled by this sampler.
*/
string id() const;
/**
* Return the last generated point.
*/
const vector<double>& lastPoint() const { return theLastPoint; }
/**
* Access the last generated point.
*/
vector<double>& lastPoint() { return theLastPoint; }
/**
* Return the reference weight to be used
*/
double referenceWeight() const { return theReferenceWeight; }
/**
* Set the reference weight to be used
*/
void referenceWeight(double w) { theReferenceWeight = w; }
/**
* Return true, if this sampler can provide unweighted events; if
* the proposal density is not an overestimate, weights larger than
* one can be generated, the handling of these points being subject
* to the GeneralSampler class.
*/
virtual bool canUnweight() const { return true; }
/**
* Return true, if this sampler adapts on the fly while generating
* events. Cross sections in the GeneralSampler class are calculated
* from adding up the cross sections quoted by individual samplers.
*/
virtual bool adaptsOnTheFly() const { return false; }
/**
* If this sampler features a compensation algorithm, return true if
* more events need to be generated to finish the compensation.
*/
virtual bool compensating() const { return false; }
/**
* Return true, if weighted events should be generated
*/
bool weighted() const { return theWeighted; }
/**
* Indicate that weighted events should be generated
*/
void doWeighted(bool yes = true) { theWeighted = yes; }
/**
* Exception to be thrown if cross section information should be updated.
*/
struct NextIteration {};
/**
* Generate the next point and return its weight; store the point in
* lastPoint().
*/
virtual double generate();
/**
* Fill and finalize the remappers present
*/
void fillRemappers(bool progress);
/**
* Write remappers to grid file
*/
void saveRemappers() const;
/**
* Write integration data to grid files
*/
void saveIntegrationData() const;
/**
* Save grid data
*/
virtual void saveGrid() const {}
/**
* Read integration data from grid files
*/
void readIntegrationData();
/**
* Read remappers from grid file
*/
void setupRemappers(bool progress);
/**
* Run a single iteration of n points, optionally printing a
* progress bar to cout. Calls generate n times.
*/
void runIteration(unsigned long n, bool progress);
/**
* Adapt this sampler after an iteration has been run
*/
virtual void adapt() {}
/**
* Initialize this bin sampler. This default version calls runIteration.
*/
virtual void initialize(bool progress);
/**
* Return true, if this sampler has already been initialized.
*/
bool initialized() const { return theInitialized; }
/**
* Indicate that this sampler has already been initialized.
*/
void isInitialized() { theInitialized = true; }
/**
* Return true, if integration has already been performed
*/
bool integrated() const { return theIntegrated; }
/**
* Return true, if remappers have been set up
*/
bool remappersFilled() const { return theRemappersFilled; }
/**
+ * Return true, if grid data exists for this sampler.
+ */
+ virtual bool existsGrid() const { return false; }
+
+ /**
* Return true, if this sampler has already read grid data.
*/
bool hasGrids() const { return theHasGrids; }
/**
* Indicate that this sampler has already read grid data.
*/
void didReadGrids() { theHasGrids = true; }
/**
* Finalize this sampler.
*/
virtual void finalize(bool);
/**
* Return the total integrated cross section determined from the
* Monte Carlo sampling so far.
*/
virtual CrossSection integratedXSec() const {
return averageWeight()*nanobarn;
}
/**
* Return the error on the total integrated cross section determined
* from the Monte Carlo sampling so far.
*/
virtual CrossSection integratedXSecErr() const {
return sqrt(abs(averageWeightVariance()))*nanobarn;
}
/**
* Define the key for the collinear subtraction data.
*/
struct RandomNumberHistogram {
/**
* The lower bound
*/
double lower;
/**
* The bins, indexed by upper bound.
*/
map<double,double > bins;
map<double,double > binsw1;
/**
* Constructor
*/
RandomNumberHistogram(double low = 0.0,
double up = 1.,
unsigned int nbins = 20);
/**
* Book an event.
*/
void book(double inv, double weight) {
map<double,double>::iterator b = bins.upper_bound(inv);
if ( b == bins.end() ) return;
b->second = b->second+weight;
map<double,double>::iterator b2 = binsw1.upper_bound(inv);
if ( b2 == binsw1.end() ) return;
b2->second = b2->second+1.;
}
/**
* Write to file given name and invariant.
*/
void dump(const std::string& folder,const std::string& prefix, const std::string& process,const int NR)const;
};
typedef pair<string,size_t > RandomNumberIndex;
map<RandomNumberIndex,pair<RandomNumberHistogram,double> > RandomNumberHistograms;
public:
/**
* Return the dimension.
*/
int dimension() const { return theEventHandler->nDim(bin()); }
/**
* Return the number of points to be used for initial integration.
*/
unsigned long initialPoints() const { return theInitialPoints; }
/**
* Set the number of points to be used for initial integration.
*/
void initialPoints(unsigned long n) { theInitialPoints = n; }
/**
* Return the number of iterations to be considered for initialization.
*/
size_t nIterations() const { return theNIterations; }
/**
* Set the number of iterations to be considered for initialization.
*/
void nIterations(size_t n) { theNIterations = n; }
/**
* Set the factor to enhance the number of points for the next
* iteration.
*/
void enhancementFactor(double f) { theEnhancementFactor = f; }
/**
* Return the factor to enhance the number of points for the next
* iteration.
*/
double enhancementFactor() const { return theEnhancementFactor; }
/**
* Return the folder for the random number plots.
*/
string randomNumberString() const {return theRandomNumbers;}
/**
* In the AlmostUnweighted mode we do not need to unweight
* the events to the reference weight.
* Kappa reduces effectivly the reference weight.
* This can be used for processes, where unweighting
* is hardly feasable.
*/
double kappa() const {return theKappa;}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* The bias with which this sampler is selected.
*/
double theBias;
/**
* True, if weighted events should be generated
*/
bool theWeighted;
/**
* The number of points to use for initial integration.
*/
unsigned long theInitialPoints;
/**
* The number of iterations to be considered for initialization.
*/
size_t theNIterations;
/**
* Factor to enhance the number of points for the next iteration.
*/
double theEnhancementFactor;
/**
* Switch to count only non zero weights in presampling.
*/
bool theNonZeroInPresampling;
/**
* Switch to require that we get half of the points
* in each iteration below the maximum weight of the iteration.
*/
bool theHalfPoints;
/**
* The maximum number of allowed new maxima,
* in combination with HalfPoints, in order to prevent unstable
* processes.
*/
int theMaxNewMax;
/**
* The reference weight to be used
*/
double theReferenceWeight;
/**
* The bin to be sampled.
*/
int theBin;
/**
* Wether or not this sampler has already been initialized.
*/
bool theInitialized;
/**
* The last generated point.
*/
vector<double> theLastPoint;
/**
* The event handler to be used.
*/
tStdEHPtr theEventHandler;
/**
* The containing sampler
*/
Ptr<GeneralSampler>::tptr theSampler;
/**
* Folder for the random number plots.
*/
string theRandomNumbers;
/**
* Remapper objects indexed by dimension
*/
map<size_t,Remapper> remappers;
/**
* The number of points to be used for initial filling of the remappers
*/
unsigned long theRemapperPoints;
/**
* True if channels should get a remapper
*/
bool theRemapChannelDimension;
/**
* The number of bins to be used for luminosity dimensions
*/
unsigned long theLuminosityMapperBins;
/**
* The number of bins to be used for any other dimension
*/
unsigned long theGeneralMapperBins;
/**
* The minimum selection probability for remapper bins
*/
double theRemapperMinSelection;
/**
* True, if integration has already be performed
*/
bool theIntegrated;
/**
* True, if remappers have been set up
*/
bool theRemappersFilled;
/**
* True, if this sampler has already read grid data.
*/
bool theHasGrids;
/**
* In the AlmostUnweighted mode we do not need to unweight
* the events to the reference weight.
* Kappa reduces effectivly the reference weight.
* This can be used for processes, where unweighting
* is hardly feasable.
*/
double theKappa;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
BinSampler & operator=(const BinSampler &);
};
}
#endif /* Herwig_BinSampler_H */
diff --git a/Sampling/CellGrids/CellGridSampler.cc b/Sampling/CellGrids/CellGridSampler.cc
--- a/Sampling/CellGrids/CellGridSampler.cc
+++ b/Sampling/CellGrids/CellGridSampler.cc
@@ -1,345 +1,360 @@
// -*- C++ -*-
//
// CellGridSampler.cpp is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the CellGridSampler class.
//
#include "CellGridSampler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include <boost/progress.hpp>
#include "CellGridSampler.h"
#include "Herwig/Sampling/GeneralSampler.h"
using namespace Herwig;
using namespace ExSample;
CellGridSampler::CellGridSampler()
: BinSampler(), SimpleCellGrid(),
theExplorationPoints(1000), theExplorationSteps(8),
theGain(0.3), theEpsilon(0.01),
theMinimumSelection(0.0001), theLuminositySplits(0),
theChannelSplits(0), theAllChannelSplits(false),
theUnweightCells(true) {}
CellGridSampler::~CellGridSampler() {}
IBPtr CellGridSampler::clone() const {
return new_ptr(*this);
}
IBPtr CellGridSampler::fullclone() const {
return new_ptr(*this);
}
double CellGridSampler::generate() {
UseRandom rnd;
double w = SimpleCellGrid::sample(rnd,*this,lastPoint(),
!weighted() && initialized() && theUnweightCells,
!initialized());
if ( !weighted() && initialized() ) {
double p = min(abs(w),kappa()*referenceWeight())/(kappa()*referenceWeight());
double sign = w >= 0. ? 1. : -1.;
if ( p < 1 && UseRandom::rnd() > p )
w = 0.;
else
w = sign*max(abs(w),referenceWeight()*kappa());
}
select(w);
if ( w != 0.0 )
accept();
assert(kappa()==1.||sampler()->almostUnweighted());
return w;
}
void CellGridSampler::adapt() {
UseRandom rnd;
set<SimpleCellGrid*> newCells;
SimpleCellGrid::adapt(theGain,theEpsilon,newCells);
SimpleCellGrid::explore(theExplorationPoints,rnd,*this,newCells,Repository::clog());
SimpleCellGrid::setWeights();
SimpleCellGrid::updateIntegral();
SimpleCellGrid::minimumSelection(theMinimumSelection);
}
void CellGridSampler::saveGrid() const {
XML::Element grid = SimpleCellGrid::toXML();
grid.appendAttribute("process",id());
sampler()->grids().append(grid);
}
+bool CellGridSampler::existsGrid() const {
+ list<XML::Element>::iterator git = sampler()->grids().children().begin();
+ for ( ; git != sampler()->grids().children().end(); ++git ) {
+ if ( git->type() != XML::ElementTypes::Element )
+ continue;
+ if ( git->name() != "CellGrid" )
+ continue;
+ string proc;
+ git->getFromAttribute("process",proc);
+ if ( proc == id() )
+ return true;
+ }
+ return false;
+}
+
void CellGridSampler::initialize(bool progress) {
bool haveGrid = false;
list<XML::Element>::iterator git = sampler()->grids().children().begin();
for ( ; git != sampler()->grids().children().end(); ++git ) {
if ( git->type() != XML::ElementTypes::Element )
continue;
if ( git->name() != "CellGrid" )
continue;
string proc;
git->getFromAttribute("process",proc);
if ( proc == id() ) {
haveGrid = true;
break;
}
}
if ( haveGrid ) {
SimpleCellGrid::fromXML(*git);
sampler()->grids().erase(git);
didReadGrids();
}
lastPoint().resize(dimension());
if (randomNumberString()!="")
for(size_t i=0;i<lastPoint().size();i++){
RandomNumberHistograms[RandomNumberIndex(id(),i)] = make_pair( RandomNumberHistogram(),0.);
}
if ( initialized() ) {
if ( !hasGrids() )
throw Exception() << "CellGridSampler: Require existing grid when starting to run.\n"
<< "Did you miss setting --setupfile?"
<< Exception::abortnow;
return;
}
if ( haveGrid ) {
if ( !integrated() )
runIteration(initialPoints(),progress);
isInitialized();
return;
}
SimpleCellGrid::boundaries(vector<double>(dimension(),0.0),vector<double>(dimension(),1.0));
SimpleCellGrid::weightInformation().resize(dimension());
UseRandom rnd;
boost::progress_display* progressBar = 0;
if ( progress ) {
Repository::clog() << "exploring " << process();
progressBar = new boost::progress_display(theExplorationSteps,Repository::clog());
}
std::set<SimpleCellGrid*> newCells;
if ( pre_adaption_splits().empty() &&
(theLuminositySplits || theChannelSplits || theAllChannelSplits) ) {
const StandardEventHandler& eh = *eventHandler();
const StandardXComb& xc = *eh.xCombs()[bin()];
the_pre_adaption_splits.resize(dimension(),0);
const pair<int,int>& pdims = xc.partonDimensions();
if ( theLuminositySplits && dimension() >= pdims.first + pdims.second ) {
for ( int n = 0; n < pdims.first; ++n )
the_pre_adaption_splits[n] = theLuminositySplits;
for ( int n = dimension() - pdims.second; n < dimension(); ++n )
the_pre_adaption_splits[n] = theLuminositySplits;
}
if ( theChannelSplits && xc.diagrams().size() &&
dimension() > pdims.first + pdims.second ) {
the_pre_adaption_splits[pdims.first] = theChannelSplits;
}
if ( theAllChannelSplits && xc.diagrams().size() > 1 &&
dimension() > pdims.first + pdims.second ) {
the_pre_adaption_splits[pdims.first] = xc.diagrams().size() - 1;
}
}
for(int splitdim=0; splitdim<min(dimension(),(int)pre_adaption_splits().size());splitdim++)
SimpleCellGrid::splitter(splitdim,pre_adaption_splits()[splitdim]);
SimpleCellGrid::explore(theExplorationPoints,rnd,*this,newCells,Repository::clog());
bool notAll = false;
for ( std::size_t step = 1; step < theExplorationSteps; ++step ) {
newCells.clear();
SimpleCellGrid::adapt(theGain,theEpsilon,newCells);
if ( progressBar )
++(*progressBar);
if ( newCells.empty() ) {
notAll = true;
break;
}
SimpleCellGrid::explore(theExplorationPoints,rnd,*this,newCells,Repository::clog());
}
if ( progressBar )
++(*progressBar);
SimpleCellGrid::setWeights();
SimpleCellGrid::updateIntegral();
SimpleCellGrid::minimumSelection(theMinimumSelection);
if ( progressBar ) {
if ( notAll )
cout << "\n" << flush;
delete progressBar;
}
unsigned long points = initialPoints();
for ( unsigned long k = 0; k < nIterations(); ++k ) {
runIteration(points,progress);
if ( k < nIterations() - 1 ) {
points = (unsigned long)(points*enhancementFactor());
adapt();
nextIteration();
}
}
didReadGrids();
isInitialized();
}
void CellGridSampler::finalize(bool) {
XML::Element grid = SimpleCellGrid::toXML();
grid.appendAttribute("process",id());
sampler()->grids().append(grid);
if (randomNumberString()!="")
for ( map<RandomNumberIndex,pair<RandomNumberHistogram,double> >::
const_iterator b = RandomNumberHistograms.begin();
b != RandomNumberHistograms.end(); ++b ) {
b->second.first.dump(randomNumberString(), b->first.first,shortprocess(),b->first.second);
}
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void CellGridSampler::persistentOutput(PersistentOStream & os) const {
os << theExplorationPoints << theExplorationSteps
<< theGain << theEpsilon << theMinimumSelection
<< the_pre_adaption_splits
<< theLuminositySplits << theChannelSplits
<< theAllChannelSplits << theUnweightCells;
}
void CellGridSampler::persistentInput(PersistentIStream & is, int) {
is >> theExplorationPoints >> theExplorationSteps
>> theGain >> theEpsilon >> theMinimumSelection
>> the_pre_adaption_splits
>> theLuminositySplits >> theChannelSplits
>> theAllChannelSplits >> theUnweightCells;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<CellGridSampler,BinSampler>
describeHerwigCellGridSampler("Herwig::CellGridSampler", "HwSampling.so");
void CellGridSampler::Init() {
static ClassDocumentation<CellGridSampler> documentation
("CellGridSampler samples XCombs bins using CellGrids.");
static Parameter<CellGridSampler,size_t> interfaceExplorationPoints
("ExplorationPoints",
"The number of points to use for cell exploration.",
&CellGridSampler::theExplorationPoints, 1000, 1, 0,
false, false, Interface::lowerlim);
static Parameter<CellGridSampler,size_t> interfaceExplorationSteps
("ExplorationSteps",
"The number of exploration steps to perform.",
&CellGridSampler::theExplorationSteps, 8, 1, 0,
false, false, Interface::lowerlim);
static Parameter<CellGridSampler,double> interfaceGain
("Gain",
"The gain factor used for adaption.",
&CellGridSampler::theGain, 0.3, 0.0, 1.0,
false, false, Interface::limited);
static Parameter<CellGridSampler,double> interfaceEpsilon
("Epsilon",
"The efficieny threshold used for adaption.",
&CellGridSampler::theEpsilon, 0.01, 0.0, 1.0,
false, false, Interface::limited);
static Parameter<CellGridSampler,double> interfaceMinimumSelection
("MinimumSelection",
"The minimum cell selection probability.",
&CellGridSampler::theMinimumSelection, 0.0001, 0.0, 1.0,
false, false, Interface::limited);
static ParVector<CellGridSampler,int> interfacethe_pre_adaption_splits
("preadaptionsplit",
"The splittings for each dimension befor adaption.",
&CellGridSampler::the_pre_adaption_splits, 1., -1, 0.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<CellGridSampler,int> interfaceLuminositySplits
("LuminositySplits",
"",
&CellGridSampler::theLuminositySplits, 0, 0, 0,
false, false, Interface::lowerlim);
static Parameter<CellGridSampler,int> interfaceChannelSplits
("ChannelSplits",
"",
&CellGridSampler::theChannelSplits, 0, 0, 0,
false, false, Interface::lowerlim);
static Switch<CellGridSampler,bool> interfaceAllChannelSplits
("AllChannelSplits",
"",
&CellGridSampler::theAllChannelSplits, false, false, false);
static SwitchOption interfaceAllChannelSplitsOn
(interfaceAllChannelSplits,
"On",
"",
true);
static SwitchOption interfaceAllChannelSplitsOff
(interfaceAllChannelSplits,
"Off",
"",
false);
static Switch<CellGridSampler,bool> interfaceUnweightCells
("UnweightCells",
"",
&CellGridSampler::theUnweightCells, true, false, false);
static SwitchOption interfaceUnweightCellsYes
(interfaceUnweightCells,
"Yes",
"",
true);
static SwitchOption interfaceUnweightCellsNo
(interfaceUnweightCells,
"No",
"",
false);
}
diff --git a/Sampling/CellGrids/CellGridSampler.h b/Sampling/CellGrids/CellGridSampler.h
--- a/Sampling/CellGrids/CellGridSampler.h
+++ b/Sampling/CellGrids/CellGridSampler.h
@@ -1,205 +1,210 @@
// -*- C++ -*-
//
// CellGridSampler.hpp is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef Herwig_CellGridSampler_H
#define Herwig_CellGridSampler_H
//
// This is the declaration of the CellGridSampler class.
//
#include "Herwig/Sampling/BinSampler.h"
#include "SimpleCellGrid.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief CellGridSampler samples XCombs bins using CellGrids
*
* @see \ref CellGridSamplerInterfaces "The interfaces"
* defined for CellGridSampler.
*/
class CellGridSampler:
public Herwig::BinSampler, ExSample::SimpleCellGrid {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
CellGridSampler();
/**
* The destructor.
*/
virtual ~CellGridSampler();
//@}
public:
/**
* Clone this object.
*/
Ptr<CellGridSampler>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<CellGridSampler>::ptr>(clone());
}
public:
/**
* Generate the next point; store the point in lastPoint() and its
* weight using select(); if noMaxInfo is true, do not throw
* NewMaximum or UpdateCrossSections exceptions.
*/
virtual double generate();
/**
* Initialize this bin sampler. This default version calls runIteration.
*/
virtual void initialize(bool progress);
/**
* Finalize this sampler.
*/
virtual void finalize(bool);
/**
* Adapt
*/
virtual void adapt();
/**
+ * Return true, if grid data exists for this sampler.
+ */
+ virtual bool existsGrid() const;
+
+ /**
* Save grid data
*/
virtual void saveGrid() const;
/**
* The splittings for each dimension befor adaption.
*/
const vector<int>& pre_adaption_splits() const { return the_pre_adaption_splits; }
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
CellGridSampler & operator=(const CellGridSampler &);
/**
* The number of points used to explore a cell
*/
size_t theExplorationPoints;
/**
* The number of exploration steps
*/
size_t theExplorationSteps;
/**
* The adaption threshold.
*/
double theGain;
/**
* The adaption threshold.
*/
double theEpsilon;
/**
* The minimum probability for cell selection.
*/
double theMinimumSelection;
/**
* The splittings for each dimension befor adaption.
*/
vector<int> the_pre_adaption_splits;
/**
* The number of splits to put into parton luminiosity degrees of
* freedom.
*/
int theLuminositySplits;
/**
* The number of splits to put into channel degrees of freedom.
*/
int theChannelSplits;
/**
* Perform splits for all channels
*/
bool theAllChannelSplits;
/**
* Perform unweighting in cells
*/
bool theUnweightCells;
};
}
#endif /* Herwig_CellGridSampler_H */
diff --git a/Sampling/GeneralSampler.cc b/Sampling/GeneralSampler.cc
--- a/Sampling/GeneralSampler.cc
+++ b/Sampling/GeneralSampler.cc
@@ -1,1035 +1,1063 @@
// -*- C++ -*-
//
// GeneralSampler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GeneralSampler class.
//
#include "GeneralSampler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Utilities/LoopGuard.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig/Utilities/RunDirectories.h"
+#include "Herwig/API/RunDirectories.h"
#include "Herwig/Utilities/XML/ElementIO.h"
#include <boost/progress.hpp>
#include <boost/filesystem.hpp>
#include <cstdlib>
#include <sstream>
using namespace Herwig;
GeneralSampler::GeneralSampler()
: theVerbose(false),
theIntegratedXSec(ZERO), theIntegratedXSecErr(ZERO),
theUpdateAfter(1), crossSectionCalls(0), gotCrossSections(false),
theSumWeights(0.), theSumWeights2(0.),
theAttempts(0), theAccepts(0),
theMaxWeight(0.0), theAddUpSamplers(false),
theGlobalMaximumWeight(true), theFlatSubprocesses(false),
isSampling(false), theMinSelection(0.01), runCombinationData(false),
theAlmostUnweighted(false), maximumExceeds(0),
maximumExceededBy(0.), correctWeights(0.),theMaxEnhancement(1.05), didReadGrids(false),
theParallelIntegration(false),
theIntegratePerJob(0), theIntegrationJobs(0), theIntegrationJobsCreated(0),
justAfterIntegrate(false), theWriteGridsOnFinish(false) {}
GeneralSampler::~GeneralSampler() {}
IBPtr GeneralSampler::clone() const {
return new_ptr(*this);
}
IBPtr GeneralSampler::fullclone() const {
return new_ptr(*this);
}
double sign(double x) {
return x >= 0. ? 1. : -1.;
}
void GeneralSampler::initialize() {
if ( theParallelIntegration &&
runLevel() == ReadMode )
throw Exception()
<< "\n---------------------------------------------------\n\n"
<< "Parallel integration is only supported\n in the build/integrate/run mode\n\n"
<< "---------------------------------------------------\n"
<< Exception::abortnow;
if ( runLevel() == ReadMode ||
runLevel() == IntegrationMode ) {
assert(theSamplers.empty());
- if ( !theGrids.children().empty() )
- Repository::clog()
- << "---------------------------------------------------\n\n"
- << "Using an existing grid. Please consider re-running \n"
- << "the grid adaption when there have been significant \n"
- << "changes to parameters, cuts, etc.\n\n"
- << "---------------------------------------------------\n"
- << flush;
}
if ( theParallelIntegration ) {
if ( !theIntegratePerJob && !theIntegrationJobs )
throw Exception()
<< "Please specify the number of subprocesses per integration job or the "
<< "number of integration jobs to be created."
<< Exception::abortnow;
if ( theIntegrationJobs ) {
unsigned int nintegrate = eventHandler()->nBins()/theIntegrationJobs;
if ( eventHandler()->nBins() % theIntegrationJobs != 0 )
++nintegrate;
theIntegratePerJob = max(theIntegratePerJob,nintegrate);
}
unsigned int jobCount = 0;
ofstream* jobList = 0;
generator()->log()
<< "---------------------------------------------------\n"
<< "preparing integration jobs ...\n" << flush;
vector<int> randomized;
vector<int> pickfrom;
for ( int b = 0; b < eventHandler()->nBins(); ++b )
pickfrom.push_back(b);
//set<int> check;
while ( !pickfrom.empty() ) {
size_t idx = UseRandom::irnd(pickfrom.size());
randomized.push_back(pickfrom[idx]);
pickfrom.erase(pickfrom.begin() + idx);
}
int b = 0;
for ( vector<int>::const_iterator bx = randomized.begin();
bx != randomized.end(); ++bx, ++b ) {
if ( b == 0 || b % theIntegratePerJob == 0 ) {
if ( jobList ) {
jobList->close();
delete jobList;
jobList = 0;
}
ostringstream name;
string prefix = RunDirectories::runStorage();
if ( prefix.empty() )
prefix = "./";
else if ( *prefix.rbegin() != '/' )
prefix += "/";
name << prefix << "integrationJob" << jobCount<<"List";
++jobCount;
string fname = name.str();
jobList = new ofstream(fname.c_str());
if ( !*jobList ) {
delete jobList;
throw Exception() << "Failed to write integration job list"
<< Exception::abortnow;
}
}
*jobList << *bx << " ";
}
theIntegrationJobsCreated = jobCount;
generator()->log()
<< "---------------------------------------------------\n\n"
<< "Wrote " << jobCount << " integration jobs\n"
<< "Please submit integration jobs with the\nintegrate --jobid=x\ncommand for job ids "
<< "from 0 to " << (jobCount-1) << "\n\n"
<< "e.g.:\n\n"
<< "\e[93m for i in $(seq 0 "<< (jobCount-1) <<");do Herwig integrate --jobid=$i "<<generator()->runName()<<".run & done \e[0m \n\n"
<< "---------------------------------------------------\n"
<< flush;
if ( jobList ) {
jobList->close();
delete jobList;
jobList = 0;
}
theParallelIntegration = false;
return;
}
if ( runLevel() == BuildMode )
return;
if ( !samplers().empty() )
return;
if ( binSampler()->adaptsOnTheFly() ) {
if ( !theAddUpSamplers ) {
Repository::clog() << "Warning: On-the-fly adapting samplers require cross section calculation from "
<< "adding up individual samplers. The AddUpSamplers flag will be switched on.";
}
theAddUpSamplers = true;
}
if ( !weighted() && !binSampler()->canUnweight() )
throw Exception() << "Unweighted events requested from weighted bin sampler object.";
if ( theFlatSubprocesses && !theGlobalMaximumWeight ) {
Repository::clog() << "Warning: Can only use a global maximum weight when selecting subprocesses "
<< "uniformly. The GlobalMaximumWeight flag will be switched on.";
theGlobalMaximumWeight = true;
}
set<int> binsToIntegrate;
if ( integrationList() != "" ) {
string prefix = RunDirectories::runStorage();
assert ( !prefix.empty() );
string fname = prefix.substr(0, prefix.size()-1) + "List";
ifstream jobList(fname.c_str());
if ( jobList ) {
int b = 0;
while ( jobList >> b )
binsToIntegrate.insert(b);
} else {
Repository::clog()
<< "Job list '"
<< fname << "' not found.\n"
<< "Assuming empty integration job\n" << flush;
return;
}
}
if ( binsToIntegrate.empty() ) {
for ( int b = 0; b < eventHandler()->nBins(); ++b )
binsToIntegrate.insert(b);
}
boost::progress_display* progressBar = 0;
if ( !theVerbose && !justAfterIntegrate ) {
Repository::clog() << "integrating subprocesses";
progressBar = new boost::progress_display(binsToIntegrate.size(),Repository::clog());
}
+
int count=0;
+ bool reuseGrid = false;
+ bool missingGrid = false;
for ( set<int>::const_iterator bit = binsToIntegrate.begin(); bit != binsToIntegrate.end(); ++bit ) {
count++;
if(theVerbose&&
(runLevel() == ReadMode ||
runLevel() == IntegrationMode))
cout<<"\nIntegrate "<< count <<" of "<<binsToIntegrate.size() <<":\n"<<flush;
Ptr<BinSampler>::ptr s = theBinSampler->cloneMe();
s->eventHandler(eventHandler());
s->sampler(this);
s->bin(*bit);
lastSampler(s);
s->doWeighted(eventHandler()->weighted());
s->setupRemappers(theVerbose);
if ( justAfterIntegrate )
s->readIntegrationData();
+ reuseGrid = reuseGrid || s->existsGrid();
+ missingGrid = missingGrid || ( ! s->existsGrid() );
s->initialize(theVerbose);
samplers()[*bit] = s;
if ( !theVerbose && !justAfterIntegrate )
++(*progressBar);
if ( s->nanPoints() && theVerbose ) {
Repository::clog() << "warning: "
<< s->nanPoints() << " of "
<< s->allPoints() << " points with nan or inf weight.\n"
<< flush;
}
}
if ( progressBar ) {
delete progressBar;
progressBar = 0;
}
+ if ( missingGrid && runLevel() == RunMode )
+ generator()->log()
+ << "\n--------------------------------------------------------------------------------\n\n"
+ << "Warning:No grid file could be found at the start of this run.\n\n"
+ << "* For a read/run setup intented to be used with --setupfile please consider\n"
+ << " using the build/integrate/run setup.\n"
+ << "* For a build/integrate/run setup to be used with --setupfile please ensure\n"
+ << " that the same setupfile is provided to both the integrate and run steps.\n\n"
+ << "--------------------------------------------------------------------------------\n" << flush;
+
+ if ( runLevel() == ReadMode ||
+ runLevel() == IntegrationMode ) {
+ if ( reuseGrid )
+ Repository::clog()
+ << "--------------------------------------------------------------------------------\n\n"
+ << "Re-using an existing grid as starting point for grid optimization. \n"
+ << "Please consider removing the grid files and re-running the grid adaption\n"
+ << "when there have been significant changes to parameters, cuts, etc.\n\n"
+ << "--------------------------------------------------------------------------------\n"
+ << flush;
+ }
+
if ( runLevel() == IntegrationMode ) {
theGrids = XML::Element(XML::ElementTypes::Element,"Grids");
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
s->second->saveGrid();
s->second->saveRemappers();
s->second->saveIntegrationData();
}
writeGrids();
return;
}
if ( theVerbose ) {
bool oldAdd = theAddUpSamplers;
theAddUpSamplers = true;
try {
Repository::clog() << "estimated total cross section is ( "
<< integratedXSec()/nanobarn << " +/- "
<< integratedXSecErr()/nanobarn << " ) nb\n" << flush;
} catch (...) {
theAddUpSamplers = oldAdd;
throw;
}
theAddUpSamplers = oldAdd;
}
updateSamplers();
if ( samplers().empty() ) {
throw Exception() << "No processes with non-zero cross section present."
<< Exception::abortnow;
}
if ( !justAfterIntegrate ) {
theGrids = XML::Element(XML::ElementTypes::Element,"Grids");
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
s->second->saveGrid();
s->second->saveRemappers();
}
writeGrids();
}
}
double GeneralSampler::generate() {
long excptTries = 0;
gotCrossSections = false;
lastSampler(samplers().upper_bound(UseRandom::rnd())->second);
double weight = 0.;
while ( true ) {
try {
weight = 1.0;
double p = lastSampler()->referenceWeight()/lastSampler()->bias()/theMaxWeight;
if ( weighted() )
weight *= p;
else if ( p < UseRandom::rnd() ){
weight = 0.0;
// The lastSampler was picked according to the bias of the process.
--excptTries;
}
if ( weight != 0.0 )
weight *= lastSampler()->generate()/lastSampler()->referenceWeight();
} catch(BinSampler::NextIteration) {
updateSamplers();
lastSampler(samplers().upper_bound(UseRandom::rnd())->second);
if ( ++excptTries == eventHandler()->maxLoop() )
break;
continue;
} catch (...) {
throw;
}
if ( ! isfinite(lastSampler()->lastWeight()) ) {
lastSampler() = samplers().upper_bound(UseRandom::rnd())->second;
if ( ++excptTries == eventHandler()->maxLoop() )
break;
continue;
}
theAttempts += 1;
if ( abs(weight) == 0.0 ) {
lastSampler(samplers().upper_bound(UseRandom::rnd())->second);
if ( ++excptTries == eventHandler()->maxLoop() )
break;
continue;
}
if ( !eventHandler()->weighted() && !theAlmostUnweighted ) {
if ( abs(weight) > 1. ) {
++maximumExceeds;
maximumExceededBy += abs(weight)-1.;
}
correctWeights+=weight;
if ( weight > 0.0 )
weight = 1.;
else
weight = -1.;
}
break;
}
theAccepts += 1;
if ( excptTries == eventHandler()->maxLoop() )
throw Exception()
<< "GeneralSampler::generate() : Maximum number of tries to re-run event "
<< "selection reached. Aborting now." << Exception::runerror;
lastPoint() = lastSampler()->lastPoint();
lastSampler()->accept();
theSumWeights += weight;
theSumWeights2 += sqr(weight);
return weight;
}
void GeneralSampler::rejectLast() {
if ( !lastSampler() )
return;
double w = 0.0;
if ( weighted() )
w = lastSampler()->lastWeight()/lastSampler()->bias()/theMaxWeight;
else
w = lastSampler()->lastWeight()/lastSampler()->referenceWeight();
lastSampler()->reject();
theSumWeights -= w;
theSumWeights2 -= sqr(w);
theAttempts -= 1;
theAccepts -= 1;
}
void GeneralSampler::updateSamplers() {
map<double,Ptr<BinSampler>::ptr> checkedSamplers;
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
if ( s->second->averageAbsWeight() == 0.0 ) {
generator()->log() << "Warning: no phase space points with non-zero cross section\n"
<< "could be obtained for the process: "
<< s->second->process() << "\n"
<< "This process will not be considered. Try increasing InitialPoints.\n"
<< flush;
if ( s->second->nanPoints() ) {
generator()->log() << "Warning: "
<< s->second->nanPoints() << " of "
<< s->second->allPoints() << " points with nan or inf weight\n"
<< "in " << s->second->process() << "\n" << flush;
}
continue;
}
checkedSamplers.insert(*s);
}
theSamplers = checkedSamplers;
if ( samplers().empty() )
return;
double allMax = 0.0;
double sumbias = 0.;
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
double bias = 1.;
if ( !theFlatSubprocesses )
bias *= s->second->averageAbsWeight();
s->second->bias(bias);
sumbias += bias;
allMax = max(allMax,s->second->maxWeight()*theMaxEnhancement);
}
double nsumbias = 0.0;
bool needAdjust = false;
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
needAdjust |= s->second->bias()/sumbias < theMinSelection;
s->second->bias(max(s->second->bias()/sumbias,theMinSelection));
nsumbias += s->second->bias();
}
if ( nsumbias == 0.0 ) {
samplers().clear();
return;
}
if ( needAdjust ) {
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
s->second->bias(s->second->bias()/nsumbias);
}
}
theMaxWeight = 0.0;
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
double wref = theGlobalMaximumWeight ? allMax :
s->second->maxWeight()*theMaxEnhancement;
s->second->referenceWeight(wref);
theMaxWeight = max(theMaxWeight,wref/s->second->bias());
if ( (isSampling && s->second == lastSampler()) ||
!isSampling )
s->second->nextIteration();
}
map<double,Ptr<BinSampler>::ptr> newSamplers;
double current = 0.;
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
if ( s->second->bias() == 0.0 )
continue;
current += s->second->bias();
newSamplers[current] = s->second;
}
samplers() = newSamplers;
}
void GeneralSampler::currentCrossSections() const {
if ( !theAddUpSamplers ) {
double n = attempts();
if ( n > 1 ) {
theIntegratedXSec = sumWeights()*maxXSec()/attempts();
double sw = sumWeights(); double sw2 = sumWeights2();
theIntegratedXSecErr = maxXSec()*sqrt(abs(sw2/n-sqr(sw/n))/(n-1));
} else {
theIntegratedXSec = ZERO;
theIntegratedXSecErr = ZERO;
}
return;
}
if ( gotCrossSections )
return;
if ( crossSectionCalls > 0 ) {
if ( ++crossSectionCalls == theUpdateAfter ) {
crossSectionCalls = 0;
} else return;
}
++crossSectionCalls;
gotCrossSections = true;
theIntegratedXSec = ZERO;
double var = 0.0;
for ( map<double,Ptr<BinSampler>::ptr>::const_iterator s = samplers().begin();
s != samplers().end(); ++s ) {
theIntegratedXSec += s->second->integratedXSec();
var += sqr(s->second->integratedXSecErr()/nanobarn);
}
theIntegratedXSecErr = sqrt(var)*nanobarn;
}
void GeneralSampler::prepare() {
readGrids();
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void GeneralSampler::doinit() {
if ( RunDirectories::empty() )
RunDirectories::pushRunId(generator()->runName());
if ( integratePerJob() || integrationJobs() ) {
theParallelIntegration = true;
theIntegratePerJob = integratePerJob();
theIntegrationJobs = integrationJobs();
}
readGrids();
- if ( theGrids.children().empty() && runLevel() == RunMode )
+ bool missingGrid = false;
+ for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
+ s != samplers().end(); ++s )
+ missingGrid = missingGrid || ( ! s->second->existsGrid() );
+ if ( missingGrid && runLevel() == RunMode )
generator()->log()
<< "\n---------------------------------------------------\n\n"
<< "Warning: No grid file could be found at the start of this run.\n\n"
<< "* For a read/run setup intented to be used with --setupfile please consider\n"
<< " using the build/integrate/run setup.\n"
<< "* For a build/integrate/run setup to be used with --setupfile please ensure\n"
<< " that the same setupfile is provided to both, the integrate and run steps.\n\n"
<< "---------------------------------------------------\n" << flush;
if ( samplers().empty() && runLevel() == RunMode )
justAfterIntegrate = true;
SamplerBase::doinit();
}
void GeneralSampler::dofinish() {
set<string> compensating;
for ( map<double,Ptr<BinSampler>::ptr>::const_iterator s =
samplers().begin(); s != samplers().end(); ++s ) {
if ( s->second->compensating() ) {
compensating.insert(s->second->process());
}
if ( s->second->nanPoints() ) {
generator()->log() << "warning: "
<< s->second->nanPoints() << " of "
<< s->second->allPoints() << " points with nan or inf weight\n"
<< "in " << s->second->process() << "\n" << flush;
}
s->second->finalize(theVerbose);
}
if ( theVerbose ) {
if ( !compensating.empty() ) {
generator()->log() << "warning: sampling for the following processes is still compensating:\n";
for ( set<string>::const_iterator c = compensating.begin();
c != compensating.end(); ++c )
generator()->log() << *c << "\n";
}
generator()->log() << "final integrated cross section is ( "
<< integratedXSec()/nanobarn << " +/- "
<< integratedXSecErr()/nanobarn << " ) nb\n" << flush;
}
if ( !compensating.empty() ) {
generator()->log() << "Warning: Some samplers are still in compensating mode.\n" << flush;
}
if ( maximumExceeds != 0 ) {
//generator()->log() << maximumExceeds << " of " << theAttempts
// << " attempted points exceeded the guessed maximum weight\n"
// << "with an average relative deviation of "
// << maximumExceededBy/maximumExceeds << "\n\n" << flush;
generator()->log() <<"\n\n\nNote: In this run "<<maximumExceeds<<" of the "<<theAccepts<<" accepted events\n"
<<"were found with a weight W larger than the expected Wmax.\n";
generator()->log() <<"This corresponds to a cross section difference between:\n"
<<" UnitWeights: "<< theMaxWeight*theSumWeights/theAttempts<<"nb\n"
<<" AlmostUnweighted: "<< theMaxWeight*correctWeights/theAttempts<< "nb\n"<<
" use 'set Sampler:AlmostUnweighted On' to switch to non-unit weights.\n\n";
generator()->log() <<"The maximum weight determined in the read/integrate step has been enhanced by \n"<<
" set /Herwig/Samplers/Sampler:MaxEnhancement "<< theMaxEnhancement<<
".\nIf the rate of excessions ("<<(double)maximumExceeds*100/(double)theAccepts<<
"%) or the change of the cross section is large,\nyou can try to:\n\n"<<
"Enhance the number of points used in the read/integrate step\n"<<
" set /Herwig/Samplers/Sampler:BinSampler:InitialPoints ...\n\n"<<
"and/or enhance the reference weight found in the read/integrate step\n"<<
" set /Herwig/Samplers/Sampler:MaxEnhancement 1.x\n\n"<<
"If this does not help (and your process is well defined by cuts)\n"<<
"don't hesitate to contact herwig@projects.hepforge.org.\n\n";
}
if ( runCombinationData ) {
string dataName = RunDirectories::runStorage();
if ( dataName.empty() )
dataName = "./";
else if ( *dataName.rbegin() != '/' )
dataName += "/";
dataName += "HerwigSampling.dat";
ofstream data(dataName.c_str());
double runXSec =
theMaxWeight*theSumWeights/theAttempts;
double runXSecErr =
sqr(theMaxWeight)*(1./theAttempts)*(1./(theAttempts-1.))*
abs(theSumWeights2 - sqr(theSumWeights)/theAttempts);
data << setprecision(17);
data << "CrossSectionCombined "
<< (integratedXSec()/nanobarn) << " +/- "
<< (integratedXSecErr()/nanobarn) << "\n"
<< "CrossSectionRun "
<< runXSec << " +/- " << sqrt(runXSecErr) << "\n"
<< "PointsAttempted " << theAttempts << "\n"
<< "PointsAccepted " << theAccepts << "\n"
<< "SumWeights " << theSumWeights*theMaxWeight << "\n"
<< "SumWeights2 " << theSumWeights2*sqr(theMaxWeight) << "\n"
<< flush;
}
theGrids = XML::Element(XML::ElementTypes::Element,"Grids");
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
s->second->saveGrid();
s->second->saveRemappers();
if ( justAfterIntegrate )
s->second->saveIntegrationData();
}
if ( theWriteGridsOnFinish )
writeGrids();
SamplerBase::dofinish();
}
void GeneralSampler::doinitrun() {
readGrids();
- if ( theGrids.children().empty() && !didReadGrids )
- generator()->log()
- << "\n---------------------------------------------------\n\n"
- << "Warning:No grid file could be found at the start of this run.\n\n"
- << "* For a read/run setup intented to be used with --setupfile please consider\n"
- << " using the build/integrate/run setup.\n"
- << "* For a build/integrate/run setup to be used with --setupfile please ensure\n"
- << " that the same setupfile is provided to both, the integrate and run steps.\n\n"
- << "---------------------------------------------------\n" << flush;
-
if ( samplers().empty() ) {
justAfterIntegrate = true;
if ( !hasSetupFile() )
initialize();
} else {
for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
s != samplers().end(); ++s ) {
s->second->setupRemappers(theVerbose);
if ( justAfterIntegrate )
s->second->readIntegrationData();
s->second->initialize(theVerbose);
}
}
+
+ bool missingGrid = false;
+ for ( map<double,Ptr<BinSampler>::ptr>::iterator s = samplers().begin();
+ s != samplers().end(); ++s )
+ missingGrid = missingGrid || ( ! s->second->existsGrid() );
+ if ( missingGrid && !didReadGrids )
+ generator()->log()
+ << "\n--------------------------------------------------------------------------------\n\n"
+ << "Warning:No grid file could be found at the start of this run.\n\n"
+ << "* For a read/run setup intented to be used with --setupfile please consider\n"
+ << " using the build/integrate/run setup.\n"
+ << "* For a build/integrate/run setup to be used with --setupfile please ensure\n"
+ << " that the same setupfile is provided to both the integrate and run steps.\n\n"
+ << "--------------------------------------------------------------------------------\n" << flush;
+
isSampling = true;
SamplerBase::doinitrun();
}
void GeneralSampler::rebind(const TranslationMap & trans) {
for ( map<double,Ptr<BinSampler>::ptr>::iterator s =
samplers().begin(); s != samplers().end(); ++s )
s->second = trans.translate(s->second);
SamplerBase::rebind(trans);
}
IVector GeneralSampler::getReferences() {
IVector ret = SamplerBase::getReferences();
for ( map<double,Ptr<BinSampler>::ptr>::iterator s =
samplers().begin(); s != samplers().end(); ++s )
ret.push_back(s->second);
return ret;
}
void GeneralSampler::writeGrids() const {
if ( theGrids.children().empty() )
return;
string dataName = RunDirectories::runStorage();
if ( dataName.empty() )
dataName = "./";
else if ( *dataName.rbegin() != '/' )
dataName += "/";
dataName += "HerwigGrids.xml";
ofstream out(dataName.c_str());
XML::ElementIO::put(theGrids,out);
}
void GeneralSampler::readGrids() {
// return if grids were already read
if ( didReadGrids )
return;
// check for global HerwigGrids.xml file or combine integration jobs to a global HerwigGrids.xml file
// Show messages of integration job combination only in the first run (if no global HerwigGrids.xml file is found in one of the directories)
// or in case of an error
// Check if a globalHerwigGridsFileFound was found and keep messages in a stringstream buffer beforehand
bool globalHerwigGridsFileFound = false;
bool integrationJobCombinationSuccessful = true;
std::stringstream messageBuffer;
RunDirectories directories;
while ( directories && !didReadGrids ) {
string dataName = directories.nextRunStorage();
if ( dataName.empty() )
dataName = "./";
else if ( *dataName.rbegin() != '/' )
dataName += "/";
string directoryName = dataName;
dataName += "HerwigGrids.xml";
ifstream in(dataName.c_str());
if ( in ) {
theGrids = XML::ElementIO::get(in);
didReadGrids = true;
// Set to true if in any of the directories a global HerwigGrid.xml file was found
globalHerwigGridsFileFound = true;
}
else {
// Check if integrationJob was split and try to merge single integrationJobs together
// integrationJobsCreated() == 0 indicates that parallel integration has not been
// requested, while the parallel integration parameters may well yield a single job
if(integrationJobsCreated() >= 1 && runLevel() == RunMode) {
messageBuffer << "\n\n* Global HerwigGrids.xml file does not exist yet"
<< "\n and integration jobs were split into " << integrationJobsCreated() << " integration jobs."
<< "\n Trying to combine single integration jobs to a global HerwigGrids.xml file"
<< "\n using the following directory " << directoryName << ".";
theGrids = XML::Element(XML::ElementTypes::Element,"Grids");
integrationJobCombinationSuccessful = true;
for(unsigned int currentProcessedIntegrationJobNum = 0; currentProcessedIntegrationJobNum < integrationJobsCreated(); ++currentProcessedIntegrationJobNum) {
ostringstream currentProcessedIntegrationJob;
currentProcessedIntegrationJob << directoryName << "integrationJob" << currentProcessedIntegrationJobNum << "/HerwigGrids.xml";
if(boost::filesystem::exists(boost::filesystem::path(currentProcessedIntegrationJob.str()))) {
ifstream localGridFileIN(currentProcessedIntegrationJob.str().c_str());
if(localGridFileIN) {
theGrids = theGrids + XML::ElementIO::get(localGridFileIN);
messageBuffer << "\n* Added integration job " << currentProcessedIntegrationJobNum << " to global HerwigGrids.xml file.";
}
else {
integrationJobCombinationSuccessful = false;
messageBuffer << "\n* Could not open/add integration job " << currentProcessedIntegrationJobNum << " to global HerwigGrids.xml file.";
}
}
else {
integrationJobCombinationSuccessful = false;
messageBuffer << "\n* Could not find integration job " << currentProcessedIntegrationJob.str();
}
}
if(integrationJobCombinationSuccessful) {
string globalGridFile = directoryName + "HerwigGrids.xml";
ofstream globalGridFileOF(globalGridFile.c_str());
XML::ElementIO::put(theGrids,globalGridFileOF);
messageBuffer << "\n* Global HerwigGrids.xml file was created, the integration jobs 0 to " << integrationJobsCreated()-1
<< " were combined."
<< "\n* If previous warnings in regards to the HerwigGrids.xml file occured, these can be safely ignored."
<< "\n* Note: This message will occur only in the first run and will be suppressed in further runs.\n"
<< flush;
didReadGrids = true;
}
else {
messageBuffer << "\n* Global HerwigGrids.xml file could not be created due to failed combination of integration jobs."
<< "\n Please check the above-mentioned missing/failed integration jobs which are needed for the combination."
<< "\n* Note: It can be that the HerwigGrids.xml file is searched and can be found in further directories."
<< "\n In this case you can ignore this warning message.\n" << flush;
}
}
}
}
// Show messages if global HerwigGrids.xml file was not found or first combination run
if (!globalHerwigGridsFileFound && (theVerbose || !integrationJobCombinationSuccessful))
BaseRepository::cout() << messageBuffer.str() << "\n" << flush;
if ( !didReadGrids )
theGrids = XML::Element(XML::ElementTypes::Element,"Grids");
}
void GeneralSampler::persistentOutput(PersistentOStream & os) const {
os << theVerbose << theBinSampler << theSamplers << theLastSampler
<< theUpdateAfter << crossSectionCalls << gotCrossSections
<< ounit(theIntegratedXSec,nanobarn)
<< ounit(theIntegratedXSecErr,nanobarn)
<< theSumWeights << theSumWeights2
<< theAttempts << theAccepts << theMaxWeight
<< theAddUpSamplers << theGlobalMaximumWeight
<< theFlatSubprocesses << isSampling << theMinSelection
<< runCombinationData << theAlmostUnweighted << maximumExceeds
<< maximumExceededBy << correctWeights << theMaxEnhancement
<< theParallelIntegration
<< theIntegratePerJob << theIntegrationJobs
<< theIntegrationJobsCreated << theWriteGridsOnFinish;
}
void GeneralSampler::persistentInput(PersistentIStream & is, int) {
is >> theVerbose >> theBinSampler >> theSamplers >> theLastSampler
>> theUpdateAfter >> crossSectionCalls >> gotCrossSections
>> iunit(theIntegratedXSec,nanobarn)
>> iunit(theIntegratedXSecErr,nanobarn)
>> theSumWeights >> theSumWeights2
>> theAttempts >> theAccepts >> theMaxWeight
>> theAddUpSamplers >> theGlobalMaximumWeight
>> theFlatSubprocesses >> isSampling >> theMinSelection
>> runCombinationData >> theAlmostUnweighted >> maximumExceeds
>> maximumExceededBy >> correctWeights >> theMaxEnhancement
>> theParallelIntegration
>> theIntegratePerJob >> theIntegrationJobs
>> theIntegrationJobsCreated >> theWriteGridsOnFinish;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<GeneralSampler,SamplerBase>
describeHerwigGeneralSampler("Herwig::GeneralSampler", "HwSampling.so");
void GeneralSampler::Init() {
static ClassDocumentation<GeneralSampler> documentation
("A GeneralSampler class");
static Reference<GeneralSampler,BinSampler> interfaceBinSampler
("BinSampler",
"The bin sampler to be used.",
&GeneralSampler::theBinSampler, false, false, true, false, false);
static Parameter<GeneralSampler,size_t> interfaceUpdateAfter
("UpdateAfter",
"Update cross sections every number of events.",
&GeneralSampler::theUpdateAfter, 1, 1, 0,
false, false, Interface::lowerlim);
static Switch<GeneralSampler,bool> interfaceVerbose
("Verbose",
"",
&GeneralSampler::theVerbose, false, false, false);
static SwitchOption interfaceVerboseOn
(interfaceVerbose,
"On",
"",
true);
static SwitchOption interfaceVerboseOff
(interfaceVerbose,
"Off",
"",
false);
static Switch<GeneralSampler,bool> interfaceAddUpSamplers
("AddUpSamplers",
"Calculate cross sections from adding up individual samplers.",
&GeneralSampler::theAddUpSamplers, false, false, false);
static SwitchOption interfaceAddUpSamplersOn
(interfaceAddUpSamplers,
"On",
"",
true);
static SwitchOption interfaceAddUpSamplersOff
(interfaceAddUpSamplers,
"Off",
"",
false);
static Switch<GeneralSampler,bool> interfaceGlobalMaximumWeight
("GlobalMaximumWeight",
"Use a global maximum weight instead of partial unweighting.",
&GeneralSampler::theGlobalMaximumWeight, true, false, false);
static SwitchOption interfaceGlobalMaximumWeightOn
(interfaceGlobalMaximumWeight,
"On",
"",
true);
static SwitchOption interfaceGlobalMaximumWeightOff
(interfaceGlobalMaximumWeight,
"Off",
"",
false);
static Parameter<GeneralSampler,double> interfaceMaxEnhancement
("MaxEnhancement",
"Enhance the maximum reference weight found in the read step.",
&GeneralSampler::theMaxEnhancement, 1.1, 1.0, 1.5,
false, false, Interface::limited);
static Switch<GeneralSampler,bool> interfaceFlatSubprocesses
("FlatSubprocesses",
"[debug] Perform a flat subprocess selection.",
&GeneralSampler::theFlatSubprocesses, false, false, false);
static SwitchOption interfaceFlatSubprocessesOn
(interfaceFlatSubprocesses,
"On",
"",
true);
static SwitchOption interfaceFlatSubprocessesOff
(interfaceFlatSubprocesses,
"Off",
"",
false);
static Parameter<GeneralSampler,double> interfaceMinSelection
("MinSelection",
"A minimum subprocess selection probability.",
&GeneralSampler::theMinSelection, 0.01, 0.0, 1.0,
false, false, Interface::limited);
static Switch<GeneralSampler,bool> interfaceRunCombinationData
("RunCombinationData",
"",
&GeneralSampler::runCombinationData, false, false, false);
static SwitchOption interfaceRunCombinationDataOn
(interfaceRunCombinationData,
"On",
"",
true);
static SwitchOption interfaceRunCombinationDataOff
(interfaceRunCombinationData,
"Off",
"",
false);
static Switch<GeneralSampler,bool> interfaceAlmostUnweighted
("AlmostUnweighted",
"",
&GeneralSampler::theAlmostUnweighted, false, false, false);
static SwitchOption interfaceAlmostUnweightedOn
(interfaceAlmostUnweighted,
"On",
"",
true);
static SwitchOption interfaceAlmostUnweightedOff
(interfaceAlmostUnweighted,
"Off",
"",
false);
static Switch<GeneralSampler,bool> interfaceParallelIntegration
("ParallelIntegration",
"Prepare parallel jobs for integration.",
&GeneralSampler::theParallelIntegration, false, false, false);
static SwitchOption interfaceParallelIntegrationYes
(interfaceParallelIntegration,
"Yes",
"",
true);
static SwitchOption interfaceParallelIntegrationNo
(interfaceParallelIntegration,
"No",
"",
false);
static Parameter<GeneralSampler,unsigned int> interfaceIntegratePerJob
("IntegratePerJob",
"The number of subprocesses to integrate per job.",
&GeneralSampler::theIntegratePerJob, 0, 0, 0,
false, false, Interface::lowerlim);
static Parameter<GeneralSampler,unsigned int> interfaceIntegrationJobs
("IntegrationJobs",
"The maximum number of integration jobs to create.",
&GeneralSampler::theIntegrationJobs, 0, 0, 0,
false, false, Interface::lowerlim);
static Parameter<GeneralSampler,unsigned int> interfaceIntegrationJobsCreated
("IntegrationJobsCreated",
"The number of integration jobs which were actually created.",
&GeneralSampler::theIntegrationJobsCreated, 1, 1, 0,
false, false, Interface::lowerlim);
static Switch<GeneralSampler,bool> interfaceWriteGridsOnFinish
("WriteGridsOnFinish",
"Write grids on finishing a run.",
&GeneralSampler::theWriteGridsOnFinish, false, false, false);
static SwitchOption interfaceWriteGridsOnFinishYes
(interfaceWriteGridsOnFinish,
"Yes",
"",
true);
static SwitchOption interfaceWriteGridsOnFinishNo
(interfaceWriteGridsOnFinish,
"No",
"",
false);
}
diff --git a/Sampling/MonacoSampler.cc b/Sampling/MonacoSampler.cc
--- a/Sampling/MonacoSampler.cc
+++ b/Sampling/MonacoSampler.cc
@@ -1,399 +1,414 @@
// -*- C++ -*-
//
// MonacoSampler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MonacoSampler class.
//
#include "MonacoSampler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include <boost/progress.hpp>
#include "MonacoSampler.h"
#include "Herwig/Sampling/GeneralSampler.h"
using namespace Herwig;
MonacoSampler::MonacoSampler()
: BinSampler(),
theAlpha(0.875),
theGridDivisions(48),
theIterationPoints(0) {}
MonacoSampler::~MonacoSampler() {}
IBPtr MonacoSampler::clone() const {
return new_ptr(*this);
}
IBPtr MonacoSampler::fullclone() const {
return new_ptr(*this);
}
double MonacoSampler::generate() {
double w = 1.;
// cout<<"\npoint: ";
std::valarray<int> upperb(dimension());
for ( int k = 0; k < dimension(); ++k ) {
double div = (1 - UseRandom::rnd()) * theGridDivisions;
upperb[k] = static_cast<int>(div);
double gupper, glower;
if ( upperb[k] <= 0 ) {
upperb[k] = 0;
glower = 0.;
gupper = theGrid(k,0);
} else if (upperb[k] >= static_cast<int>(theGridDivisions)) {
upperb[k] = theGridDivisions-1;
glower = theGrid(k,theGridDivisions-2);
gupper = theGrid(k,theGridDivisions-1);
} else {
glower = theGrid(k,upperb[k]-1);
gupper = theGrid(k,upperb[k]);
}
double gdiff = gupper - glower;
lastPoint()[k] = glower + (div-upperb[k])*gdiff;
w *= gdiff * theGridDivisions;
}
// cout<<lastPoint()[k]<<" ";
try {
w *= eventHandler()->dSigDR(lastPoint()) / nanobarn;
} catch (Veto&) {
w = 0.0;
} catch (...) {
throw;
}
// only store numbers
double wgt = w;
if ( ! isfinite(wgt) ) wgt = 0;
// save results for later grid optimization
theIterationPoints++;
for ( int k = 0; k < dimension(); ++k ) {
theGridData(k,upperb[k]) += wgt*wgt;
}
if (randomNumberString()!="")
for ( size_t k = 0; k < lastPoint().size(); ++k ) {
RandomNumberHistograms[RandomNumberIndex(id(),k)].first.book(lastPoint()[k],wgt);
RandomNumberHistograms[RandomNumberIndex(id(),k)].second+=wgt;
}
if ( !weighted() && initialized() ) {
double p = min(abs(w),kappa()*referenceWeight())/(kappa()*referenceWeight());
double sign = w >= 0. ? 1. : -1.;
if ( p < 1 && UseRandom::rnd() > p )
w = 0.;
else
w = sign*max(abs(w),kappa()*referenceWeight());
}
select(w);
assert(kappa()==1.||sampler()->almostUnweighted());
if ( w != 0.0 )
accept();
return w;
}
void MonacoSampler::saveGrid() const {
XML::Element grid = toXML();
grid.appendAttribute("process",id());
sampler()->grids().append(grid);
}
+bool MonacoSampler::existsGrid() const {
+ list<XML::Element>::iterator git = sampler()->grids().children().begin();
+ for ( ; git != sampler()->grids().children().end(); ++git ) {
+ if ( git->type() != XML::ElementTypes::Element )
+ continue;
+ if ( git->name() != "Monaco" )
+ continue;
+ string proc;
+ git->getFromAttribute("process",proc);
+ if ( proc == id() )
+ return true;
+ }
+ return false;
+}
+
void MonacoSampler::initialize(bool progress) {
//read in grid
bool haveGrid = false;
list<XML::Element>::iterator git = sampler()->grids().children().begin();
for ( ; git != sampler()->grids().children().end(); ++git ) {
if ( git->type() != XML::ElementTypes::Element )
continue;
if ( git->name() != "Monaco" )
continue;
string proc;
git->getFromAttribute("process",proc);
if ( proc == id() ) {
haveGrid = true;
break;
}
}
if ( haveGrid ) {
fromXML(*git);
sampler()->grids().erase(git);
didReadGrids();
} else {
// flat grid
theGrid.resize(dimension(),theGridDivisions);
for (int k = 0; k < dimension(); k++)
for (size_t l = 0; l < theGridDivisions; l++)
theGrid(k,l) = (l+1)/static_cast<double>(theGridDivisions);
theGridData = boost::numeric::ublas::zero_matrix<double>(dimension(),theGridDivisions);
theIterationPoints = 0;
}
lastPoint().resize(dimension());
if (randomNumberString()!="")
for(size_t i=0;i<lastPoint().size();i++){
RandomNumberHistograms[RandomNumberIndex(id(),i)] = make_pair( RandomNumberHistogram(),0.);
}
if ( initialized() ) {
if ( !hasGrids() )
throw Exception() << "MonacoSampler: Require existing grid when starting to run.\n"
<< "Did you miss setting --setupfile?"
<< Exception::abortnow;
return;
}
if ( haveGrid ) {
if ( !integrated() ) {
runIteration(initialPoints(),progress);
adapt();
}
isInitialized();
return;
}
// if ( !sampler()->grids().children().empty() ) {
// nIterations(1);
// }
unsigned long points = initialPoints();
for ( unsigned long k = 0; k < nIterations(); ++k ) {
runIteration(points,progress);
if ( k < nIterations() - 1 ) {
points = (unsigned long)(points*enhancementFactor());
adapt();
nextIteration();
}
}
adapt();
didReadGrids();
isInitialized();
}
void MonacoSampler::adapt() {
int dim = dimension();
// refine grid
std::valarray<double> gridcumul(dim);
for (int k=0; k<dim; ++k) {
double gridold = theGridData(k,0);
double gridnew = theGridData(k,1);
theGridData(k,0) = (gridold + gridnew) / 2.0;
gridcumul[k] = theGridData(k,0);
for (size_t l=1; l<theGridDivisions-1; ++l) {
theGridData(k,l) = gridold + gridnew;
gridold = gridnew;
gridnew = theGridData(k,l+1);
theGridData(k,l) = (theGridData(k,l) + gridnew) / 3.0;
gridcumul[k] += theGridData(k,l);
}
theGridData(k,theGridDivisions-1) = (gridnew + gridold) / 2.0;
gridcumul[k] += theGridData(k,theGridDivisions-1);
}
for (int k=0; k<dim; ++k) {
double rc = 0.;
std::valarray<double> ri(theGridDivisions);
for (size_t l=0; l<theGridDivisions; ++l) {
ri[l] = 0.;
if ((theGridData(k,l) >= 0) && (gridcumul[k] != 0)) {
theGridData(k,l) = max( 1.0e-30, theGridData(k,l) );
double gpart = gridcumul[k] / theGridData(k,l);
ri[l] = pow( (gpart - 1.0) / (gpart * log( gpart )), theAlpha);
} else {
ri[l] = pow( 1. / log( 1e30 ), theAlpha);
}
rc += ri[l];
}
rc /= theGridDivisions;
double gridold = 0, gridnew = 0.;
double deltar = 0.;
unsigned int m = 0;
std::valarray<double> theGridRowNew(theGridDivisions);
for (size_t l = 0; l < theGridDivisions; ++l) {
deltar += ri[l];
gridold = gridnew;
gridnew = theGrid(k,l);
for (; deltar > rc; m++) {
deltar -= rc;
theGridRowNew[m] = gridnew - (gridnew - gridold) * deltar / ri[l];
}
}
for (size_t l = 0; l < theGridDivisions-1; ++l) {
theGrid(k,l) = theGridRowNew[l];
}
theGrid(k,theGridDivisions-1) = 1.0;
}
theGridData = boost::numeric::ublas::zero_matrix<double>(dimension(),theGridDivisions);
theIterationPoints = 0;
}
void MonacoSampler::finalize(bool) {
// save grid
adapt();
XML::Element grid = MonacoSampler::toXML();
grid.appendAttribute("process",id());
sampler()->grids().append(grid);
if (randomNumberString()!="")
for ( map<RandomNumberIndex,pair<RandomNumberHistogram,double> >::
const_iterator b = RandomNumberHistograms.begin();
b != RandomNumberHistograms.end(); ++b ) {
b->second.first.dump(randomNumberString(), b->first.first,shortprocess(),b->first.second);
}
}
void MonacoSampler::fromXML(const XML::Element& grid) {
int dim = 0;
grid.getFromAttribute("Dimension",dim);
if ( dim != dimension() ) {
throw std::runtime_error("[MonacoSampler] Number of dimensions in grid file does not match expectation.");
}
size_t griddivisions = 0;
grid.getFromAttribute("GridDivisions",griddivisions);
boost::numeric::ublas::matrix<double> tmpgrid(dim,griddivisions);
pair<multimap<pair<int,string>,list<XML::Element>::iterator>::const_iterator,multimap<pair<int,string>,list<XML::Element>::iterator>::const_iterator> cit;
cit = grid.findAll(XML::ElementTypes::Element,"GridVector");
if ( cit.first->second == grid.children().end() )
throw std::runtime_error("[MonacoSampler] Expected a GridVector element.");
for (multimap<pair<int,string>,list<XML::Element>::iterator>::const_iterator iit=cit.first; iit!=cit.second; ++iit) {
const XML::Element& gridvector = *iit->second;
int k = 0;
gridvector.getFromAttribute("Index",k);
if ( k >= dim ) {
throw std::runtime_error("[MonacoSampler] Index of grid dimension larger than grid size.");
} else {
list<XML::Element>::const_iterator git;
git = gridvector.findFirst(XML::ElementTypes::ParsedCharacterData,"");
if ( git == gridvector.children().end() )
throw std::runtime_error("[MonacoSampler] Expected grid data.");
istringstream bdata(git->content());
for ( size_t l = 0; l < griddivisions; ++l ) {
bdata >> tmpgrid(k,l);
}
}
}
// store back into main variable
// if griddivisions do not match, rebin preserving bin density
theGrid.resize(dim,theGridDivisions);
theIterationPoints = 0;
double divratio = griddivisions / static_cast<double>(theGridDivisions);
for (int k = 0; k < dim; k++) {
double xold = 0, xnew = 0, deltar = 0;
size_t l = 0;
for (size_t m = 0; m < griddivisions; m++) {
deltar += 1;
xold = xnew;
xnew = tmpgrid(k,m);
for (; deltar > divratio; l++) {
deltar -= divratio;
theGrid(k,l) = xnew - (xnew - xold) * deltar;
}
}
theGrid(k,theGridDivisions-1) = 1.0;
}
theGridData = boost::numeric::ublas::zero_matrix<double>(dimension(),theGridDivisions);
}
XML::Element MonacoSampler::toXML() const {
XML::Element grid(XML::ElementTypes::Element,"Monaco");
grid.appendAttribute("Dimension",dimension());
grid.appendAttribute("GridDivisions",theGridDivisions);
for ( int k = 0; k < dimension(); ++k ) {
XML::Element gridvector(XML::ElementTypes::Element,"GridVector");
gridvector.appendAttribute("Index",k);
ostringstream bdata;
bdata << setprecision(17);
for ( size_t l = 0; l < theGridDivisions; ++l )
bdata << theGrid(k,l) << " ";
XML::Element belem(XML::ElementTypes::ParsedCharacterData,bdata.str());
gridvector.append(belem);
grid.append(gridvector);
}
return grid;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void MonacoSampler::persistentOutput(PersistentOStream & os) const {
BinSampler::put(os);
os << theAlpha << theGridDivisions;
}
void MonacoSampler::persistentInput(PersistentIStream & is, int) {
BinSampler::get(is);
is >> theAlpha >> theGridDivisions;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<MonacoSampler,BinSampler>
describeHerwigMonacoSampler("Herwig::MonacoSampler", "HwSampling.so");
void MonacoSampler::Init() {
static ClassDocumentation<MonacoSampler> documentation
("MonacoSampler samples XCombs bins. This implementation performs weighted MC integration using Monaco, an adapted Vegas algorithm.");
static Parameter<MonacoSampler,double> interfaceAlpha
("Alpha",
"Rate of grid modification (0 for no modification).",
&MonacoSampler::theAlpha, 0.875, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<MonacoSampler,size_t> interfaceGridDivisions
("GridDivisions",
"The number of divisions per grid dimension.",
&MonacoSampler::theGridDivisions, 48, 1, 0,
false, false, Interface::lowerlim);
}
diff --git a/Sampling/MonacoSampler.h b/Sampling/MonacoSampler.h
--- a/Sampling/MonacoSampler.h
+++ b/Sampling/MonacoSampler.h
@@ -1,190 +1,195 @@
// -*- C++ -*-
//
// MonacoSampler.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef Herwig_MonacoSampler_H
#define Herwig_MonacoSampler_H
//
// This is the declaration of the MonacoSampler class.
//
#include "Herwig/Sampling/BinSampler.h"
#include "Herwig/Utilities/XML/Element.h"
#include <boost/numeric/ublas/matrix.hpp>
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Michael Rauch
*
* \brief MonacoSampler samples XCombs bins using using Monaco
*
* @see \ref MonacoSamplerInterfaces "The interfaces"
* defined for MonacoSampler.
*/
class MonacoSampler: public Herwig::BinSampler {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MonacoSampler();
/**
* The destructor.
*/
virtual ~MonacoSampler();
//@}
public:
/**
* Clone this object.
*/
Ptr<MonacoSampler>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<MonacoSampler>::ptr>(clone());
}
public:
/**
* Generate the next point and return its weight; store the point in
* lastPoint().
*/
virtual double generate();
/**
* Adapt this sampler after an iteration has been run
*/
virtual void adapt();
/**
+ * Return true, if grid data exists for this sampler.
+ */
+ virtual bool existsGrid() const;
+
+ /**
* Save grid data
*/
virtual void saveGrid() const;
/**
* Initialize this bin sampler. This default version calls runIteration.
*/
virtual void initialize(bool progress);
/**
* Finalize this sampler.
*/
virtual void finalize(bool);
/**
* Fill Monaco grid data from an XML element
*/
virtual void fromXML(const XML::Element&);
/**
* Return an XML element for the data of the Monaco grid
*/
virtual XML::Element toXML() const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* Rate of grid modification (0 for no modification)
*/
double theAlpha;
/**
* Number of grid divisions per dimension
*/
size_t theGridDivisions;
/**
* Grid boundaries
* (first index: dimension of random numbers,
* second index: dimension of partitions per random number)
*/
boost::numeric::ublas::matrix<double> theGrid;
/**
* Collected value per grid bin
*/
boost::numeric::ublas::matrix<double> theGridData;
private:
/**
* Number of points collected in iteration so far
*/
size_t theIterationPoints;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MonacoSampler & operator=(const MonacoSampler &);
};
}
#endif /* Herwig_MonacoSampler_H */
diff --git a/Shower/QTilde/Default/QTildeSudakov.cc b/Shower/QTilde/Default/QTildeSudakov.cc
--- a/Shower/QTilde/Default/QTildeSudakov.cc
+++ b/Shower/QTilde/Default/QTildeSudakov.cc
@@ -1,1060 +1,1060 @@
// -*- C++ -*-
//
// QTildeSudakov.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the QTildeSudakov class.
//
#include "QTildeSudakov.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h"
#include "Herwig/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h"
#include "Herwig/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "Herwig/Shower/QTilde/Base/ShowerVertex.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "Herwig/Shower/QTilde/QTildeShowerHandler.h"
#include "Herwig/Shower/QTilde/Base/PartnerFinder.h"
#include "Herwig/Shower/QTilde/Base/ShowerModel.h"
#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h"
using namespace Herwig;
DescribeNoPIOClass<QTildeSudakov,Herwig::SudakovFormFactor>
describeQTildeSudakov ("Herwig::QTildeSudakov","HwShower.so");
void QTildeSudakov::Init() {
static ClassDocumentation<QTildeSudakov> documentation
("The QTildeSudakov class implements the Sudakov form factor for ordering it"
" qtilde");
}
bool QTildeSudakov::guessTimeLike(Energy2 &t,Energy2 tmin,double enhance,
double detune) {
Energy2 told = t;
// calculate limits on z and if lower>upper return
if(!computeTimeLikeLimits(t)) return false;
// guess values of t and z
t = guesst(told,0,ids_,enhance,ids_[1]==ids_[2],detune);
z(guessz(0,ids_));
// actual values for z-limits
if(!computeTimeLikeLimits(t)) return false;
if(t<tmin) {
t=-1.0*GeV2;
return false;
}
else
return true;
}
bool QTildeSudakov::guessSpaceLike(Energy2 &t, Energy2 tmin, const double x,
double enhance,
double detune) {
Energy2 told = t;
// calculate limits on z if lower>upper return
if(!computeSpaceLikeLimits(t,x)) return false;
// guess values of t and z
t = guesst(told,1,ids_,enhance,ids_[1]==ids_[2],detune);
z(guessz(1,ids_));
// actual values for z-limits
if(!computeSpaceLikeLimits(t,x)) return false;
if(t<tmin) {
t=-1.0*GeV2;
return false;
}
else
return true;
}
bool QTildeSudakov::PSVeto(const Energy2 t,
const Energy2 maxQ2) {
// still inside PS, return true if outside
// check vs overestimated limits
if(z() < zLimits().first || z() > zLimits().second) return true;
Energy2 q2 = z()*(1.-z())*t;
if(ids_[0]->id()!=ParticleID::g &&
ids_[0]->id()!=ParticleID::gamma ) q2 += masssquared_[0];
if(q2>maxQ2) return true;
// compute the pts
Energy2 pt2 = z()*(1.-z())*q2 - masssquared_[1]*(1.-z()) - masssquared_[2]*z();
// if pt2<0 veto
if(pt2<pT2min()) return true;
// otherwise calculate pt and return
pT(sqrt(pt2));
return false;
}
ShoKinPtr QTildeSudakov::generateNextTimeBranching(const Energy startingScale,
const IdList &ids,
const RhoDMatrix & rho,
double enhance,
double detuning,
Energy2 maxQ2) {
// First reset the internal kinematics variables that can
// have been eventually set in the previous call to the method.
q_ = ZERO;
z(0.);
phi(0.);
// perform initialization
Energy2 tmax(sqr(startingScale)),tmin;
initialize(ids,tmin);
// check max > min
if(tmax<=tmin) return ShoKinPtr();
// calculate next value of t using veto algorithm
Energy2 t(tmax);
// no shower variations to calculate
if(ShowerHandler::currentHandler()->showerVariations().empty()){
// Without variations do the usual Veto algorithm
// No need for more if-statements in this loop.
do {
if(!guessTimeLike(t,tmin,enhance,detuning)) break;
}
while(PSVeto(t,maxQ2) ||
SplittingFnVeto(z()*(1.-z())*t,ids,true,rho,detuning) ||
- alphaSVeto(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t));
+ alphaSVeto(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t));
}
else {
bool alphaRew(true),PSRew(true),SplitRew(true);
do {
if(!guessTimeLike(t,tmin,enhance,detuning)) break;
PSRew=PSVeto(t,maxQ2);
if (PSRew) continue;
SplitRew=SplittingFnVeto(z()*(1.-z())*t,ids,true,rho,detuning);
- alphaRew=alphaSVeto(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t);
- double factor=alphaSVetoRatio(splittingFn()->angularOrdered() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,1.)*
+ alphaRew=alphaSVeto(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t);
+ double factor=alphaSVetoRatio(splittingFn()->pTScale() ? sqr(z()*(1.-z()))*t : z()*(1.-z())*t,1.)*
SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,rho,detuning);
tShowerHandlerPtr ch = ShowerHandler::currentHandler();
if( !(SplitRew || alphaRew) ) {
//Emission
q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV;
if (q_ <= ZERO) break;
}
for ( map<string,ShowerVariation>::const_iterator var =
ch->showerVariations().begin();
var != ch->showerVariations().end(); ++var ) {
if ( ( ch->firstInteraction() && var->second.firstInteraction ) ||
( !ch->firstInteraction() && var->second.secondaryInteractions ) ) {
- double newfactor = alphaSVetoRatio(splittingFn()->angularOrdered() ?
+ double newfactor = alphaSVetoRatio(splittingFn()->pTScale() ?
sqr(z()*(1.-z()))*t :
z()*(1.-z())*t,var->second.renormalizationScaleFactor)
* SplittingFnVetoRatio(z()*(1.-z())*t,ids,true,rho,detuning);
double varied;
if ( SplitRew || alphaRew ) {
// No Emission
varied = (1. - newfactor) / (1. - factor);
} else {
// Emission
varied = newfactor / factor;
}
map<string,double>::iterator wi = ch->currentWeights().find(var->first);
if ( wi != ch->currentWeights().end() )
wi->second *= varied;
else {
assert(false);
//ch->currentWeights()[var->first] = varied;
}
}
}
}
while(PSRew || SplitRew || alphaRew);
}
q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV;
if(q_ < ZERO) return ShoKinPtr();
// return the ShowerKinematics object
return createFinalStateBranching(q_,z(),phi(),pT());
}
ShoKinPtr QTildeSudakov::
generateNextSpaceBranching(const Energy startingQ,
const IdList &ids,
double x,
const RhoDMatrix & rho,
double enhance,
Ptr<BeamParticleData>::transient_const_pointer beam,
double detuning) {
// First reset the internal kinematics variables that can
// have been eventually set in the previous call to the method.
q_ = ZERO;
z(0.);
phi(0.);
// perform the initialization
Energy2 tmax(sqr(startingQ)),tmin;
initialize(ids,tmin);
// check max > min
if(tmax<=tmin) return ShoKinPtr();
// calculate next value of t using veto algorithm
Energy2 t(tmax),pt2(ZERO);
// no shower variations
if(ShowerHandler::currentHandler()->showerVariations().empty()){
// Without variations do the usual Veto algorithm
// No need for more if-statements in this loop.
do {
if(!guessSpaceLike(t,tmin,x,enhance,detuning)) break;
pt2=sqr(1.-z())*t-z()*masssquared_[2];
}
while(pt2 < pT2min()||
z() > zLimits().second||
SplittingFnVeto((1.-z())*t/z(),ids,false,rho,detuning)||
- alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t)||
+ alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t)||
PDFVeto(t,x,ids[0],ids[1],beam));
}
// shower variations
else
{
bool alphaRew(true),PDFRew(true),ptRew(true),zRew(true),SplitRew(true);
do {
if(!guessSpaceLike(t,tmin,x,enhance,detuning)) break;
pt2=sqr(1.-z())*t-z()*masssquared_[2];
ptRew=pt2 < pT2min();
zRew=z() > zLimits().second;
if (ptRew||zRew) continue;
SplitRew=SplittingFnVeto((1.-z())*t/z(),ids,false,rho,detuning);
- alphaRew=alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t);
+ alphaRew=alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t);
PDFRew=PDFVeto(t,x,ids[0],ids[1],beam);
double factor=PDFVetoRatio(t,x,ids[0],ids[1],beam,1.)*
- alphaSVetoRatio(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t,1.)*
+ alphaSVetoRatio(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t,1.)*
SplittingFnVetoRatio((1.-z())*t/z(),ids,false,rho,detuning);
tShowerHandlerPtr ch = ShowerHandler::currentHandler();
if( !(PDFRew || SplitRew || alphaRew) ) {
//Emission
q_ = t > ZERO ? Energy(sqrt(t)) : -1.*MeV;
if (q_ <= ZERO) break;
}
for ( map<string,ShowerVariation>::const_iterator var =
ch->showerVariations().begin();
var != ch->showerVariations().end(); ++var ) {
if ( ( ch->firstInteraction() && var->second.firstInteraction ) ||
( !ch->firstInteraction() && var->second.secondaryInteractions ) ) {
double newfactor = PDFVetoRatio(t,x,ids[0],ids[1],beam,var->second.factorizationScaleFactor)*
- alphaSVetoRatio(splittingFn()->angularOrdered() ?
+ alphaSVetoRatio(splittingFn()->pTScale() ?
sqr(1.-z())*t : (1.-z())*t,var->second.renormalizationScaleFactor)
*SplittingFnVetoRatio((1.-z())*t/z(),ids,false,rho,detuning);
double varied;
if( PDFRew || SplitRew || alphaRew) {
// No Emission
varied = (1. - newfactor) / (1. - factor);
} else {
// Emission
varied = newfactor / factor;
}
map<string,double>::iterator wi = ch->currentWeights().find(var->first);
if ( wi != ch->currentWeights().end() )
wi->second *= varied;
else {
assert(false);
//ch->currentWeights()[var->first] = varied;
}
}
}
}
while( PDFRew || SplitRew || alphaRew);
}
if(t > ZERO && zLimits().first < zLimits().second) q_ = sqrt(t);
else return ShoKinPtr();
pT(sqrt(pt2));
// create the ShowerKinematics and return it
return createInitialStateBranching(q_,z(),phi(),pT());
}
void QTildeSudakov::initialize(const IdList & ids, Energy2 & tmin) {
ids_=ids;
tmin = cutOffOption() != 2 ? ZERO : 4.*pT2min();
masses_ = virtualMasses(ids);
masssquared_.clear();
for(unsigned int ix=0;ix<masses_.size();++ix) {
masssquared_.push_back(sqr(masses_[ix]));
if(ix>0) tmin=max(masssquared_[ix],tmin);
}
}
ShoKinPtr QTildeSudakov::generateNextDecayBranching(const Energy startingScale,
const Energy stoppingScale,
const Energy minmass,
const IdList &ids,
const RhoDMatrix & rho,
double enhance,
double detuning) {
// First reset the internal kinematics variables that can
// have been eventually set in the previous call to this method.
q_ = Constants::MaxEnergy;
z(0.);
phi(0.);
// perform initialisation
Energy2 tmax(sqr(stoppingScale)),tmin;
initialize(ids,tmin);
tmin=sqr(startingScale);
// check some branching possible
if(tmax<=tmin) return ShoKinPtr();
// perform the evolution
Energy2 t(tmin),pt2(-MeV2);
do {
if(!guessDecay(t,tmax,minmass,enhance,detuning)) break;
pt2 = sqr(1.-z())*(t-masssquared_[0])-z()*masssquared_[2];
}
while(SplittingFnVeto((1.-z())*t/z(),ids,true,rho,detuning)||
- alphaSVeto(splittingFn()->angularOrdered() ? sqr(1.-z())*t : (1.-z())*t ) ||
+ alphaSVeto(splittingFn()->pTScale() ? sqr(1.-z())*t : (1.-z())*t ) ||
pt2<pT2min() ||
t*(1.-z())>masssquared_[0]-sqr(minmass));
if(t > ZERO) {
q_ = sqrt(t);
pT(sqrt(pt2));
}
else return ShoKinPtr();
phi(0.);
// create the ShowerKinematics object
return createDecayBranching(q_,z(),phi(),pT());
}
bool QTildeSudakov::guessDecay(Energy2 &t,Energy2 tmax, Energy minmass,
double enhance, double detune) {
// previous scale
Energy2 told = t;
// overestimated limits on z
if(tmax<masssquared_[0]) {
t=-1.0*GeV2;
return false;
}
Energy2 tm2 = tmax-masssquared_[0];
Energy tm = sqrt(tm2);
pair<double,double> limits=make_pair(sqr(minmass/masses_[0]),
1.-sqrt(masssquared_[2]+pT2min()+
0.25*sqr(masssquared_[2])/tm2)/tm
+0.5*masssquared_[2]/tm2);
zLimits(limits);
if(zLimits().second<zLimits().first) {
t=-1.0*GeV2;
return false;
}
// guess values of t and z
t = guesst(told,2,ids_,enhance,ids_[1]==ids_[2],detune);
z(guessz(2,ids_));
// actual values for z-limits
if(t<masssquared_[0]) {
t=-1.0*GeV2;
return false;
}
tm2 = t-masssquared_[0];
tm = sqrt(tm2);
limits=make_pair(sqr(minmass/masses_[0]),
1.-sqrt(masssquared_[2]+pT2min()+
0.25*sqr(masssquared_[2])/tm2)/tm
+0.5*masssquared_[2]/tm2);
zLimits(limits);
if(t>tmax||zLimits().second<zLimits().first) {
t=-1.0*GeV2;
return false;
}
else
return true;
}
bool QTildeSudakov::computeTimeLikeLimits(Energy2 & t) {
if (t < 1e-20 * GeV2) {
t=-1.*GeV2;
return false;
}
// special case for gluon radiating
pair<double,double> limits;
if(ids_[0]->id()==ParticleID::g||ids_[0]->id()==ParticleID::gamma) {
// no emission possible
if(t<16.*(masssquared_[1]+pT2min())) {
t=-1.*GeV2;
return false;
}
// overestimate of the limits
limits.first = 0.5*(1.-sqrt(1.-4.*sqrt((masssquared_[1]+pT2min())/t)));
limits.second = 1.-limits.first;
}
// special case for radiated particle is gluon
else if(ids_[2]->id()==ParticleID::g||ids_[2]->id()==ParticleID::gamma) {
limits.first = sqrt((masssquared_[1]+pT2min())/t);
limits.second = 1.-sqrt((masssquared_[2]+pT2min())/t);
}
else if(ids_[1]->id()==ParticleID::g||ids_[1]->id()==ParticleID::gamma) {
limits.second = sqrt((masssquared_[2]+pT2min())/t);
limits.first = 1.-sqrt((masssquared_[1]+pT2min())/t);
}
else {
limits.first = (masssquared_[1]+pT2min())/t;
limits.second = 1.-(masssquared_[2]+pT2min())/t;
}
if(limits.first>=limits.second) {
t=-1.*GeV2;
return false;
}
zLimits(limits);
return true;
}
bool QTildeSudakov::computeSpaceLikeLimits(Energy2 & t, double x) {
if (t < 1e-20 * GeV2) {
t=-1.*GeV2;
return false;
}
pair<double,double> limits;
// compute the limits
limits.first = x;
double yy = 1.+0.5*masssquared_[2]/t;
limits.second = yy - sqrt(sqr(yy)-1.+pT2min()/t);
// return false if lower>upper
zLimits(limits);
if(limits.second<limits.first) {
t=-1.*GeV2;
return false;
}
else
return true;
}
namespace {
tShowerParticlePtr findCorrelationPartner(ShowerParticle & particle,
bool forward,
ShowerInteraction inter) {
tPPtr child = &particle;
tShowerParticlePtr mother;
if(forward) {
mother = !particle.parents().empty() ?
dynamic_ptr_cast<tShowerParticlePtr>(particle.parents()[0]) : tShowerParticlePtr();
}
else {
mother = particle.children().size()==2 ?
dynamic_ptr_cast<tShowerParticlePtr>(&particle) : tShowerParticlePtr();
}
tShowerParticlePtr partner;
while(mother) {
tPPtr otherChild;
if(forward) {
for (unsigned int ix=0;ix<mother->children().size();++ix) {
if(mother->children()[ix]!=child) {
otherChild = mother->children()[ix];
break;
}
}
}
else {
otherChild = mother->children()[1];
}
tShowerParticlePtr other = dynamic_ptr_cast<tShowerParticlePtr>(otherChild);
if((inter==ShowerInteraction::QCD && otherChild->dataPtr()->coloured()) ||
(inter==ShowerInteraction::QED && otherChild->dataPtr()->charged())) {
partner = other;
break;
}
if(forward && !other->isFinalState()) {
partner = dynamic_ptr_cast<tShowerParticlePtr>(mother);
break;
}
child = mother;
if(forward) {
mother = ! mother->parents().empty() ?
dynamic_ptr_cast<tShowerParticlePtr>(mother->parents()[0]) : tShowerParticlePtr();
}
else {
if(mother->children()[0]->children().size()!=2)
break;
tShowerParticlePtr mtemp =
dynamic_ptr_cast<tShowerParticlePtr>(mother->children()[0]);
if(!mtemp)
break;
else
mother=mtemp;
}
}
if(!partner) {
if(forward) {
partner = dynamic_ptr_cast<tShowerParticlePtr>( child)->partner();
}
else {
if(mother) {
tShowerParticlePtr parent;
if(!mother->children().empty()) {
parent = dynamic_ptr_cast<tShowerParticlePtr>(mother->children()[0]);
}
if(!parent) {
parent = dynamic_ptr_cast<tShowerParticlePtr>(mother);
}
partner = parent->partner();
}
else {
partner = dynamic_ptr_cast<tShowerParticlePtr>(&particle)->partner();
}
}
}
return partner;
}
pair<double,double> softPhiMin(double phi0, double phi1, double A, double B, double C, double D) {
double c01 = cos(phi0 - phi1);
double s01 = sin(phi0 - phi1);
double s012(sqr(s01)), c012(sqr(c01));
double A2(A*A), B2(B*B), C2(C*C), D2(D*D);
if(abs(B/A)<1e-10 && abs(D/C)<1e-10) return make_pair(phi0,phi0+Constants::pi);
double root = sqr(B2)*C2*D2*sqr(s012) + 2.*A*B2*B*C2*C*D*c01*s012 + 2.*A*B2*B*C*D2*D*c01*s012
+ 4.*A2*B2*C2*D2*c012 - A2*B2*C2*D2*s012 - A2*B2*sqr(D2)*s012 - sqr(B2)*sqr(C2)*s012
- sqr(B2)*C2*D2*s012 - 4.*A2*A*B*C*D2*D*c01 - 4.*A*B2*B*C2*C*D*c01 + sqr(A2)*sqr(D2)
+ 2.*A2*B2*C2*D2 + sqr(B2)*sqr(C2);
if(root<0.) return make_pair(phi0,phi0+Constants::pi);
root = sqrt(root);
double denom = (-2.*A*B*C*D*c01 + A2*D2 + B2*C2);
double denom2 = (-B*C*c01 + A*D);
double num = B2*C*D*s012;
return make_pair(atan2(B*s01*(-C*(num + root) / denom + D) / denom2, -(num + root ) / denom) + phi0,
atan2(B*s01*(-C*(num - root) / denom + D) / denom2, -(num - root ) / denom) + phi0);
}
}
double QTildeSudakov::generatePhiForward(ShowerParticle & particle,
const IdList & ids,
ShoKinPtr kinematics,
const RhoDMatrix & rho) {
// no correlations, return flat phi
if(! dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->correlations())
return Constants::twopi*UseRandom::rnd();
// get the kinematic variables
double z = kinematics->z();
Energy2 t = z*(1.-z)*sqr(kinematics->scale());
Energy pT = kinematics->pT();
// if soft correlations
Energy2 pipj,pik;
bool canBeSoft[2] = {ids[1]->id()==ParticleID::g || ids[1]->id()==ParticleID::gamma,
ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma };
vector<Energy2> pjk(3,ZERO);
vector<Energy> Ek(3,ZERO);
Energy Ei,Ej;
Energy2 m12(ZERO),m22(ZERO);
InvEnergy2 aziMax(ZERO);
bool softAllowed = dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()&&
(canBeSoft[0] || canBeSoft[1]);
if(softAllowed) {
// find the partner for the soft correlations
tShowerParticlePtr partner=findCorrelationPartner(particle,true,splittingFn()->interactionType());
// remember we want the softer gluon
bool swapOrder = !canBeSoft[1] || (canBeSoft[0] && canBeSoft[1] && z < 0.5);
double zFact = !swapOrder ? (1.-z) : z;
// compute the transforms to the shower reference frame
// first the boost
Lorentz5Momentum pVect = particle.showerBasis()->pVector();
Lorentz5Momentum nVect = particle.showerBasis()->nVector();
Boost beta_bb;
if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) {
beta_bb = -(pVect + nVect).boostVector();
}
else if(particle.showerBasis()->frame()==ShowerBasis::Rest) {
beta_bb = -pVect.boostVector();
}
else
assert(false);
pVect.boost(beta_bb);
nVect.boost(beta_bb);
Axis axis;
if(particle.showerBasis()->frame()==ShowerBasis::BackToBack) {
axis = pVect.vect().unit();
}
else if(particle.showerBasis()->frame()==ShowerBasis::Rest) {
axis = nVect.vect().unit();
}
else
assert(false);
// and then the rotation
LorentzRotation rot;
if(axis.perp2()>0.) {
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
}
else if(axis.z()<0.) {
rot.rotate(Constants::pi,Axis(1.,0.,0.));
}
rot.invert();
pVect *= rot;
nVect *= rot;
// shower parameters
Energy2 pn = pVect*nVect, m2 = pVect.m2();
double alpha0 = particle.showerParameters().alpha;
double beta0 = 0.5/alpha0/pn*
(sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt));
Lorentz5Momentum qperp0(particle.showerParameters().ptx,
particle.showerParameters().pty,ZERO,ZERO);
assert(partner);
Lorentz5Momentum pj = partner->momentum();
pj.boost(beta_bb);
pj *= rot;
// compute the two phi independent dot products
pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn )
+0.5*sqr(pT)/zFact;
Energy2 dot1 = pj*pVect;
Energy2 dot2 = pj*nVect;
Energy2 dot3 = pj*qperp0;
pipj = alpha0*dot1+beta0*dot2+dot3;
// compute the constants for the phi dependent dot product
pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0))
+0.5*sqr(pT)*dot2/pn/zFact/alpha0;
pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT;
pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT;
m12 = sqr(particle.dataPtr()->mass());
m22 = sqr(partner->dataPtr()->mass());
if(swapOrder) {
pjk[1] *= -1.;
pjk[2] *= -1.;
}
Ek[0] = zFact*(alpha0*pVect.t()-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0))
+0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0;
Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT;
Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT;
if(swapOrder) {
Ek[1] *= -1.;
Ek[2] *= -1.;
}
Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2]));
Ei = alpha0*pVect.t()+beta0*nVect.t();
Ej = pj.t();
double phi0 = atan2(-pjk[2],-pjk[1]);
if(phi0<0.) phi0 += Constants::twopi;
double phi1 = atan2(-Ek[2],-Ek[1]);
if(phi1<0.) phi1 += Constants::twopi;
double xi_min = pik/Ei/(Ek[0]+mag2), xi_max = pik/Ei/(Ek[0]-mag2), xi_ij = pipj/Ei/Ej;
if(xi_min>xi_max) swap(xi_min,xi_max);
if(xi_min>xi_ij) softAllowed = false;
Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2]));
if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==1) {
aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag);
}
else if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==2) {
double A = (pipj*Ek[0]- Ej*pik)/Ej/sqr(Ej);
double B = -sqrt(sqr(pipj)*(sqr(Ek[1])+sqr(Ek[2])))/Ej/sqr(Ej);
double C = pjk[0]/sqr(Ej);
double D = -sqrt(sqr(pjk[1])+sqr(pjk[2]))/sqr(Ej);
pair<double,double> minima = softPhiMin(phi0,phi1,A,B,C,D);
aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + max(Ej*(A+B*cos(minima.first -phi1))/(C+D*cos(minima.first -phi0)),
Ej*(A+B*cos(minima.second-phi1))/(C+D*cos(minima.second-phi0))));
}
else
assert(false);
}
// if spin correlations
vector<pair<int,Complex> > wgts;
if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->spinCorrelations()) {
// calculate the weights
wgts = splittingFn()->generatePhiForward(z,t,ids,rho);
}
else {
wgts = vector<pair<int,Complex> >(1,make_pair(0,1.));
}
// generate the azimuthal angle
double phi,wgt;
static const Complex ii(0.,1.);
unsigned int ntry(0);
double phiMax(0.),wgtMax(0.);
do {
phi = Constants::twopi*UseRandom::rnd();
// first the spin correlations bit (gives 1 if correlations off)
Complex spinWgt = 0.;
for(unsigned int ix=0;ix<wgts.size();++ix) {
if(wgts[ix].first==0)
spinWgt += wgts[ix].second;
else
spinWgt += exp(double(wgts[ix].first)*ii*phi)*wgts[ix].second;
}
wgt = spinWgt.real();
if(wgt-1.>1e-10) {
generator()->log() << "Forward spin weight problem " << wgt << " " << wgt-1.
<< " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n";
generator()->log() << "Weights \n";
for(unsigned int ix=0;ix<wgts.size();++ix)
generator()->log() << wgts[ix].first << " " << wgts[ix].second << "\n";
}
// soft correlations bit
double aziWgt = 1.;
if(softAllowed) {
Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi);
Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi);
if(pipj*Eg>pik*Ej) {
if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==1) {
aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax;
}
else if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==2) {
aziWgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax);
}
if(aziWgt-1.>1e-10||aziWgt<-1e-10) {
generator()->log() << "Forward soft weight problem " << aziWgt << " " << aziWgt-1.
<< " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n";
}
}
else {
aziWgt = 0.;
}
}
wgt *= aziWgt;
if(wgt>wgtMax) {
phiMax = phi;
wgtMax = wgt;
}
++ntry;
}
while(wgt<UseRandom::rnd()&&ntry<10000);
if(ntry==10000) {
generator()->log() << "Too many tries to generate phi in forward evolution\n";
phi = phiMax;
}
// return the azimuthal angle
return phi;
}
double QTildeSudakov::generatePhiBackward(ShowerParticle & particle,
const IdList & ids,
ShoKinPtr kinematics,
const RhoDMatrix & rho) {
// no correlations, return flat phi
if(! dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->correlations())
return Constants::twopi*UseRandom::rnd();
// get the kinematic variables
double z = kinematics->z();
Energy2 t = (1.-z)*sqr(kinematics->scale())/z;
Energy pT = kinematics->pT();
// if soft correlations
bool softAllowed = dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations() &&
(ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma);
Energy2 pipj,pik,m12(ZERO),m22(ZERO);
vector<Energy2> pjk(3,ZERO);
Energy Ei,Ej,Ek;
InvEnergy2 aziMax(ZERO);
if(softAllowed) {
// find the partner for the soft correlations
tShowerParticlePtr partner=findCorrelationPartner(particle,false,splittingFn()->interactionType());
double zFact = (1.-z);
// compute the transforms to the shower reference frame
// first the boost
Lorentz5Momentum pVect = particle.showerBasis()->pVector();
Lorentz5Momentum nVect = particle.showerBasis()->nVector();
assert(particle.showerBasis()->frame()==ShowerBasis::BackToBack);
Boost beta_bb = -(pVect + nVect).boostVector();
pVect.boost(beta_bb);
nVect.boost(beta_bb);
Axis axis = pVect.vect().unit();
// and then the rotation
LorentzRotation rot;
if(axis.perp2()>0.) {
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
}
else if(axis.z()<0.) {
rot.rotate(Constants::pi,Axis(1.,0.,0.));
}
rot.invert();
pVect *= rot;
nVect *= rot;
// shower parameters
Energy2 pn = pVect*nVect;
Energy2 m2 = pVect.m2();
double alpha0 = particle.x();
double beta0 = -0.5/alpha0/pn*sqr(alpha0)*m2;
Lorentz5Momentum pj = partner->momentum();
pj.boost(beta_bb);
pj *= rot;
double beta2 = 0.5*(1.-zFact)*(sqr(alpha0*zFact/(1.-zFact))*m2+sqr(pT))/alpha0/zFact/pn;
// compute the two phi independent dot products
Energy2 dot1 = pj*pVect;
Energy2 dot2 = pj*nVect;
pipj = alpha0*dot1+beta0*dot2;
pik = alpha0*(alpha0*zFact/(1.-zFact)*m2+pn*(beta2+zFact/(1.-zFact)*beta0));
// compute the constants for the phi dependent dot product
pjk[0] = alpha0*zFact/(1.-zFact)*dot1+beta2*dot2;
pjk[1] = pj.x()*pT;
pjk[2] = pj.y()*pT;
m12 = ZERO;
m22 = sqr(partner->dataPtr()->mass());
Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2]));
if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==1) {
aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag);
}
else if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==2) {
Ek = alpha0*zFact/(1.-zFact)*pVect.t()+beta2*nVect.t();
Ei = alpha0*pVect.t()+beta0*nVect.t();
Ej = pj.t();
if(pipj*Ek> Ej*pik) {
aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik + (pipj*Ek- Ej*pik)/(pjk[0]-mag));
}
else {
aziMax = 0.5/pik/Ek*(Ei-m12*Ek/pik);
}
}
else {
assert(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==0);
}
}
// if spin correlations
vector<pair<int,Complex> > wgts;
if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->spinCorrelations()) {
// get the weights
wgts = splittingFn()->generatePhiBackward(z,t,ids,rho);
}
else {
wgts = vector<pair<int,Complex> >(1,make_pair(0,1.));
}
// generate the azimuthal angle
double phi,wgt;
static const Complex ii(0.,1.);
unsigned int ntry(0);
double phiMax(0.),wgtMax(0.);
do {
phi = Constants::twopi*UseRandom::rnd();
Complex spinWgt = 0.;
for(unsigned int ix=0;ix<wgts.size();++ix) {
if(wgts[ix].first==0)
spinWgt += wgts[ix].second;
else
spinWgt += exp(double(wgts[ix].first)*ii*phi)*wgts[ix].second;
}
wgt = spinWgt.real();
if(wgt-1.>1e-10) {
generator()->log() << "Backward weight problem " << wgt << " " << wgt-1.
<< " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << z << " " << phi << "\n";
generator()->log() << "Weights \n";
for(unsigned int ix=0;ix<wgts.size();++ix)
generator()->log() << wgts[ix].first << " " << wgts[ix].second << "\n";
}
// soft correlations bit
double aziWgt = 1.;
if(softAllowed) {
Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi);
if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==1) {
aziWgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax;
}
else if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==2) {
aziWgt = max(ZERO,0.5/pik/Ek*(Ei-m12*Ek/pik + pipj*Ek/dot - Ej*pik/dot)/aziMax);
}
if(aziWgt-1.>1e-10||aziWgt<-1e-10) {
generator()->log() << "Backward soft weight problem " << aziWgt << " " << aziWgt-1.
<< " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n";
}
}
wgt *= aziWgt;
if(wgt>wgtMax) {
phiMax = phi;
wgtMax = wgt;
}
++ntry;
}
while(wgt<UseRandom::rnd()&&ntry<10000);
if(ntry==10000) {
generator()->log() << "Too many tries to generate phi in backward evolution\n";
phi = phiMax;
}
// return the azimuthal angle
return phi;
}
double QTildeSudakov::generatePhiDecay(ShowerParticle & particle,
const IdList & ids,
ShoKinPtr kinematics,
const RhoDMatrix &) {
// only soft correlations in this case
// no correlations, return flat phi
if( !(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations() &&
(ids[2]->id()==ParticleID::g || ids[2]->id()==ParticleID::gamma )))
return Constants::twopi*UseRandom::rnd();
// get the kinematic variables
double z = kinematics->z();
Energy pT = kinematics->pT();
// if soft correlations
// find the partner for the soft correlations
tShowerParticlePtr partner = findCorrelationPartner(particle,true,splittingFn()->interactionType());
double zFact(1.-z);
// compute the transforms to the shower reference frame
// first the boost
Lorentz5Momentum pVect = particle.showerBasis()->pVector();
Lorentz5Momentum nVect = particle.showerBasis()->nVector();
assert(particle.showerBasis()->frame()==ShowerBasis::Rest);
Boost beta_bb = -pVect.boostVector();
pVect.boost(beta_bb);
nVect.boost(beta_bb);
Axis axis = nVect.vect().unit();
// and then the rotation
LorentzRotation rot;
if(axis.perp2()>0.) {
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.rotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
}
else if(axis.z()<0.) {
rot.rotate(Constants::pi,Axis(1.,0.,0.));
}
rot.invert();
pVect *= rot;
nVect *= rot;
// shower parameters
Energy2 pn = pVect*nVect;
Energy2 m2 = pVect.m2();
double alpha0 = particle.showerParameters().alpha;
double beta0 = 0.5/alpha0/pn*
(sqr(particle.dataPtr()->mass())-sqr(alpha0)*m2+sqr(particle.showerParameters().pt));
Lorentz5Momentum qperp0(particle.showerParameters().ptx,
particle.showerParameters().pty,ZERO,ZERO);
Lorentz5Momentum pj = partner->momentum();
pj.boost(beta_bb);
pj *= rot;
// compute the two phi independent dot products
Energy2 pik = 0.5*zFact*(sqr(alpha0)*m2 - sqr(particle.showerParameters().pt) + 2.*alpha0*beta0*pn )
+0.5*sqr(pT)/zFact;
Energy2 dot1 = pj*pVect;
Energy2 dot2 = pj*nVect;
Energy2 dot3 = pj*qperp0;
Energy2 pipj = alpha0*dot1+beta0*dot2+dot3;
// compute the constants for the phi dependent dot product
vector<Energy2> pjk(3,ZERO);
pjk[0] = zFact*(alpha0*dot1+dot3-0.5*dot2/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0))
+0.5*sqr(pT)*dot2/pn/zFact/alpha0;
pjk[1] = (pj.x() - dot2/alpha0/pn*qperp0.x())*pT;
pjk[2] = (pj.y() - dot2/alpha0/pn*qperp0.y())*pT;
Energy2 m12 = sqr(particle.dataPtr()->mass());
Energy2 m22 = sqr(partner->dataPtr()->mass());
Energy2 mag = sqrt(sqr(pjk[1])+sqr(pjk[2]));
InvEnergy2 aziMax;
vector<Energy> Ek(3,ZERO);
Energy Ei,Ej;
if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==1) {
aziMax = -m12/sqr(pik) -m22/sqr(pjk[0]+mag) +2.*pipj/pik/(pjk[0]-mag);
}
else if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==2) {
Ek[0] = zFact*(alpha0*pVect.t()+-0.5*nVect.t()/pn*(alpha0*m2-sqr(particle.showerParameters().pt)/alpha0))
+0.5*sqr(pT)*nVect.t()/pn/zFact/alpha0;
Ek[1] = -nVect.t()/alpha0/pn*qperp0.x()*pT;
Ek[2] = -nVect.t()/alpha0/pn*qperp0.y()*pT;
Energy mag2=sqrt(sqr(Ek[1])+sqr(Ek[2]));
Ei = alpha0*pVect.t()+beta0*nVect.t();
Ej = pj.t();
aziMax = 0.5/pik/(Ek[0]-mag2)*(Ei-m12*(Ek[0]-mag2)/pik + pipj*(Ek[0]+mag2)/(pjk[0]-mag) - Ej*pik/(pjk[0]-mag) );
}
else
assert(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==0);
// generate the azimuthal angle
double phi,wgt(0.);
unsigned int ntry(0);
double phiMax(0.),wgtMax(0.);
do {
phi = Constants::twopi*UseRandom::rnd();
Energy2 dot = pjk[0]+pjk[1]*cos(phi)+pjk[2]*sin(phi);
if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==1) {
wgt = (-m12/sqr(pik) -m22/sqr(dot) +2.*pipj/pik/dot)/aziMax;
}
else if(dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->softCorrelations()==2) {
if(qperp0.m2()==ZERO) {
wgt = 1.;
}
else {
Energy Eg = Ek[0]+Ek[1]*cos(phi)+Ek[2]*sin(phi);
wgt = max(ZERO,0.5/pik/Eg*(Ei-m12*Eg/pik + (pipj*Eg - Ej*pik)/dot)/aziMax);
}
}
if(wgt-1.>1e-10||wgt<-1e-10) {
generator()->log() << "Decay soft weight problem " << wgt << " " << wgt-1.
<< " " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << " " << " " << phi << "\n";
}
if(wgt>wgtMax) {
phiMax = phi;
wgtMax = wgt;
}
++ntry;
}
while(wgt<UseRandom::rnd()&&ntry<10000);
if(ntry==10000) {
phi = phiMax;
generator()->log() << "Too many tries to generate phi\n";
}
// return the azimuthal angle
return phi;
}
Energy QTildeSudakov::calculateScale(double zin, Energy pt, IdList ids,
unsigned int iopt) {
Energy2 tmin;
initialize(ids,tmin);
// final-state branching
if(iopt==0) {
Energy2 scale=(sqr(pt)+masssquared_[1]*(1.-zin)+masssquared_[2]*zin);
if(ids[0]->id()!=ParticleID::g) scale -= zin*(1.-zin)*masssquared_[0];
scale /= sqr(zin*(1-zin));
return scale<=ZERO ? sqrt(tmin) : sqrt(scale);
}
else if(iopt==1) {
Energy2 scale=(sqr(pt)+zin*masssquared_[2])/sqr(1.-zin);
return scale<=ZERO ? sqrt(tmin) : sqrt(scale);
}
else if(iopt==2) {
Energy2 scale = (sqr(pt)+zin*masssquared_[2])/sqr(1.-zin)+masssquared_[0];
return scale<=ZERO ? sqrt(tmin) : sqrt(scale);
}
else {
throw Exception() << "Unknown option in QTildeSudakov::calculateScale() "
<< "iopt = " << iopt << Exception::runerror;
}
}
ShoKinPtr QTildeSudakov::createFinalStateBranching(Energy scale,double z,
double phi, Energy pt) {
ShoKinPtr showerKin = new_ptr(FS_QTildeShowerKinematics1to2());
showerKin->scale(scale);
showerKin->z(z);
showerKin->phi(phi);
showerKin->pT(pt);
showerKin->SudakovFormFactor(this);
return showerKin;
}
ShoKinPtr QTildeSudakov::createInitialStateBranching(Energy scale,double z,
double phi, Energy pt) {
ShoKinPtr showerKin = new_ptr(IS_QTildeShowerKinematics1to2());
showerKin->scale(scale);
showerKin->z(z);
showerKin->phi(phi);
showerKin->pT(pt);
showerKin->SudakovFormFactor(this);
return showerKin;
}
ShoKinPtr QTildeSudakov::createDecayBranching(Energy scale,double z,
double phi, Energy pt) {
ShoKinPtr showerKin = new_ptr(Decay_QTildeShowerKinematics1to2());
showerKin->scale(scale);
showerKin->z(z);
showerKin->phi(phi);
showerKin->pT(pt);
showerKin->SudakovFormFactor(this);
return showerKin;
}
diff --git a/Shower/QTilde/SplittingFunctions/SplittingFunction.cc b/Shower/QTilde/SplittingFunctions/SplittingFunction.cc
--- a/Shower/QTilde/SplittingFunctions/SplittingFunction.cc
+++ b/Shower/QTilde/SplittingFunctions/SplittingFunction.cc
@@ -1,871 +1,891 @@
// -*- C++ -*-
//
// SplittingFunction.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SplittingFunction class.
//
#include "SplittingFunction.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
DescribeAbstractClass<SplittingFunction,Interfaced>
describeSplittingFunction ("Herwig::SplittingFunction","");
void SplittingFunction::Init() {
static ClassDocumentation<SplittingFunction> documentation
("The SplittingFunction class is the based class for 1->2 splitting functions"
" in Herwig");
static Switch<SplittingFunction,ColourStructure> interfaceColourStructure
("ColourStructure",
"The colour structure for the splitting function",
&SplittingFunction::_colourStructure, Undefined, false, false);
static SwitchOption interfaceColourStructureTripletTripletOctet
(interfaceColourStructure,
"TripletTripletOctet",
"3 -> 3 8",
TripletTripletOctet);
static SwitchOption interfaceColourStructureOctetOctetOctet
(interfaceColourStructure,
"OctetOctetOctet",
"8 -> 8 8",
OctetOctetOctet);
static SwitchOption interfaceColourStructureOctetTripletTriplet
(interfaceColourStructure,
"OctetTripletTriplet",
"8 -> 3 3bar",
OctetTripletTriplet);
static SwitchOption interfaceColourStructureTripletOctetTriplet
(interfaceColourStructure,
"TripletOctetTriplet",
"3 -> 8 3",
TripletOctetTriplet);
static SwitchOption interfaceColourStructureSextetSextetOctet
(interfaceColourStructure,
"SextetSextetOctet",
"6 -> 6 8",
SextetSextetOctet);
static SwitchOption interfaceColourStructureChargedChargedNeutral
(interfaceColourStructure,
"ChargedChargedNeutral",
"q -> q 0",
ChargedChargedNeutral);
static SwitchOption interfaceColourStructureNeutralChargedCharged
(interfaceColourStructure,
"NeutralChargedCharged",
"0 -> q qbar",
NeutralChargedCharged);
static SwitchOption interfaceColourStructureChargedNeutralCharged
(interfaceColourStructure,
"ChargedNeutralCharged",
"q -> 0 q",
ChargedNeutralCharged);
static Switch<SplittingFunction,ShowerInteraction>
interfaceInteractionType
("InteractionType",
"Type of the interaction",
&SplittingFunction::_interactionType,
ShowerInteraction::UNDEFINED, false, false);
static SwitchOption interfaceInteractionTypeQCD
(interfaceInteractionType,
"QCD","QCD",ShowerInteraction::QCD);
static SwitchOption interfaceInteractionTypeQED
(interfaceInteractionType,
"QED","QED",ShowerInteraction::QED);
static Switch<SplittingFunction,bool> interfaceAngularOrdered
("AngularOrdered",
"Whether or not this interaction is angular ordered, "
"normally only g->q qbar and gamma-> f fbar are the only ones which aren't.",
&SplittingFunction::angularOrdered_, true, false, false);
static SwitchOption interfaceAngularOrderedYes
(interfaceAngularOrdered,
"Yes",
"Interaction is angular ordered",
true);
static SwitchOption interfaceAngularOrderedNo
(interfaceAngularOrdered,
"No",
"Interaction isn't angular ordered",
false);
+ static Switch<SplittingFunction,unsigned int> interfaceScaleChoice
+ ("ScaleChoice",
+ "The scale choice to be used",
+ &SplittingFunction::scaleChoice_, 2, false, false);
+ static SwitchOption interfaceScaleChoicepT
+ (interfaceScaleChoice,
+ "pT",
+ "pT of the branching",
+ 0);
+ static SwitchOption interfaceScaleChoiceQ2
+ (interfaceScaleChoice,
+ "Q2",
+ "Q2 of the branching",
+ 1);
+ static SwitchOption interfaceScaleChoiceFromAngularOrdering
+ (interfaceScaleChoice,
+ "FromAngularOrdering",
+ "If angular order use pT, otherwise Q2",
+ 2);
+
}
void SplittingFunction::persistentOutput(PersistentOStream & os) const {
os << oenum(_interactionType) << _interactionOrder
<< oenum(_colourStructure) << _colourFactor
- << angularOrdered_;
+ << angularOrdered_ << scaleChoice_;
}
void SplittingFunction::persistentInput(PersistentIStream & is, int) {
is >> ienum(_interactionType) >> _interactionOrder
>> ienum(_colourStructure) >> _colourFactor
- >> angularOrdered_;
+ >> angularOrdered_ >> scaleChoice_;
}
void SplittingFunction::colourConnection(tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second,
ShowerPartnerType partnerType,
const bool back) const {
if(_colourStructure==TripletTripletOctet) {
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// ensure input consistency
assert(( cparent.first && !cparent.second &&
partnerType==ShowerPartnerType::QCDColourLine) ||
( !cparent.first && cparent.second &&
partnerType==ShowerPartnerType::QCDAntiColourLine));
// q -> q g
if(cparent.first) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
newline->addColoured ( first);
newline->addAntiColoured (second);
}
// qbar -> qbar g
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.second->addAntiColoured(second);
newline->addColoured(second);
newline->addAntiColoured(first);
}
// Set progenitor
first->progenitor(parent->progenitor());
second->progenitor(parent->progenitor());
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// ensure input consistency
assert(( cfirst.first && !cfirst.second &&
partnerType==ShowerPartnerType::QCDColourLine) ||
( !cfirst.first && cfirst.second &&
partnerType==ShowerPartnerType::QCDAntiColourLine));
// q -> q g
if(cfirst.first) {
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addAntiColoured(second);
newline->addColoured(second);
newline->addColoured(parent);
}
// qbar -> qbar g
else {
ColinePtr newline=new_ptr(ColourLine());
cfirst.second->addColoured(second);
newline->addAntiColoured(second);
newline->addAntiColoured(parent);
}
// Set progenitor
parent->progenitor(first->progenitor());
second->progenitor(first->progenitor());
}
}
else if(_colourStructure==OctetOctetOctet) {
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// ensure input consistency
assert(cparent.first&&cparent.second);
// ensure first gluon is hardest
if( first->id()==second->id() && parent->showerKinematics()->z()<0.5 )
swap(first,second);
// colour line radiates
if(partnerType==ShowerPartnerType::QCDColourLine) {
// The colour line is radiating
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
cparent.second->addAntiColoured(first);
newline->addColoured(first);
newline->addAntiColoured(second);
}
// anti colour line radiates
else if(partnerType==ShowerPartnerType::QCDAntiColourLine) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
cparent.second->addAntiColoured(second);
newline->addColoured(second);
newline->addAntiColoured(first);
}
else
assert(false);
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// ensure input consistency
assert(cfirst.first&&cfirst.second);
// The colour line is radiating
if(partnerType==ShowerPartnerType::QCDColourLine) {
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addAntiColoured(second);
cfirst.second->addAntiColoured(parent);
newline->addColoured(parent);
newline->addColoured(second);
}
// anti colour line radiates
else if(partnerType==ShowerPartnerType::QCDAntiColourLine) {
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addColoured(parent);
cfirst.second->addColoured(second);
newline->addAntiColoured(second);
newline->addAntiColoured(parent);
}
else
assert(false);
}
}
else if(_colourStructure == OctetTripletTriplet) {
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// ensure input consistency
assert(cparent.first&&cparent.second);
cparent.first ->addColoured ( first);
cparent.second->addAntiColoured(second);
// Set progenitor
first->progenitor(parent->progenitor());
second->progenitor(parent->progenitor());
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// ensure input consistency
assert(( cfirst.first && !cfirst.second) ||
(!cfirst.first && cfirst.second));
// g -> q qbar
if(cfirst.first) {
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addColoured(parent);
newline->addAntiColoured(second);
newline->addAntiColoured(parent);
}
// g -> qbar q
else {
ColinePtr newline=new_ptr(ColourLine());
cfirst.second->addAntiColoured(parent);
newline->addColoured(second);
newline->addColoured(parent);
}
// Set progenitor
parent->progenitor(first->progenitor());
second->progenitor(first->progenitor());
}
}
else if(_colourStructure == TripletOctetTriplet) {
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// ensure input consistency
assert(( cparent.first && !cparent.second) ||
(!cparent.first && cparent.second));
// q -> g q
if(cparent.first) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
newline->addColoured (second);
newline->addAntiColoured( first);
}
// qbar -> g qbar
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.second->addAntiColoured(first);
newline->addColoured ( first);
newline->addAntiColoured(second);
}
// Set progenitor
first->progenitor(parent->progenitor());
second->progenitor(parent->progenitor());
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// ensure input consistency
assert(cfirst.first&&cfirst.second);
// q -> g q
if(parent->id()>0) {
cfirst.first ->addColoured(parent);
cfirst.second->addColoured(second);
}
else {
cfirst.first ->addAntiColoured(second);
cfirst.second->addAntiColoured(parent);
}
// Set progenitor
parent->progenitor(first->progenitor());
second->progenitor(first->progenitor());
}
}
else if(_colourStructure==SextetSextetOctet) {
//make sure we're not doing backward evolution
assert(!back);
//make sure something sensible
assert(parent->colourLine() || parent->antiColourLine());
//get the colour lines or anti-colour lines
bool isAntiColour=true;
ColinePair cparent;
if(parent->colourLine()) {
cparent = ColinePair(const_ptr_cast<tColinePtr>(parent->colourInfo()->colourLines()[0]),
const_ptr_cast<tColinePtr>(parent->colourInfo()->colourLines()[1]));
isAntiColour=false;
}
else {
cparent = ColinePair(const_ptr_cast<tColinePtr>(parent->colourInfo()->antiColourLines()[0]),
const_ptr_cast<tColinePtr>(parent->colourInfo()->antiColourLines()[1]));
}
//check for sensible input
// assert(cparent.first && cparent.second);
// sextet has 2 colour lines
if(!isAntiColour) {
//pick at random which of the colour topolgies to take
double topology = UseRandom::rnd();
if(topology < 0.25) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
cparent.second->addColoured(first);
newline->addColoured(first);
newline->addAntiColoured(second);
}
else if(topology >=0.25 && topology < 0.5) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
cparent.second->addColoured(second);
newline->addColoured(first);
newline->addAntiColoured(second);
}
else if(topology >= 0.5 && topology < 0.75) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
cparent.second->addColoured(first);
newline->addColoured(first);
newline->addAntiColoured(second);
}
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
cparent.second->addColoured(second);
newline->addColoured(first);
newline->addAntiColoured(second);
}
}
// sextet has 2 anti-colour lines
else {
double topology = UseRandom::rnd();
if(topology < 0.25){
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addAntiColoured(second);
cparent.second->addAntiColoured(first);
newline->addAntiColoured(first);
newline->addColoured(second);
}
else if(topology >=0.25 && topology < 0.5) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addAntiColoured(first);
cparent.second->addAntiColoured(second);
newline->addAntiColoured(first);
newline->addColoured(second);
}
else if(topology >= 0.5 && topology < 0.75) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addAntiColoured(second);
cparent.second->addAntiColoured(first);
newline->addAntiColoured(first);
newline->addColoured(second);
}
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addAntiColoured(first);
cparent.second->addAntiColoured(second);
newline->addAntiColoured(first);
newline->addColoured(second);
}
}
}
else if(_colourStructure == ChargedChargedNeutral) {
if(!parent->data().coloured()) return;
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// q -> q g
if(cparent.first) {
cparent.first->addColoured(first);
}
// qbar -> qbar g
if(cparent.second) {
cparent.second->addAntiColoured(first);
}
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// q -> q g
if(cfirst.first) {
cfirst.first->addColoured(parent);
}
// qbar -> qbar g
if(cfirst.second) {
cfirst.second->addAntiColoured(parent);
}
}
}
else if(_colourStructure == ChargedNeutralCharged) {
if(!parent->data().coloured()) return;
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// q -> q g
if(cparent.first) {
cparent.first->addColoured(second);
}
// qbar -> qbar g
if(cparent.second) {
cparent.second->addAntiColoured(second);
}
}
else {
if (second->dataPtr()->iColour()==PDT::Colour3 ) {
ColinePtr newline=new_ptr(ColourLine());
newline->addColoured(second);
newline->addColoured(parent);
}
else if (second->dataPtr()->iColour()==PDT::Colour3bar ) {
ColinePtr newline=new_ptr(ColourLine());
newline->addAntiColoured(second);
newline->addAntiColoured(parent);
}
}
}
else if(_colourStructure == NeutralChargedCharged ) {
if(!back) {
if(first->dataPtr()->coloured()) {
ColinePtr newline=new_ptr(ColourLine());
if(first->dataPtr()->iColour()==PDT::Colour3) {
newline->addColoured (first );
newline->addAntiColoured(second);
}
else if (first->dataPtr()->iColour()==PDT::Colour3bar) {
newline->addColoured (second);
newline->addAntiColoured(first );
}
else
assert(false);
}
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// gamma -> q qbar
if(cfirst.first) {
cfirst.first->addAntiColoured(second);
}
// gamma -> qbar q
else if(cfirst.second) {
cfirst.second->addColoured(second);
}
else
assert(false);
}
}
else {
assert(false);
}
}
void SplittingFunction::doinit() {
Interfaced::doinit();
assert(_interactionType!=ShowerInteraction::UNDEFINED);
assert((_colourStructure>0&&_interactionType==ShowerInteraction::QCD) ||
(_colourStructure<0&&_interactionType==ShowerInteraction::QED) );
if(_colourFactor>0.) return;
// compute the colour factors if need
if(_colourStructure==TripletTripletOctet) {
_colourFactor = 4./3.;
}
else if(_colourStructure==OctetOctetOctet) {
_colourFactor = 3.;
}
else if(_colourStructure==OctetTripletTriplet) {
_colourFactor = 0.5;
}
else if(_colourStructure==TripletOctetTriplet) {
_colourFactor = 4./3.;
}
else if(_colourStructure==SextetSextetOctet) {
_colourFactor = 10./3.;
}
else if(_colourStructure<0) {
_colourFactor = 1.;
}
else {
assert(false);
}
}
bool SplittingFunction::checkColours(const IdList & ids) const {
if(_colourStructure==TripletTripletOctet) {
if(ids[0]!=ids[1]) return false;
if((ids[0]->iColour()==PDT::Colour3||ids[0]->iColour()==PDT::Colour3bar) &&
ids[2]->iColour()==PDT::Colour8) return true;
return false;
}
else if(_colourStructure==OctetOctetOctet) {
for(unsigned int ix=0;ix<3;++ix) {
if(ids[ix]->iColour()!=PDT::Colour8) return false;
}
return true;
}
else if(_colourStructure==OctetTripletTriplet) {
if(ids[0]->iColour()!=PDT::Colour8) return false;
if(ids[1]->iColour()==PDT::Colour3&&ids[2]->iColour()==PDT::Colour3bar)
return true;
if(ids[1]->iColour()==PDT::Colour3bar&&ids[2]->iColour()==PDT::Colour3)
return true;
return false;
}
else if(_colourStructure==TripletOctetTriplet) {
if(ids[0]!=ids[2]) return false;
if((ids[0]->iColour()==PDT::Colour3||ids[0]->iColour()==PDT::Colour3bar) &&
ids[1]->iColour()==PDT::Colour8) return true;
return false;
}
else if(_colourStructure==SextetSextetOctet) {
if(ids[0]!=ids[1]) return false;
if((ids[0]->iColour()==PDT::Colour6 || ids[0]->iColour()==PDT::Colour6bar) &&
ids[2]->iColour()==PDT::Colour8) return true;
return false;
}
else if(_colourStructure==ChargedChargedNeutral) {
if(ids[0]!=ids[1]) return false;
if(ids[2]->iCharge()!=0) return false;
if(ids[0]->iCharge()==ids[1]->iCharge()) return true;
return false;
}
else if(_colourStructure==ChargedNeutralCharged) {
if(ids[0]!=ids[2]) return false;
if(ids[1]->iCharge()!=0) return false;
if(ids[0]->iCharge()==ids[2]->iCharge()) return true;
return false;
}
else if(_colourStructure==NeutralChargedCharged) {
if(ids[1]->id()!=-ids[2]->id()) return false;
if(ids[0]->iCharge()!=0) return false;
if(ids[1]->iCharge()==-ids[2]->iCharge()) return true;
return false;
}
else {
assert(false);
}
return false;
}
namespace {
bool hasColour(tPPtr p) {
PDT::Colour colour = p->dataPtr()->iColour();
return colour==PDT::Colour3 || colour==PDT::Colour8 || colour == PDT::Colour6;
}
bool hasAntiColour(tPPtr p) {
PDT::Colour colour = p->dataPtr()->iColour();
return colour==PDT::Colour3bar || colour==PDT::Colour8 || colour == PDT::Colour6bar;
}
}
void SplittingFunction::evaluateFinalStateScales(ShowerPartnerType partnerType,
Energy scale, double z,
tShowerParticlePtr parent,
tShowerParticlePtr emitter,
tShowerParticlePtr emitted) {
// identify emitter and emitted
double zEmitter = z, zEmitted = 1.-z;
bool bosonSplitting(false);
// special for g -> gg, particle highest z is emitter
if(emitter->id() == emitted->id() && emitter->id() == parent->id() &&
zEmitted > zEmitter) {
swap(zEmitted,zEmitter);
swap( emitted, emitter);
}
// otherwise if particle ID same
else if(emitted->id()==parent->id()) {
swap(zEmitted,zEmitter);
swap( emitted, emitter);
}
// no real emitter/emitted
else if(emitter->id()!=parent->id()) {
bosonSplitting = true;
}
// may need to add angularOrder flag here
// now the various scales
// QED
if(partnerType==ShowerPartnerType::QED) {
assert(colourStructure()==ChargedChargedNeutral ||
colourStructure()==ChargedNeutralCharged ||
colourStructure()==NeutralChargedCharged );
// normal case
if(!bosonSplitting) {
assert(colourStructure()==ChargedChargedNeutral ||
colourStructure()==ChargedNeutralCharged );
// set the scales
// emitter
emitter->scales().QED = zEmitter*scale;
emitter->scales().QED_noAO = scale;
emitter->scales().QCD_c = min(scale,parent->scales().QCD_c );
emitter->scales().QCD_c_noAO = min(scale,parent->scales().QCD_c_noAO );
emitter->scales().QCD_ac = min(scale,parent->scales().QCD_ac );
emitter->scales().QCD_ac_noAO = min(scale,parent->scales().QCD_ac_noAO);
// emitted
emitted->scales().QED = zEmitted*scale;
emitted->scales().QED_noAO = scale;
emitted->scales().QCD_c = ZERO;
emitted->scales().QCD_c_noAO = ZERO;
emitted->scales().QCD_ac = ZERO;
emitted->scales().QCD_ac_noAO = ZERO;
}
// gamma -> f fbar
else {
assert(colourStructure()==NeutralChargedCharged );
// emitter
emitter->scales().QED = zEmitter*scale;
emitter->scales().QED_noAO = scale;
if(hasColour(emitter)) {
emitter->scales().QCD_c = zEmitter*scale;
emitter->scales().QCD_c_noAO = scale;
}
if(hasAntiColour(emitter)) {
emitter->scales().QCD_ac = zEmitter*scale;
emitter->scales().QCD_ac_noAO = scale;
}
// emitted
emitted->scales().QED = zEmitted*scale;
emitted->scales().QED_noAO = scale;
if(hasColour(emitted)) {
emitted->scales().QCD_c = zEmitted*scale;
emitted->scales().QCD_c_noAO = scale;
}
if(hasAntiColour(emitted)) {
emitted->scales().QCD_ac = zEmitted*scale;
emitted->scales().QCD_ac_noAO = scale;
}
}
}
// QCD
else {
// normal case eg q -> q g and g -> g g
if(!bosonSplitting) {
emitter->scales().QED = min(scale,parent->scales().QED );
emitter->scales().QED_noAO = min(scale,parent->scales().QED_noAO);
if(partnerType==ShowerPartnerType::QCDColourLine) {
emitter->scales().QCD_c = zEmitter*scale;
emitter->scales().QCD_c_noAO = scale;
emitter->scales().QCD_ac = min(zEmitter*scale,parent->scales().QCD_ac );
emitter->scales().QCD_ac_noAO = min( scale,parent->scales().QCD_ac_noAO);
}
else {
emitter->scales().QCD_c = min(zEmitter*scale,parent->scales().QCD_c );
emitter->scales().QCD_c_noAO = min( scale,parent->scales().QCD_c_noAO );
emitter->scales().QCD_ac = zEmitter*scale;
emitter->scales().QCD_ac_noAO = scale;
}
// emitted
emitted->scales().QED = ZERO;
emitted->scales().QED_noAO = ZERO;
emitted->scales().QCD_c = zEmitted*scale;
emitted->scales().QCD_c_noAO = scale;
emitted->scales().QCD_ac = zEmitted*scale;
emitted->scales().QCD_ac_noAO = scale;
}
// g -> q qbar
else {
// emitter
if(emitter->dataPtr()->charged()) {
emitter->scales().QED = zEmitter*scale;
emitter->scales().QED_noAO = scale;
}
emitter->scales().QCD_c = zEmitter*scale;
emitter->scales().QCD_c_noAO = scale;
emitter->scales().QCD_ac = zEmitter*scale;
emitter->scales().QCD_ac_noAO = scale;
// emitted
if(emitted->dataPtr()->charged()) {
emitted->scales().QED = zEmitted*scale;
emitted->scales().QED_noAO = scale;
}
emitted->scales().QCD_c = zEmitted*scale;
emitted->scales().QCD_c_noAO = scale;
emitted->scales().QCD_ac = zEmitted*scale;
emitted->scales().QCD_ac_noAO = scale;
}
}
}
void SplittingFunction::evaluateInitialStateScales(ShowerPartnerType partnerType,
Energy scale, double z,
tShowerParticlePtr parent,
tShowerParticlePtr spacelike,
tShowerParticlePtr timelike) {
// scale for time-like child
Energy AOScale = (1.-z)*scale;
// QED
if(partnerType==ShowerPartnerType::QED) {
if(parent->id()==spacelike->id()) {
// parent
parent ->scales().QED = scale;
parent ->scales().QED_noAO = scale;
parent ->scales().QCD_c = min(scale,spacelike->scales().QCD_c );
parent ->scales().QCD_c_noAO = min(scale,spacelike->scales().QCD_c_noAO );
parent ->scales().QCD_ac = min(scale,spacelike->scales().QCD_ac );
parent ->scales().QCD_ac_noAO = min(scale,spacelike->scales().QCD_ac_noAO);
// timelike
timelike->scales().QED = AOScale;
timelike->scales().QED_noAO = scale;
timelike->scales().QCD_c = ZERO;
timelike->scales().QCD_c_noAO = ZERO;
timelike->scales().QCD_ac = ZERO;
timelike->scales().QCD_ac_noAO = ZERO;
}
else if(parent->id()==timelike->id()) {
parent ->scales().QED = scale;
parent ->scales().QED_noAO = scale;
if(hasColour(parent)) {
parent ->scales().QCD_c = scale;
parent ->scales().QCD_c_noAO = scale;
}
if(hasAntiColour(parent)) {
parent ->scales().QCD_ac = scale;
parent ->scales().QCD_ac_noAO = scale;
}
// timelike
timelike->scales().QED = AOScale;
timelike->scales().QED_noAO = scale;
if(hasColour(timelike)) {
timelike->scales().QCD_c = AOScale;
timelike->scales().QCD_c_noAO = scale;
}
if(hasAntiColour(timelike)) {
timelike->scales().QCD_ac = AOScale;
timelike->scales().QCD_ac_noAO = scale;
}
}
else {
parent ->scales().QED = scale;
parent ->scales().QED_noAO = scale;
parent ->scales().QCD_c = ZERO ;
parent ->scales().QCD_c_noAO = ZERO ;
parent ->scales().QCD_ac = ZERO ;
parent ->scales().QCD_ac_noAO = ZERO ;
// timelike
timelike->scales().QED = AOScale;
timelike->scales().QED_noAO = scale;
if(hasColour(timelike)) {
timelike->scales().QCD_c = min(AOScale,spacelike->scales().QCD_ac );
timelike->scales().QCD_c_noAO = min( scale,spacelike->scales().QCD_ac_noAO);
}
if(hasAntiColour(timelike)) {
timelike->scales().QCD_ac = min(AOScale,spacelike->scales().QCD_c );
timelike->scales().QCD_ac_noAO = min( scale,spacelike->scales().QCD_c_noAO );
}
}
}
// QCD
else {
// timelike
if(timelike->dataPtr()->charged()) {
timelike->scales().QED = AOScale;
timelike->scales().QED_noAO = scale;
}
if(hasColour(timelike)) {
timelike->scales().QCD_c = AOScale;
timelike->scales().QCD_c_noAO = scale;
}
if(hasAntiColour(timelike)) {
timelike->scales().QCD_ac = AOScale;
timelike->scales().QCD_ac_noAO = scale;
}
if(parent->id()==spacelike->id()) {
parent ->scales().QED = min(scale,spacelike->scales().QED );
parent ->scales().QED_noAO = min(scale,spacelike->scales().QED_noAO );
parent ->scales().QCD_c = min(scale,spacelike->scales().QCD_c );
parent ->scales().QCD_c_noAO = min(scale,spacelike->scales().QCD_c_noAO );
parent ->scales().QCD_ac = min(scale,spacelike->scales().QCD_ac );
parent ->scales().QCD_ac_noAO = min(scale,spacelike->scales().QCD_ac_noAO);
}
else {
if(parent->dataPtr()->charged()) {
parent ->scales().QED = scale;
parent ->scales().QED_noAO = scale;
}
if(hasColour(parent)) {
parent ->scales().QCD_c = scale;
parent ->scales().QCD_c_noAO = scale;
}
if(hasAntiColour(parent)) {
parent ->scales().QCD_ac = scale;
parent ->scales().QCD_ac_noAO = scale;
}
}
}
}
void SplittingFunction::evaluateDecayScales(ShowerPartnerType partnerType,
Energy scale, double z,
tShowerParticlePtr parent,
tShowerParticlePtr spacelike,
tShowerParticlePtr timelike) {
assert(parent->id()==spacelike->id());
// angular-ordered scale for 2nd child
Energy AOScale = (1.-z)*scale;
// QED
if(partnerType==ShowerPartnerType::QED) {
// timelike
timelike->scales().QED = AOScale;
timelike->scales().QED_noAO = scale;
timelike->scales().QCD_c = ZERO;
timelike->scales().QCD_c_noAO = ZERO;
timelike->scales().QCD_ac = ZERO;
timelike->scales().QCD_ac_noAO = ZERO;
// spacelike
spacelike->scales().QED = scale;
spacelike->scales().QED_noAO = scale;
}
// QCD
else {
// timelike
timelike->scales().QED = ZERO;
timelike->scales().QED_noAO = ZERO;
timelike->scales().QCD_c = AOScale;
timelike->scales().QCD_c_noAO = scale;
timelike->scales().QCD_ac = AOScale;
timelike->scales().QCD_ac_noAO = scale;
// spacelike
spacelike->scales().QED = max(scale,parent->scales().QED );
spacelike->scales().QED_noAO = max(scale,parent->scales().QED_noAO );
}
spacelike->scales().QCD_c = max(scale,parent->scales().QCD_c );
spacelike->scales().QCD_c_noAO = max(scale,parent->scales().QCD_c_noAO );
spacelike->scales().QCD_ac = max(scale,parent->scales().QCD_ac );
spacelike->scales().QCD_ac_noAO = max(scale,parent->scales().QCD_ac_noAO);
}
diff --git a/Shower/QTilde/SplittingFunctions/SplittingFunction.h b/Shower/QTilde/SplittingFunctions/SplittingFunction.h
--- a/Shower/QTilde/SplittingFunctions/SplittingFunction.h
+++ b/Shower/QTilde/SplittingFunctions/SplittingFunction.h
@@ -1,371 +1,385 @@
// -*- C++ -*-
//
// SplittingFunction.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SplittingFunction_H
#define HERWIG_SplittingFunction_H
//
// This is the declaration of the SplittingFunction class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "Herwig/Shower/QTilde/ShowerConfig.h"
#include "ThePEG/EventRecord/RhoDMatrix.h"
#include "Herwig/Decay/DecayMatrixElement.h"
#include "Herwig/Shower/QTilde/Base/ShowerKinematics.fh"
#include "ThePEG/EventRecord/ColourLine.h"
#include "ThePEG/PDT/ParticleData.h"
#include "SplittingFunction.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* Enum to define the possible types of colour structure which can occur in
* the branching.
*/
enum ColourStructure {Undefined=0,
TripletTripletOctet = 1,OctetOctetOctet =2,
OctetTripletTriplet = 3,TripletOctetTriplet=4,
SextetSextetOctet = 5,
ChargedChargedNeutral=-1,ChargedNeutralCharged=-2,
NeutralChargedCharged=-3};
/** \ingroup Shower
*
* This is an abstract class which defines the common interface
* for all \f$1\to2\f$ splitting functions, for both initial-state
* and final-state radiation.
*
* The SplittingFunction class contains a number of purely virtual members
* which must be implemented in the inheriting classes. The class also stores
* the interaction type of the spltting function.
*
* The inheriting classes need to specific the splitting function
* \f$P(z,2p_j\cdot p_k)\f$, in terms of the energy fraction \f$z\f$ and
* the evolution scale. In order to allow the splitting functions to be used
* with different choices of evolution functions the scale is given by
* \f[2p_j\cdot p_k=(p_j+p_k)^2-m_{jk}^2=Q^2-(p_j+p_k)^2=z(1-z)\tilde{q}^2=
* \frac{p_T^2}{z(1-z)}-m_{jk}^2+\frac{m_j^2}{z}+\frac{m_k^2}{1-z},\f]
* where \f$Q^2\f$ is the virtuality of the branching particle,
* $p_T$ is the relative transverse momentum of the branching products and
* \f$\tilde{q}^2\f$ is the angular variable described in hep-ph/0310083.
*
* In addition an overestimate of the
* splitting function, \f$P_{\rm over}(z)\f$ which only depends upon \f$z\f$,
* the integral, inverse of the integral for this overestimate and
* ratio of the true splitting function to the overestimate must be provided
* as they are necessary for the veto alogrithm used to implement the evolution.
*
* @see \ref SplittingFunctionInterfaces "The interfaces"
* defined for SplittingFunction.
*/
class SplittingFunction: public Interfaced {
public:
/**
* The default constructor.
* @param b All splitting functions must have an interaction order
*/
SplittingFunction(unsigned int b)
: Interfaced(), _interactionType(ShowerInteraction::UNDEFINED),
_interactionOrder(b),
_colourStructure(Undefined), _colourFactor(-1.),
- angularOrdered_(true) {}
+ angularOrdered_(true), scaleChoice_(2) {}
+
public:
/**
* Methods to return the interaction type and order for the splitting function
*/
//@{
/**
* Return the type of the interaction
*/
ShowerInteraction interactionType() const {return _interactionType;}
/**
* Return the order of the splitting function in the interaction
*/
unsigned int interactionOrder() const {return _interactionOrder;}
/**
* Return the colour structure
*/
ColourStructure colourStructure() const {return _colourStructure;}
/**
* Return the colour factor
*/
double colourFactor(const IdList &ids) const {
if(_colourStructure>0)
return _colourFactor;
else if(_colourStructure<0) {
if(_colourStructure==ChargedChargedNeutral ||
_colourStructure==ChargedNeutralCharged) {
return sqr(double(ids[0]->iCharge())/3.);
}
else if(_colourStructure==NeutralChargedCharged) {
return sqr(double(ids[1]->iCharge())/3.);
}
else
assert(false);
}
else
assert(false);
}
//@}
/**
* Purely virtual method which should determine whether this splitting
* function can be used for a given set of particles.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual bool accept(const IdList & ids) const = 0;
/**
* Method to check the colours are correct
*/
virtual bool checkColours(const IdList & ids) const;
/**
* Methods to return the splitting function.
*/
//@{
/**
* Purely virtual method which should return the exact value of the splitting function,
* \f$P\f$ evaluated in terms of the energy fraction, \f$z\f$, and the evolution scale
\f$\tilde{q}^2\f$.
* @param z The energy fraction.
* @param t The scale \f$t=2p_j\cdot p_k\f$.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double P(const double z, const Energy2 t, const IdList & ids,
const bool mass, const RhoDMatrix & rho) const = 0;
/**
* Purely virtual method which should return
* an overestimate of the splitting function,
* \f$P_{\rm over}\f$ such that the result \f$P_{\rm over}\geq P\f$. This function
* should be simple enough that it does not depend on the evolution scale.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual double overestimateP(const double z, const IdList & ids) const = 0;
/**
* Purely virtual method which should return
* the ratio of the splitting function to the overestimate, i.e.
* \f$P(z,\tilde{q}^2)/P_{\rm over}(z)\f$.
* @param z The energy fraction.
* @param t The scale \f$t=2p_j\cdot p_k\f$.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double ratioP(const double z, const Energy2 t, const IdList & ids,
const bool mass, const RhoDMatrix & rho) const = 0;
/**
* Purely virtual method which should return the indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*
*/
virtual double integOverP(const double z, const IdList & ids,
unsigned int PDFfactor=0) const = 0;
/**
* Purely virtual method which should return the inverse of the
* indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$ which is used to
* generate the value of \f$z\f$.
* @param r Value of the splitting function to be inverted
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double invIntegOverP(const double r, const IdList & ids,
unsigned int PDFfactor=0) const = 0;
//@}
/**
* Purely virtual method which should make the proper colour connection
* between the emitting parent and the branching products.
* @param parent The parent for the branching
* @param first The first branching product
* @param second The second branching product
* @param partnerType The type of evolution partner
* @param back Whether this is foward or backward evolution.
*/
virtual void colourConnection(tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second,
ShowerPartnerType partnerType,
const bool back) const;
/**
* Method to calculate the azimuthal angle for forward evolution
* @param z The energy fraction
* @param t The scale \f$t=2p_j\cdot p_k\f$.
* @param ids The PDG codes for the particles in the splitting.
* @param The azimuthal angle, \f$\phi\f$.
* @return The weight
*/
virtual vector<pair<int,Complex> >
generatePhiForward(const double z, const Energy2 t, const IdList & ids,
const RhoDMatrix &) = 0;
/**
* Method to calculate the azimuthal angle for backward evolution
* @param z The energy fraction
* @param t The scale \f$t=2p_j\cdot p_k\f$.
* @param ids The PDG codes for the particles in the splitting.
* @return The weight
*/
virtual vector<pair<int,Complex> >
generatePhiBackward(const double z, const Energy2 t, const IdList & ids,
const RhoDMatrix &) = 0;
/**
* Calculate the matrix element for the splitting
* @param z The energy fraction
* @param t The scale \f$t=2p_j\cdot p_k\f$.
* @param ids The PDG codes for the particles in the splitting.
* @param phi The azimuthal angle, \f$\phi\f$.
* @param timeLike Whether timelike or spacelike, affects inclusive of mass terms
*/
virtual DecayMEPtr matrixElement(const double z, const Energy2 t,
const IdList & ids, const double phi,
bool timeLike) = 0;
/**
* Whether or not the interaction is angular ordered
*/
bool angularOrdered() const {return angularOrdered_;}
/**
+ * Scale choice
+ */
+ bool pTScale() const {
+ return scaleChoice_ == 2 ? angularOrdered_ : scaleChoice_ == 0;
+ }
+
+ /**
* Functions to state scales after branching happens
*/
//@{
/**
* Sort out scales for final-state emission
*/
void evaluateFinalStateScales(ShowerPartnerType type,
Energy scale, double z,
tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second);
/**
* Sort out scales for initial-state emission
*/
void evaluateInitialStateScales(ShowerPartnerType type,
Energy scale, double z,
tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second);
/**
* Sort out scales for decay emission
*/
void evaluateDecayScales(ShowerPartnerType type,
Energy scale, double z,
tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
protected:
/**
* Set the colour factor
*/
void colourFactor(double in) {_colourFactor=in;}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SplittingFunction & operator=(const SplittingFunction &);
private:
/**
* The interaction type for the splitting function.
*/
ShowerInteraction _interactionType;
/**
* The order of the splitting function in the coupling
*/
unsigned int _interactionOrder;
/**
* The colour structure
*/
ColourStructure _colourStructure;
/**
* The colour factor
*/
double _colourFactor;
/**
* Whether or not this interaction is angular-ordered
*/
bool angularOrdered_;
+
+ /**
+ * The choice of scale
+ */
+ unsigned int scaleChoice_;
+
};
}
#endif /* HERWIG_SplittingFunction_H */
diff --git a/Shower/ShowerHandler.h b/Shower/ShowerHandler.h
--- a/Shower/ShowerHandler.h
+++ b/Shower/ShowerHandler.h
@@ -1,803 +1,803 @@
// -*- C++ -*-
//
// ShowerHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ShowerHandler_H
#define HERWIG_ShowerHandler_H
//
// This is the declaration of the ShowerHandler class.
//
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/CascadeHandler.h"
#include "ShowerVariation.h"
#include "Herwig/PDF/HwRemDecayer.fh"
#include "ThePEG/EventRecord/RemnantParticle.fh"
#include "UEBase.h"
#include "PerturbativeProcess.h"
#include "Herwig/MatrixElement/Matchbox/Matching/HardScaleProfile.h"
#include "ShowerHandler.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This class is the main driver of the shower: it is responsible for
* the proper handling of all other specific collaborating classes
* and for the storing of the produced particles in the event record.
*
* @see \ref ShowerHandlerInterfaces "The interfaces"
*
* @see ThePEG::CascadeHandler
* @see MPIHandler
* @see HwRemDecayer
*/
class ShowerHandler: public CascadeHandler {
public:
/**
* Typedef for a pair of ThePEG::RemnantParticle pointers.
*/
typedef pair<tRemPPtr, tRemPPtr> RemPair;
public:
/**
* Default constructor
*/
ShowerHandler();
/**
* Destructor
*/
virtual ~ShowerHandler();
public:
/**
* The main method which manages the multiple interactions and starts
* the shower by calling cascade(sub, lastXC).
*/
virtual void cascade();
/**
* pointer to "this", the current ShowerHandler.
*/
static const tShowerHandlerPtr currentHandler() {
assert(currentHandler_);
return currentHandler_;
}
public:
/**
* Hook to allow vetoing of event after showering hard sub-process
* as in e.g. MLM merging.
*/
- virtual bool showerHardProcessVeto() { return false; }
+ virtual bool showerHardProcessVeto() const { return false; }
/**
* Return true, if this cascade handler will perform reshuffling from hard
* process masses.
*/
virtual bool isReshuffling() const { return true; }
/**
* Return true, if the shower handler can generate a truncated
* shower for POWHEG style events generated using Matchbox
*/
virtual bool canHandleMatchboxTrunc() const { return false; }
/**
* Get the PDF freezing scale
*/
Energy pdfFreezingScale() const { return pdfFreezingScale_; }
/**
* Return true if currently the primary subprocess is showered.
*/
bool firstInteraction() const {
if (!eventHandler()->currentCollision())return true;
return ( subProcess_ ==
eventHandler()->currentCollision()->primarySubProcess() );
}
/**
* Return the remnant decayer.
*/
tHwRemDecPtr remnantDecayer() const { return remDec_; }
/**
* Split the hard process into production and decays
* @param tagged The tagged particles from the StepHandler
* @param hard The hard perturbative process
* @param decay The decay particles
*/
void splitHardProcess(tPVector tagged, PerturbativeProcessPtr & hard,
DecayProcessMap & decay) const;
/**
* Decay a particle
*/
tDMPtr decay(PerturbativeProcessPtr,
DecayProcessMap & decay) const;
/**
* Cached lookup of decay modes.
* Generator::findDecayMode() is not efficient.
*/
tDMPtr findDecayMode(const string & tag) const;
/**
* A struct to order the particles in the same way as in the DecayMode's
*/
struct ParticleOrdering {
bool operator() (tcPDPtr p1, tcPDPtr p2);
};
/**
* A container for ordered particles required
* for constructing tags for decay mode lookup.
*/
typedef multiset<tcPDPtr,ParticleOrdering> OrderedParticles;
public:
/**
* @name Switches for initial- and final-state radiation
*/
//@{
/**
* Switch for any radiation
*/
bool doRadiation() const {return doFSR_ || doISR_;}
/**
* Switch on or off final state radiation.
*/
bool doFSR() const { return doFSR_;}
/**
* Switch on or off initial state radiation.
*/
bool doISR() const { return doISR_;}
//@}
public:
/**
* @name Switches for scales
*/
//@{
/**
* Return true if maximum pt should be deduced from the factorization scale
*/
bool hardScaleIsMuF() const { return maxPtIsMuF_; }
/**
* The factorization scale factor.
*/
double factorizationScaleFactor() const {
return factorizationScaleFactor_;
}
/**
* The renormalization scale factor.
*/
double renFac() const {
return renormalizationScaleFactor_;
}
/**
* The factorization scale factor.
*/
double facFac() const {
return factorizationScaleFactor_;
}
/**
* The renormalization scale factor.
*/
double renormalizationScaleFactor() const {
return renormalizationScaleFactor_;
}
/**
* The scale factor for the hard scale
*/
double hardScaleFactor() const {
return hardScaleFactor_;
}
/**
* Return true, if the phase space restrictions of the dipole shower should
* be applied.
*/
bool restrictPhasespace() const { return restrictPhasespace_; }
/**
* Return profile scales
*/
Ptr<HardScaleProfile>::tptr profileScales() const { return hardScaleProfile_; }
/**
* Return the relevant hard scale to be used in the profile scales
*/
virtual Energy hardScale() const;
//@}
public:
/**
* Access the shower variations
*/
map<string,ShowerVariation>& showerVariations() {
return showerVariations_;
}
/**
* Return the shower variations
*/
const map<string,ShowerVariation>& showerVariations() const {
return showerVariations_;
}
/**
* Access the current Weights
*/
map<string,double>& currentWeights() {
return currentWeights_;
}
/**
* Return the current Weights
*/
const map<string,double>& currentWeights() const {
return currentWeights_;
}
/**
* Change the current reweighting factor
*/
void reweight(double w) {
reweight_ = w;
}
/**
* Return the current reweighting factor
*/
double reweight() const {
return reweight_;
}
public:
/**
* struct that is used to catch exceptions which are thrown
* due to energy conservation issues of additional scatters
*/
struct ExtraScatterVeto {};
/**
* struct that is used to catch exceptions which are thrown
* due to fact that the Shower has been invoked more than
* a defined threshold on a certain configuration
*/
struct ShowerTriesVeto {
/** variable to store the number of attempts */
const int tries;
/** constructor */
ShowerTriesVeto(int t) : tries(t) {}
};
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Functions to perform the cascade
*/
//@{
/**
* The main method which manages the showering of a subprocess.
*/
virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb);
/**
* Set up for the cascade
*/
void prepareCascade(tSubProPtr sub) {
current_ = currentStep();
subProcess_ = sub;
}
/**
* Boost all the particles in the collision so that the collision always occurs
* in the rest frame with the incoming particles along the z axis
*/
void boostCollision(bool boost);
//@}
protected:
/**
* Set/unset the current shower handler
*/
//@{
/**
* Set the current handler
*/
void setCurrentHandler() {
currentHandler_ = tShowerHandlerPtr(this);
}
/**
* Unset the current handler
*/
void unSetCurrentHandler() {
currentHandler_ = tShowerHandlerPtr();
}
//@}
protected:
/**
* @name Members relating to the underlying event and MPI
*/
//@{
/**
* Return true if multiple parton interactions are switched on
* and can be used for this beam setup.
*/
bool isMPIOn() const {
return MPIHandler_ && MPIHandler_->beamOK();
}
/**
* Access function for the MPIHandler, it should only be called after
* checking with isMPIOn.
*/
tUEBasePtr getMPIHandler() const {
assert(MPIHandler_);
return MPIHandler_;
}
/**
* Is a beam particle where hadronic structure is resolved
*/
bool isResolvedHadron(tPPtr);
/**
* Get the remnants from the ThePEG::PartonBinInstance es and
* do some checks.
*/
RemPair getRemnants(PBIPair incbins);
/**
* Reset the PDF's after the hard collision has been showered
*/
void setMPIPDFs();
//@}
public:
/**
* Check if a particle decays in the shower
* @param id The PDG code for the particle
*/
bool decaysInShower(long id) const {
return ( particlesDecayInShower_.find( abs(id) ) !=
particlesDecayInShower_.end() );
}
protected:
/**
* Members to handle splitting up of hard process and decays
*/
//@{
/**
* Find decay products from the hard process and create decay processes
* @param parent The parent particle
* @param hard The hard process
* @param decay The decay processes
*/
void findDecayProducts(PPtr parent, PerturbativeProcessPtr hard, DecayProcessMap decay) const;
/**
* Find decay products from the hard process and create decay processes
* @param parent The parent particle
* @param hard The parent hard process
* @param decay The decay processes
*/
void createDecayProcess(PPtr parent,PerturbativeProcessPtr hard, DecayProcessMap & decay) const;
//@}
/**
* @name Functions to return information relevant to the process being showered
*/
//@{
/**
* Return the currently used SubProcess.
*/
tSubProPtr currentSubProcess() const {
assert(subProcess_);
return subProcess_;
}
/**
* Access to the incoming beam particles
*/
tPPair incomingBeams() const {
return incoming_;
}
//@}
protected:
/**
* Weight handling for shower variations
*/
//@
/**
* Combine the variation weights which have been encountered
*/
void combineWeights();
/**
* Initialise the weights in currentEvent()
*/
void initializeWeights();
/**
* Reset the current weights
*/
void resetWeights();
//@}
protected:
/**
* Return the maximum number of attempts for showering
* a given subprocess.
*/
unsigned int maxtry() const { return maxtry_; }
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerHandler & operator=(const ShowerHandler &);
private:
/**
* pointer to "this", the current ShowerHandler.
*/
static tShowerHandlerPtr currentHandler_;
/**
* a MPIHandler to administer the creation of several (semihard)
* partonic interactions.
*/
UEBasePtr MPIHandler_;
/**
* Pointer to the HwRemDecayer
*/
HwRemDecPtr remDec_;
private:
/**
* Maximum tries for various stages of the showering process
*/
//@{
/**
* Maximum number of attempts for the
* main showering loop
*/
unsigned int maxtry_;
/**
* Maximum number of attempts for the regeneration of an additional
* scattering, before the number of scatters is reduced.
*/
unsigned int maxtryMPI_;
/**
* Maximum number of attempts for the regeneration of an additional
* hard scattering, before this event is vetoed.
*/
unsigned int maxtryDP_;
/**
* Maximum number of attempts to generate a decay
*/
unsigned int maxtryDecay_;
//@}
private:
/**
* Factors for the various scales
*/
//@{
/**
* The factorization scale factor.
*/
double factorizationScaleFactor_;
/**
* The renormalization scale factor.
*/
double renormalizationScaleFactor_;
/**
* The scale factor for the hard scale
*/
double hardScaleFactor_;
/**
* True, if the phase space restrictions of the dipole shower should
* be applied.
*/
bool restrictPhasespace_;
/**
* True if maximum pt should be deduced from the factorization scale
*/
bool maxPtIsMuF_;
/**
* The profile scales
*/
Ptr<HardScaleProfile>::ptr hardScaleProfile_;
//@}
private:
/**
* Storage of information about the current event
*/
//@{
/**
* The incoming beam particles for the current collision
*/
tPPair incoming_;
/**
* Boost to get back to the lab
*/
LorentzRotation boost_;
/**
* Const pointer to the currently handeled ThePEG::SubProcess
*/
tSubProPtr subProcess_;
/**
* Const pointer to the current step
*/
tcStepPtr current_;
//@}
private:
/**
* PDFs to be used for the various stages and related parameters
*/
//@{
/**
* The PDF freezing scale
*/
Energy pdfFreezingScale_;
/**
* PDFs to be used for the various stages and related parameters
*/
//@{
/**
* The PDF for beam particle A. Overrides the particle's own PDF setting.
*/
PDFPtr PDFA_;
/**
* The PDF for beam particle B. Overrides the particle's own PDF setting.
*/
PDFPtr PDFB_;
/**
* The PDF for beam particle A for remnant splitting. Overrides the particle's own PDF setting.
*/
PDFPtr PDFARemnant_;
/**
* The PDF for beam particle B for remnant splitting. Overrides the particle's own PDF setting.
*/
PDFPtr PDFBRemnant_;
/**
* The MPI PDF's to be used for secondary scatters.
*/
pair <PDFPtr, PDFPtr> mpipdfs_;
/**
* The MPI PDF's to be used for secondary scatters.
*/
pair <PDFPtr, PDFPtr> rempdfs_;
/**
* The MPI PDF's to be used for secondary scatters.
*/
pair <PDFPtr, PDFPtr> remmpipdfs_;
//@}
private:
/**
* @name Parameters for initial- and final-state radiation
*/
//@{
/**
* Switch on or off final state radiation.
*/
bool doFSR_;
/**
* Switch on or off initial state radiation.
*/
bool doISR_;
//@}
private:
/**
* @name Parameters for particle decays
*/
//@{
/**
* Whether or not to split into hard and decay trees
*/
bool splitHardProcess_;
/**
* PDG codes of the particles which decay during showering
* this is fast storage for use during running
*/
set<long> particlesDecayInShower_;
/**
* PDG codes of the particles which decay during showering
* this is a vector that is interfaced so they can be changed
*/
vector<long> inputparticlesDecayInShower_;
//@}
private:
/**
* Parameters for the space-time model
*/
//@{
/**
* Whether or not to include spa-cetime distances in the shower
*/
bool includeSpaceTime_;
/**
* The minimum virtuality for the space-time model
*/
Energy2 vMin_;
//@}
private:
/**
* Parameters relevant for reweight and variations
*/
//@{
/**
* The shower variations
*/
map<string,ShowerVariation> showerVariations_;
/**
* Command to add a shower variation
*/
string doAddVariation(string);
/**
* A reweighting factor applied by the showering
*/
double reweight_;
/**
* The shower variation weights
*/
map<string,double> currentWeights_;
//@}
};
}
#endif /* HERWIG_ShowerHandler_H */
diff --git a/Tests/ExternNLO/GoSam.in b/Tests/ExternNLO/GoSam.in
--- a/Tests/ExternNLO/GoSam.in
+++ b/Tests/ExternNLO/GoSam.in
@@ -1,65 +1,65 @@
# -*- ThePEG-repository -*-
read Matchbox/PPCollider.in
cd /Herwig/EventHandlers
set EventHandler:LuminosityFunction:Energy 13000*GeV
##################################################
## Process selection
##################################################
## Note that event generation may fail if no matching matrix element has
## been found. Coupling orders are with respect to the Born process,
## i.e. NLO QCD does not require an additional power of alphas.
## Model assumptions
read Matchbox/StandardModelLike.in
read Matchbox/DiagonalCKM.in
## Set the order of the couplings
cd /Herwig/MatrixElements/Matchbox
set Factory:OrderInAlphaS 1
set Factory:OrderInAlphaEW 2
## Select the process
## You may use identifiers such as p, pbar, j, l, mu+, h0 etc.
-do Factory:Process p p -> e+ nu j
+do Factory:Process p p -> e+ e- j
read Matchbox/GoSam-GoSam.in
set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV
set /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV
read Matchbox/DefaultPPJets.in
insert JetCuts:JetRegions 0 FirstJet
cd /Herwig/MatrixElements/Matchbox
set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale
read Matchbox/NLO-NoShower.in
# read Matchbox/LO-NoShower.in
read Matchbox/FiveFlavourScheme.in
read Matchbox/MMHT2014.in
cd /Herwig/Analysis
insert Rivet:Analyses 0 MC_XS
insert Rivet:Analyses 0 MC_ZINC
insert Rivet:Analyses 0 MC_ZJETS
insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 Rivet
##################################################
## Save the generator
##################################################
do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode
# This is for testing only
set /Herwig/Samplers/Sampler:BinSampler /Herwig/Samplers/FlatBinSampler
set /Herwig/Samplers/Sampler:FlatSubprocesses On
set /Herwig/Samplers/Sampler:Verbose On
set /Herwig/EventHandlers/EventHandler:Weighted On
cd /Herwig/Generators
saverun GoSam EventGenerator
diff --git a/Tests/ExternNLO/VBFNLO.in b/Tests/ExternNLO/VBFNLO.in
new file mode 100644
--- /dev/null
+++ b/Tests/ExternNLO/VBFNLO.in
@@ -0,0 +1,131 @@
+##################################################
+## Herwig++/Matchbox input file
+##################################################
+
+##################################################
+## Collider type
+##################################################
+
+read Matchbox/PPCollider.in
+set /Herwig/EventHandlers/EventHandler:Weighted On
+
+cd /Herwig/Generators
+set EventGenerator:MaxErrors 0
+set EventGenerator:IntermediateOutput Yes
+set EventGenerator:RandomNumberGenerator:Seed 47110815
+set EventGenerator:NumberOfEvents 4000000
+
+##################################################
+## Beam energy sqrt(s)
+##################################################
+
+cd /Herwig/EventHandlers
+set EventHandler:LuminosityFunction:Energy 13000*GeV
+
+##################################################
+## Process selection
+##################################################
+
+cd /Herwig/MatrixElements/Matchbox
+set Factory:OrderInAlphaS 0
+set Factory:OrderInAlphaEW 4
+
+do Factory:Process p p j j e+ nu_e
+
+
+# split off PK Operators in hard matrix element
+cd /Herwig/MatrixElements/Matchbox
+set Factory:IndependentVirtuals On
+set Factory:IndependentPKOperators On
+
+read Matchbox/VBFNLO.in
+read Matchbox/VBFDiagramsOnly.in
+
+## Model assumptions
+read Matchbox/StandardModelLike.in
+read Matchbox/DiagonalCKM.in
+
+# switch on random helicity summation for VBFNLO
+cd /Herwig/MatrixElements/Matchbox/Amplitudes
+set VBFNLO:RandomHelicitySummation True
+
+
+##################################################
+## Cut selection
+##################################################
+
+cd /Herwig/Cuts
+
+read Matchbox/DefaultPPJets.in
+
+## Cuts on jets
+insert JetCuts:JetRegions 0 FirstJet
+insert JetCuts:JetRegions 1 SecondJet
+#insert JetCuts:JetRegions 2 ThirdJet
+
+##################################################
+## Scale choice
+##################################################
+
+# max jet p_T
+cd /Herwig/MatrixElements/Matchbox
+set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale
+
+
+##################################################
+## Matching and shower selection
+##################################################
+
+read Matchbox/NLO-NoShower.in
+
+##################################################
+## Scale uncertainties
+##################################################
+
+
+##################################################
+## Shower scale uncertainties
+##################################################
+
+
+##################################################
+## PDF choice
+##################################################
+
+read Matchbox/FourFlavourScheme.in
+read Matchbox/IdentifiedBs.in
+
+##################################################
+## Analyses
+##################################################
+
+
+##################################################
+## Phasespace
+##################################################
+
+read Matchbox/VBFNLOPhasespace.in
+
+##################################################
+## Sampler
+##################################################
+
+# Use Monaco sampler
+
+cd /Herwig/Samplers
+set Sampler:Verbose On
+set MonacoSampler:InitialPoints 1000
+set MonacoSampler:NIterations 4
+set MonacoSampler:EnhancementFactor 1.2
+set MonacoSampler:RandomNumbers RanDist
+set Sampler:BinSampler MonacoSampler
+
+
+##################################################
+## Save the generator
+##################################################
+
+do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode
+
+cd /Herwig/Generators
+saverun VBFNLO EventGenerator
diff --git a/Utilities/Makefile.am b/Utilities/Makefile.am
--- a/Utilities/Makefile.am
+++ b/Utilities/Makefile.am
@@ -1,51 +1,46 @@
SUBDIRS = XML Statistics
noinst_LTLIBRARIES = libHwUtils.la
-pkglib_LTLIBRARIES = libHwRunDirectories.la
+
libHwUtils_la_SOURCES = \
EnumParticles.h \
Interpolator.tcc Interpolator.h \
Kinematics.cc Kinematics.h \
Maths.h Maths.cc \
StandardSelectors.cc StandardSelectors.h\
Histogram.cc Histogram.fh Histogram.h \
GaussianIntegrator.cc GaussianIntegrator.h \
GaussianIntegrator.tcc \
Statistic.h HerwigStrategy.cc HerwigStrategy.h \
GSLIntegrator.h GSLIntegrator.tcc \
GSLBisection.h GSLBisection.tcc GSLHelper.h \
expm-1.h
nodist_libHwUtils_la_SOURCES = hgstamp.inc
BUILT_SOURCES = hgstamp.inc
CLEANFILES = hgstamp.inc
AUTOMAKE_OPTIONS = -Wno-portability
HGVERSION := $(shell hg -R $(top_srcdir) parents --template '"Herwig {node|short} ({branch})"' 2> /dev/null || echo \"$(PACKAGE_STRING)\" || true )
.PHONY: update_hgstamp
hgstamp.inc: update_hgstamp
@[ -f $@ ] || touch $@
@echo '$(HGVERSION)' | cmp -s $@ - || echo '$(HGVERSION)' > $@
libHwUtils_la_LIBADD = \
XML/libHwXML.la \
Statistics/libHwStatistics.la
-libHwRunDirectories_la_SOURCES = \
-RunDirectories.h RunDirectories.cc
-libHwRunDirectories_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0
-
-
check_PROGRAMS = utilities_test
utilities_test_SOURCES = \
tests/utilitiesTestsMain.cc \
tests/utilitiesTestsGlobalFixture.h \
tests/utilitiesTestsKinematics.h \
tests/utilitiesTestMaths.h \
tests/utilitiesTestsStatistic.h
utilities_test_LDADD = $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) $(BOOST_FILESYSTEM_LIBS) $(BOOST_SYSTEM_LIBS) $(THEPEGLIB) -ldl libHwUtils.la
utilities_test_LDFLAGS = $(AM_LDFLAGS) -export-dynamic $(BOOST_UNIT_TEST_FRAMEWORK_LDFLAGS) $(BOOST_SYSTEM_LDFLAGS) $(BOOST_FILESYSTEM_LDFLAGS) $(THEPEGLDFLAGS)
utilities_test_CPPFLAGS = $(AM_CPPFLAGS) $(BOOST_CPPFLAGS) -DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" -DHERWIG_PKGLIBDIR="\"$(pkglibdir)\"" -DTHEPEG_PKGLIBDIR="\"$(THEPEGLIBPATH)\""
TESTS = utilities_test
diff --git a/Utilities/RunDirectories.cc b/Utilities/RunDirectories.cc
deleted file mode 100644
--- a/Utilities/RunDirectories.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// -*- C++ -*-
-//
-// RunDirectories.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2012 The Herwig Collaboration
-//
-// Herwig is licenced under version 2 of the GPL, see COPYING for details.
-// Please respect the MCnet academic guidelines, see GUIDELINES for details.
-//
-
-#include "RunDirectories.h"
-
-#include "ThePEG/Utilities/Exception.h"
-#include "ThePEG/Handlers/SamplerBase.h"
-#include <boost/filesystem.hpp>
-
-using namespace ThePEG;
-using namespace Herwig;
-
-void RunDirectories::prefix(string p) {
- if ( *p.rbegin() != '/' )
- p += "/";
- thePrefix() = p;
-}
-
-const string& RunDirectories::prefix() {
- return thePrefix();
-}
-
-string& RunDirectories::thePrefix() {
- static string p = "./Herwig-scratch/";
- return p;
-}
-
-string& RunDirectories::theBuildStorage() {
- static string builds = "";
- return builds;
-}
-
-const string& RunDirectories::buildStorage() {
- if ( !theBuildStorage().empty() )
- return theBuildStorage();
- theBuildStorage() = prefix();
- if ( theBuildStorage().empty() )
- theBuildStorage() = "./Herwig-scratch/";
- else if ( *theBuildStorage().rbegin() != '/' )
- theBuildStorage() += "/";
- theBuildStorage() += "Build/";
- if ( boost::filesystem::exists(theBuildStorage()) ) {
- if ( !boost::filesystem::is_directory(theBuildStorage()) )
- throw Exception() << "Herwig build storage '"
- << theBuildStorage() << "' existing but not a directory."
- << Exception::abortnow;
- } else {
- boost::filesystem::create_directories(theBuildStorage());
- }
- return theBuildStorage();
-}
-
-bool RunDirectories::empty() {
- return theRunDirectories().empty();
-}
-
-list<string>& RunDirectories::theRunDirectories() {
- static list<string> rundirs;
- return rundirs;
-}
-
-const string& RunDirectories::runStorage() {
- if ( theRunDirectories().empty() )
- throw Exception() << "No run directory stack has been allocated."
- << Exception::abortnow;
- if ( boost::filesystem::exists(theRunDirectories().front()) ) {
- if ( !boost::filesystem::is_directory(theRunDirectories().front()) )
- throw Exception() << "Herwig run storage '"
- << theRunDirectories().front() << "' existing but not a directory."
- << Exception::abortnow;
- } else {
- boost::filesystem::create_directories(theRunDirectories().front());
- }
- return theRunDirectories().front();
-}
-
-const string& RunDirectories::interfaceStorage() {
- if ( SamplerBase::runLevel() == SamplerBase::IntegrationMode ||
- SamplerBase::runLevel() == SamplerBase::RunMode )
- return runStorage();
- return buildStorage();
-}
-
-void RunDirectories::pushRunId(string p) {
- if ( *p.rbegin() != '/' )
- p += "/";
- if ( theRunDirectories().empty() ) {
- theRunDirectories().push_front(prefix() + p);
- return;
- }
- theRunDirectories().push_front(theRunDirectories().front() + p);
-}
-
-RunDirectories::RunDirectories()
- : directoriesLeft(theRunDirectories()) {}
-
-string RunDirectories::nextRunStorage() {
- if ( directoriesLeft.empty() )
- throw Exception() << "No more run directories left to try."
- << Exception::abortnow;
- string res = directoriesLeft.front();
- directoriesLeft.pop_front();
- return res;
-}
-
diff --git a/Utilities/RunDirectories.h b/Utilities/RunDirectories.h
deleted file mode 100644
--- a/Utilities/RunDirectories.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// -*- C++ -*-
-//
-// RunDirectories.h is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2012 The Herwig Collaboration
-//
-// Herwig is licenced under version 2 of the GPL, see COPYING for details.
-// Please respect the MCnet academic guidelines, see GUIDELINES for details.
-//
-#ifndef HERWIG_RunDirectories_H
-#define HERWIG_RunDirectories_H
-//
-// This is the declaration of the RunDirectories class.
-//
-
-#include <string>
-#include <list>
-
-namespace Herwig {
-
-using std::string;
-using std::list;
-
-/**
- * \ingroup Matchbox
- * \author Simon Platzer
- *
- * \brief Handle directories for external library and grid storage.
- *
- */
-class RunDirectories {
-
-public:
-
- /**
- * Set a prefix for storing details of this run.
- */
- static void prefix(string p);
-
- /**
- * Return the prefix for storing details of this run.
- */
- static const string& prefix();
-
- /**
- * Return the name (and possibly create) a storage for build data
- */
- static const string& buildStorage();
-
- /**
- * Return true, if no run directories have been pushed yet
- */
- static bool empty();
-
- /**
- * Push a run identifier onto the run directories stack.
- */
- static void pushRunId(string);
-
- /**
- * Return (and possibly create) the top of the run directory stack
- * to be used for storage.
- */
- static const string& runStorage();
-
- /**
- * Return the storage to be used for interface order/contract files.
- */
- static const string& interfaceStorage();
-
-public:
-
- /**
- * Default constructor fills the directory list to test.
- */
- RunDirectories();
-
- /**
- * Return true, if there are run directories still to be considered.
- */
- operator bool() const { return !directoriesLeft.empty(); }
-
- /**
- * Return true, if there are no run directories still to be considered.
- */
- bool operator!() const { return directoriesLeft.empty(); }
-
- /**
- * Return the next run directory to be considered and pop it from
- * the stack.
- */
- string nextRunStorage();
-
-private:
-
- /**
- * The prefix for storing details of this run.
- */
- static string& thePrefix();
-
- /**
- * The build storage.
- */
- static string& theBuildStorage();
-
- /**
- * The list of run storage directories to be considered.
- */
- static list<string>& theRunDirectories();
-
- /**
- * The current run directory stack under consideration
- */
- list<string> directoriesLeft;
-
-};
-
-}
-
-#endif /* HERWIG_RunDirectories_H */
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -1,241 +1,242 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.63])
AC_INIT([Herwig],[trunk],[herwig@projects.hepforge.org],[Herwig])
AC_CONFIG_SRCDIR([Utilities/HerwigStrategy.cc])
AC_CONFIG_AUX_DIR([Config])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([Config/config.h])
dnl AC_PRESERVE_HELP_ORDER
AC_CANONICAL_HOST
dnl === disable debug symbols by default =====
if test "x$CXXFLAGS" = "x"; then
CXXFLAGS=-O3
fi
if test "x$CFLAGS" = "x"; then
CFLAGS=-O3
fi
AC_LANG([C++])
AM_INIT_AUTOMAKE([1.11 subdir-objects gnu dist-bzip2 no-dist-gzip -Wall])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
dnl Checks for C++ compiler. Handle C++11 flags.
AC_PROG_CXX
AX_CXX_COMPILE_STDCXX([11],[noext],[mandatory])
dnl check for POSIX
AC_CHECK_HEADER([unistd.h],[],
[AC_MSG_ERROR([Herwig needs "unistd.h". Non-POSIX systems are not supported.])])
dnl Checks for programs.
AC_PROG_INSTALL
AC_PROG_MAKE_SET
AC_PROG_LN_S
dnl modified search order
AC_PROG_FC([gfortran g95 g77])
dnl xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn xlf90 f90 pgf90 pghpf epcf90 xlf f77 frt pgf77 cf77 fort77 fl32 af77])
AC_LANG_PUSH([Fortran])
AC_MSG_CHECKING([if the Fortran compiler ($FC) works])
AC_COMPILE_IFELSE(
AC_LANG_PROGRAM([],[ print *[,]"Hello"]),
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([A Fortran compiler is required to build Herwig.])
]
)
AC_LANG_POP([Fortran])
LT_PREREQ([2.2.6])
LT_INIT([disable-static dlopen pic-only])
dnl ####################################
dnl ####################################
dnl for Doc/fixinterfaces.pl
AC_PATH_PROG(PERL, perl)
dnl for Models/Feynrules
AM_PATH_PYTHON([2.6],, [:])
AM_CONDITIONAL([HAVE_PYTHON], [test "x$PYTHON" != "x:"])
HERWIG_CHECK_GSL
HERWIG_CHECK_THEPEG
BOOST_REQUIRE([1.41])
BOOST_FIND_HEADER([boost/numeric/ublas/io.hpp])
BOOST_FIND_HEADER([boost/numeric/ublas/matrix.hpp])
BOOST_FIND_HEADER([boost/numeric/ublas/matrix_proxy.hpp])
BOOST_FIND_HEADER([boost/numeric/ublas/matrix_sparse.hpp])
BOOST_FIND_HEADER([boost/numeric/ublas/symmetric.hpp])
BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp])
BOOST_FIND_HEADER([boost/operators.hpp])
BOOST_FIND_HEADER([boost/progress.hpp])
BOOST_FILESYSTEM([mt])
BOOST_TEST()
HERWIG_CHECK_VBFNLO
HERWIG_CHECK_NJET
HERWIG_CHECK_GOSAM
HERWIG_CHECK_GOSAM_CONTRIB
HERWIG_CHECK_OPENLOOPS
HERWIG_CHECK_MADGRAPH
HERWIG_CHECK_EVTGEN
HERWIG_CHECK_PYTHIA
HERWIG_COMPILERFLAGS
HERWIG_LOOPTOOLS
HERWIG_PDF_PATH
FASTJET_CHECK_FASTJET
HERWIG_ENABLE_MODELS
SHARED_FLAG=-shared
AM_CONDITIONAL(NEED_APPLE_FIXES,
[test "xx${host/darwin/foundit}xx" != "xx${host}xx"])
if test "xx${host/darwin/foundit}xx" != "xx${host}xx"; then
APPLE_DSO_FLAGS=-Wl,-undefined,dynamic_lookup
SHARED_FLAG=-bundle
fi
AC_SUBST([APPLE_DSO_FLAGS])
AC_SUBST([SHARED_FLAG])
AC_CONFIG_FILES([UnderlyingEvent/Makefile
Models/Makefile
Models/StandardModel/Makefile
Models/RSModel/Makefile
Models/General/Makefile
Models/Susy/Makefile
Models/Susy/NMSSM/Makefile
Models/Susy/RPV/Makefile
Models/UED/Makefile
Models/LH/Makefile
Models/LHTP/Makefile
Models/Transplanckian/Makefile
Models/Leptoquarks/Makefile
Models/Zprime/Makefile
Models/TTbAsymm/Makefile
Models/Feynrules/Makefile
Models/Feynrules/python/Makefile-FR
Models/ADD/Makefile
Models/Sextet/Makefile
Decay/Makefile
Decay/FormFactors/Makefile
Decay/Tau/Makefile
Decay/Baryon/Makefile
Decay/VectorMeson/Makefile
Decay/Perturbative/Makefile
Decay/ScalarMeson/Makefile
Decay/TensorMeson/Makefile
Decay/WeakCurrents/Makefile
Decay/Partonic/Makefile
Decay/General/Makefile
Decay/Radiation/Makefile
Decay/EvtGen/Makefile
Doc/refman.conf
Doc/refman.h
PDT/Makefile
PDF/Makefile
MatrixElement/Makefile
MatrixElement/General/Makefile
MatrixElement/Lepton/Makefile
MatrixElement/Hadron/Makefile
MatrixElement/DIS/Makefile
MatrixElement/Powheg/Makefile
MatrixElement/Gamma/Makefile
MatrixElement/Reweighters/Makefile
MatrixElement/Matchbox/Makefile
MatrixElement/Matchbox/Base/Makefile
MatrixElement/Matchbox/Utility/Makefile
MatrixElement/Matchbox/Phasespace/Makefile
MatrixElement/Matchbox/Dipoles/Makefile
MatrixElement/Matchbox/InsertionOperators/Makefile
MatrixElement/Matchbox/Matching/Makefile
MatrixElement/Matchbox/Cuts/Makefile
MatrixElement/Matchbox/Scales/Makefile
MatrixElement/Matchbox/ColorFull/Makefile
MatrixElement/Matchbox/CVolver/Makefile
MatrixElement/Matchbox/Builtin/Makefile
MatrixElement/Matchbox/Builtin/Amplitudes/Makefile
MatrixElement/Matchbox/Tests/Makefile
MatrixElement/Matchbox/External/Makefile
MatrixElement/Matchbox/External/BLHAGeneric/Makefile
MatrixElement/Matchbox/External/VBFNLO/Makefile
MatrixElement/Matchbox/External/NJet/Makefile
MatrixElement/Matchbox/External/GoSam/Makefile
MatrixElement/Matchbox/External/OpenLoops/Makefile
MatrixElement/Matchbox/External/MadGraph/Makefile
MatrixElement/Matchbox/External/MadGraph/mg2herwig.py
Sampling/Makefile
Sampling/CellGrids/Makefile
Shower/Makefile
Shower/QTilde/Makefile
Shower/QTilde/Matching/Makefile
Shower/Dipole/Makefile
Shower/Dipole/Base/Makefile
Shower/Dipole/Kernels/Makefile
Shower/Dipole/Kinematics/Makefile
Shower/Dipole/Utility/Makefile
Shower/Dipole/AlphaS/Makefile
Utilities/Makefile
Utilities/XML/Makefile
Utilities/Statistics/Makefile
Hadronization/Makefile
lib/Makefile
include/Makefile
src/Makefile
src/defaults/Makefile
src/snippets/Makefile
src/Matchbox/Makefile
src/herwig-config
Doc/Makefile
Doc/HerwigDefaults.in
Looptools/Makefile
Analysis/Makefile
+ API/Makefile
src/Makefile-UserModules
src/defaults/Analysis.in
src/defaults/MatchboxDefaults.in
src/defaults/Decays.in
src/defaults/decayers.in
src/defaults/setup.gosam.in
src/Matchbox/LO-DefaultShower.in
src/Matchbox/LO-DipoleShower.in
src/Matchbox/MCatLO-DefaultShower.in
src/Matchbox/MCatLO-DipoleShower.in
src/Matchbox/LO-NoShower.in
src/Matchbox/MCatNLO-DefaultShower.in
src/Matchbox/MCatNLO-DipoleShower.in
src/Matchbox/NLO-NoShower.in
src/Matchbox/Powheg-DefaultShower.in
src/Matchbox/Powheg-DipoleShower.in
src/Merging/Makefile
Shower/Dipole/Merging/Makefile
src/defaults/MatchboxMergingDefaults.in
Contrib/Makefile
Contrib/make_makefiles.sh
Tests/Makefile
Makefile])
AC_CONFIG_LINKS([Doc/BSMlibs.in:Doc/BSMlibs.in])
AC_CONFIG_FILES([Doc/fixinterfaces.pl],[chmod +x Doc/fixinterfaces.pl])
HERWIG_OVERVIEW
AC_CONFIG_COMMANDS([summary],[cat config.herwig])
AC_OUTPUT
diff --git a/include/Makefile.am b/include/Makefile.am
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,36 +1,37 @@
BUILT_SOURCES = done-all-links
AUTOMAKE_OPTIONS = -Wno-portability
DIRLINKS = $(top_srcdir)/Analysis \
$(top_srcdir)/Decay \
$(top_srcdir)/Hadronization \
$(top_srcdir)/MatrixElement \
$(top_srcdir)/Models \
$(top_srcdir)/PDF \
$(top_srcdir)/PDT \
$(top_srcdir)/Shower \
$(top_srcdir)/Sampling \
$(top_srcdir)/UnderlyingEvent \
- $(top_srcdir)/Utilities
+ $(top_srcdir)/Utilities \
+ $(top_srcdir)/API
LOOPTOOLHEADERS = $(top_srcdir)/Looptools/include/clooptools.h
CLEANFILES = done-all-links
done-all-links: $(DIRLINKS) $(LOOPTOOLHEADERS)
mkdir -p Herwig/Config Herwig/Looptools
$(LN_S) -f $(addprefix ../, $(DIRLINKS)) Herwig
$(LN_S) -f $(addprefix ../../, $(LOOPTOOLHEADERS)) Herwig/Looptools
touch done-all-links
install-data-local:
find Herwig -follow \( -name '*.h' -or -name '*.icc' \
-or -name '*.tcc' -or -name '*.fh' -or -name '*.xh' \) \
-exec $(install_sh_DATA) \{\} $(DESTDIR)$(includedir)/\{\} \;
uninstall-local:
rm -rf $(DESTDIR)$(includedir)/Herwig
clean-local:
rm -rf Herwig
diff --git a/m4/herwig.m4 b/m4/herwig.m4
--- a/m4/herwig.m4
+++ b/m4/herwig.m4
@@ -1,904 +1,905 @@
dnl ##### THEPEG #####
AC_DEFUN([HERWIG_CHECK_THEPEG],
[
defaultlocation="${prefix}"
test "x$defaultlocation" = xNONE && defaultlocation="${ac_default_prefix}"
AC_MSG_CHECKING([for libThePEG in])
AC_ARG_WITH(thepeg,
AC_HELP_STRING([--with-thepeg=DIR],[location of ThePEG installation]),
[],
[with_thepeg="${defaultlocation}"])
AC_MSG_RESULT([$with_thepeg])
if test "x$with_thepeg" = "xno"; then
AC_MSG_ERROR([Cannot build Herwig++ without ThePEG. Please set --with-thepeg.])
fi
THEPEGLDFLAGS="-L${with_thepeg}/lib/ThePEG"
THEPEGHASLHAPDF="no"
if test -e ${with_thepeg}/lib/ThePEG/ThePEGLHAPDF.so ; then
THEPEGHASLHAPDF="yes"
fi
if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then
THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG"
if test -e ${with_thepeg}/lib64/ThePEG/ThePEGLHAPDF.so ; then
THEPEGHASLHAPDF="yes"
fi
fi
if test "x$THEPEGHASLHAPDF" == "xno" ; then
AC_MSG_ERROR([Herwig++ requires ThePEG to be build with lhapdf.])
fi
THEPEGHASFASTJET="no"
if test -e ${with_thepeg}/lib/ThePEG/FastJetFinder.so ; then
THEPEGHASFASTJET="yes"
fi
if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then
THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG"
if test -e ${with_thepeg}/lib64/ThePEG/FastJetFinder.so ; then
THEPEGHASFASTJET="yes"
fi
fi
if test "x$THEPEGHASFASTJET" == "xno" ; then
AC_MSG_ERROR([Herwig++ requires ThePEG to be build with FastJet.])
fi
THEPEGPATH="${with_thepeg}"
oldldflags="$LDFLAGS"
oldlibs="$LIBS"
LDFLAGS="$LDFLAGS $THEPEGLDFLAGS"
AC_CHECK_LIB([ThePEG],[debugThePEG],[],
[AC_MSG_ERROR([No ThePEG libraries in $THEPEGLDFLAGS. Please set --with-thepeg.])])
AC_SUBST([THEPEGLIB],[-lThePEG])
AC_SUBST(THEPEGLDFLAGS)
AC_SUBST(THEPEGPATH)
AC_SUBST(THEPEGHASLHAPDF)
AC_SUBST(THEPEGHASFASTJET)
LIBS="$oldlibs"
LDFLAGS="$oldldflags"
AC_MSG_CHECKING([for ThePEG headers in])
AC_ARG_WITH([thepeg-headers],
AC_HELP_STRING([--with-thepeg-headers=DIR],[location of ThePEG include directory]),
[],
[with_thepeg_headers="${with_thepeg}/include"])
AC_MSG_RESULT([$with_thepeg_headers])
if test "x$with_thepeg_headers" = "xno"; then
AC_MSG_ERROR([Cannot build Herwig++ without ThePEG headers. Please set --with-thepeg-headers.])
fi
THEPEGINCLUDE="-I$with_thepeg_headers"
oldcppflags="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $THEPEGINCLUDE"
AC_CHECK_HEADER([ThePEG/Config/ThePEG.h],[],
[AC_MSG_ERROR([No ThePEG headers in $with_thepeg_headers. Please set --with-thepeg-headers.])])
CPPFLAGS="$oldcppflags"
AC_SUBST(THEPEGINCLUDE)
AC_MSG_CHECKING([for HepMCAnalysis.so in ThePEG])
THEPEGHASHEPMC="no"
if test -e ${with_thepeg}/lib/ThePEG/HepMCAnalysis.so ; then
THEPEGHASHEPMC="yes"
fi
if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then
THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG"
if test -e ${with_thepeg}/lib64/ThePEG/HepMCAnalysis.so ; then
THEPEGHASHEPMC="yes"
fi
fi
if test "x$THEPEGHASHEPMC" == "xno" ; then
CREATE_HEPMC="# create"
AC_MSG_RESULT([not found])
else
CREATE_HEPMC="create"
AC_MSG_RESULT([found])
fi
AC_SUBST([CREATE_HEPMC])
AC_MSG_CHECKING([for RivetAnalysis.so in ThePEG])
THEPEGHASRIVET="no"
if test -e ${with_thepeg}/lib/ThePEG/RivetAnalysis.so ; then
THEPEGHASRIVET="yes"
fi
if test "${host_cpu}" == "x86_64" -a -e ${with_thepeg}/lib64/ThePEG/libThePEG.so ; then
THEPEGLDFLAGS="-L${with_thepeg}/lib64/ThePEG"
if test -e ${with_thepeg}/lib64/ThePEG/RivetAnalysis.so ; then
THEPEGHASRIVET="yes"
fi
fi
if test "x$THEPEGHASRIVET" == "xno" ; then
CREATE_RIVET="# create"
AC_MSG_RESULT([not found])
else
CREATE_RIVET="create"
AC_MSG_RESULT([found])
fi
AC_SUBST([CREATE_RIVET])
])
dnl ##### LOOPTOOLS #####
AC_DEFUN([HERWIG_LOOPTOOLS],
[
AC_REQUIRE([AC_PROG_FC])
AC_REQUIRE([AC_FC_LIBRARY_LDFLAGS])
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([HERWIG_COMPILERFLAGS])
AC_MSG_CHECKING([if Looptools build works])
enable_looptools=yes
if test "x$GCC" = "xyes"; then
case "${host}" in
x86_64-*|*-darwin1*)
AM_FCFLAGS="$AM_FCFLAGS -fdefault-integer-8"
;;
esac
AC_LANG_PUSH([Fortran])
oldFCFLAGS="$FCFLAGS"
FCFLAGS="$AM_FCFLAGS"
AC_COMPILE_IFELSE(
AC_LANG_PROGRAM([],[ print *[,]"Hello"]),
[],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([needs gfortran on 64bit machines])]
)
FCFLAGS="$oldFCFLAGS"
AC_LANG_POP([Fortran])
fi
AC_MSG_RESULT([$enable_looptools])
AC_SUBST([F77],[$FC])
AC_SUBST([FFLAGS],[$FCFLAGS])
AC_SUBST([AM_FFLAGS],[$AM_FCFLAGS])
AC_SUBST([FLIBS],[$FCLIBS])
])
dnl ##### VBFNLO #####
AC_DEFUN([HERWIG_CHECK_VBFNLO],
[
AC_MSG_CHECKING([for VBFNLO])
AC_ARG_WITH([vbfnlo],
AS_HELP_STRING([--with-vbfnlo=DIR], [Installation path of VBFNLO]),
[],
[with_vbfnlo=no]
)
AC_MSG_RESULT([$with_vbfnlo])
AS_IF([test "x$with_vbfnlo" != "xno"],
[AC_CHECK_FILES(
${with_vbfnlo}/lib/VBFNLO/libVBFNLO.so,
[have_vbfnlo=lib], [have_vbfnlo=no])],
[have_vbfnlo=no])
AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ],
[AC_CHECK_FILES(
${with_vbfnlo}/lib64/VBFNLO/libVBFNLO.so,
[have_vbfnlo=lib64], [have_vbfnlo=no])])
AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ],
[AC_CHECK_FILES(
${with_vbfnlo}/lib/VBFNLO/libVBFNLO.dylib,
[have_vbfnlo=lib], [have_vbfnlo=no])])
AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno" ],
[AC_CHECK_FILES(
${with_vbfnlo}/lib64/VBFNLO/libVBFNLO.dylib,
[have_vbfnlo=lib64], [have_vbfnlo=no])])
AS_IF([test "x$have_vbfnlo" = "xlib"],
[VBFNLOLIBS=${with_vbfnlo}/lib/VBFNLO
AC_SUBST(VBFNLOLIBS)
])
AS_IF([test "x$have_vbfnlo" = "xlib64"],
[VBFNLOLIBS=${with_vbfnlo}/lib64/VBFNLO
AC_SUBST(VBFNLOLIBS)
])
AS_IF([test "x$with_vbfnlo" != "xno" -a "x$have_vbfnlo" = "xno"],
[AC_MSG_ERROR([vbfnlo requested but not found])])
AM_CONDITIONAL(HAVE_VBFNLO,[test "x$have_vbfnlo" = "xlib" -o "x$have_vbfnlo" = "xlib64"])
if test "x$have_vbfnlo" = "xlib" -o "x$have_vbfnlo" = "xlib64" ; then
+ AC_REQUIRE([AC_PROG_SED])
VBFNLOINCLUDE=${with_vbfnlo}/include
AC_SUBST(VBFNLOINCLUDE)
- VBFNLOLIB=${with_vbfnlo}/${have_vbfnlo}/VBFNLO
+ VBFNLOLIB=$(echo ${with_vbfnlo}/${have_vbfnlo}/VBFNLO | $SED -e 's%/\+%/%g')
AC_SUBST(VBFNLOLIB)
LOAD_VBFNLO="library"
CREATE_VBFNLO="create"
INSERT_VBFNLO="insert"
SET_VBFNLO="set"
DO_VBFNLO="do"
MKDIR_VBFNLO="mkdir"
else
LOAD_VBFNLO="# library"
CREATE_VBFNLO="# create"
INSERT_VBFNLO="# insert"
SET_VBFNLO="# set"
DO_VBFNLO="# do"
MKDIR_VBFNLO="# mkdir"
fi
AC_SUBST([LOAD_VBFNLO])
AC_SUBST([CREATE_VBFNLO])
AC_SUBST([INSERT_VBFNLO])
AC_SUBST([SET_VBFNLO])
AC_SUBST([DO_VBFNLO])
AC_SUBST([MKDIR_VBFNLO])
])
dnl ##### njet #####
AC_DEFUN([HERWIG_CHECK_NJET],
[
AC_MSG_CHECKING([for njet])
AC_ARG_WITH([njet],
AS_HELP_STRING([--with-njet=DIR], [Installation path of njet]),
[],
[with_njet=no]
)
AC_MSG_RESULT([$with_njet])
AS_IF([test "x$with_njet" != "xno"],
[AC_CHECK_FILES(
${with_njet}/lib/libnjet2.so,
[have_njet=lib], [have_njet=no])],
[have_njet=no])
AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ],
[AC_CHECK_FILES(
${with_njet}/lib64/libnjet2.so,
[have_njet=lib64], [have_njet=no])])
AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno" ],
[AC_CHECK_FILES(
${with_njet}/lib/libnjet2.dylib,
[have_njet=lib], [have_njet=no])])
AS_IF([test "x$have_njet" = "xlib"],
[NJETLIBPATH=${with_njet}/lib
AC_SUBST(NJETLIBPATH)
NJETINCLUDEPATH=${with_njet}/include
AC_SUBST(NJETINCLUDEPATH)
NJETPREFIX=${with_njet}
AC_SUBST(NJETPREFIX)
])
AS_IF([test "x$have_njet" = "xlib64"],
[NJETLIBPATH=${with_njet}/lib64
AC_SUBST(NJETLIBPATH)
NJETINCLUDEPATH=${with_njet}/include
AC_SUBST(NJETINCLUDEPATH)
NJETPREFIX=${with_njet}
AC_SUBST(NJETPREFIX)
])
AS_IF([test "x$with_njet" != "xno" -a "x$have_njet" = "xno"],
[AC_MSG_ERROR([njet requested but not found])])
AM_CONDITIONAL(HAVE_NJET,[test "x$have_njet" = "xlib" -o "x$have_njet" = "xlib64"])
if test "x$have_njet" = "xlib" -o "x$have_njet" = "xlib64" ; then
LOAD_NJET="library"
CREATE_NJET="create"
INSERT_NJET="insert"
DO_NJET="do"
else
LOAD_NJET="# library"
CREATE_NJET="# create"
INSERT_NJET="# insert"
DO_NJET="# do"
fi
AC_SUBST([LOAD_NJET])
AC_SUBST([CREATE_NJET])
AC_SUBST([INSERT_NJET])
AC_SUBST([DO_NJET])
])
dnl ##### gosam #####
AC_DEFUN([HERWIG_CHECK_GOSAM],
[
AC_MSG_CHECKING([for gosam])
AC_ARG_WITH([gosam],
AS_HELP_STRING([--with-gosam=DIR], [Installation path of gosam]),
[],
[with_gosam=no]
)
AC_MSG_RESULT([$with_gosam])
AS_IF([test "x$with_gosam" != "xno"],
[AC_CHECK_FILES(
${with_gosam}/bin/gosam.py,
[have_gosam=lib], [have_gosam=no])],
[have_gosam=no])
AS_IF([test "x$have_gosam" = "xlib"],
[GOSAMPREFIX=${with_gosam}
AC_SUBST(GOSAMPREFIX)
])
AS_IF([test "x$with_gosam" != "xno" -a "x$have_gosam" = "xno"],
[AC_MSG_ERROR([GoSam requested but not found])])
AM_CONDITIONAL(HAVE_GOSAM,[test "x$have_gosam" = "xlib" ])
if test "x$have_gosam" = "xlib" ; then
LOAD_GOSAM="library"
CREATE_GOSAM="create"
INSERT_GOSAM="insert"
DO_GOSAM="do"
else
LOAD_GOSAM="# library"
CREATE_GOSAM="# create"
INSERT_GOSAM="# insert"
DO_GOSAM="# do"
fi
AC_SUBST([LOAD_GOSAM])
AC_SUBST([CREATE_GOSAM])
AC_SUBST([INSERT_GOSAM])
AC_SUBST([DO_GOSAM])
])
dnl ##### gosam-contrib #####
AC_DEFUN([HERWIG_CHECK_GOSAM_CONTRIB],
[
AC_MSG_CHECKING([for gosam-contrib])
AC_ARG_WITH([gosam-contrib],
AS_HELP_STRING([--with-gosam-contrib=DIR], [Installation path of gosam-contrib]),
[],
[with_gosam_contrib=no]
)
AC_MSG_RESULT([$with_gosam_contrib])
AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"],
[AC_CHECK_FILES(
${with_gosam}/lib/libsamurai.so,
[with_gosam_contrib=${with_gosam}], [])
])
AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"],
[AC_CHECK_FILES(
${with_gosam}/lib64/libsamurai.so,
[with_gosam_contrib=${with_gosam}], [])
])
AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"],
[AC_CHECK_FILES(
${with_gosam}/lib/libsamurai.dylib,
[with_gosam_contrib=${with_gosam}], [])
])
AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"],
[AC_CHECK_FILES(
${with_gosam}/lib64/libsamurai.dylib,
[with_gosam_contrib=${with_gosam}], [])
])
AS_IF([test "x$with_gosam_contrib" = "xno" -a "x$with_gosam" != "xno"],
[AC_MSG_ERROR([GoSam requested without requesting GoSam-Contrib])])
AS_IF([test "x$with_gosam_contrib" != "xno"],
[AC_CHECK_FILES(
${with_gosam_contrib}/lib/libsamurai.so,
[have_gosam_contrib=lib], [have_gosam_contrib=no])],
[have_gosam_contrib=no])
AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ],
[AC_CHECK_FILES(
${with_gosam_contrib}/lib64/libsamurai.so,
[have_gosam_contrib=lib64], [have_gosam_contrib=no])])
AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ],
[AC_CHECK_FILES(
${with_gosam_contrib}/lib/libsamurai.dylib,
[have_gosam_contrib=lib], [have_gosam_contrib=no])])
AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno" ],
[AC_CHECK_FILES(
${with_gosam_contrib}/lib64/libsamurai.dylib,
[have_gosam_contrib=lib64], [have_gosam_contrib=no])])
AS_IF([test "x$have_gosam_contrib" != "xno"],
[GOSAMCONTRIBPREFIX=${with_gosam_contrib}
AC_SUBST(GOSAMCONTRIBPREFIX)
])
AS_IF([test "x$have_gosam_contrib" = "xlib"],
[GOSAMCONTRIBLIBS=${with_gosam_contrib}/lib
AC_SUBST(GOSAMCONTRIBLIBS)
])
AS_IF([test "x$have_gosam_contrib" = "xlib64"],
[GOSAMCONTRIBLIBS=${with_gosam_contrib}/lib64
AC_SUBST(GOSAMCONTRIBLIBS)
])
AS_IF([test "x$with_gosam_contrib" != "xno" -a "x$have_gosam_contrib" = "xno"],
[AC_MSG_ERROR([GoSam-Contrib requested but not found])])
AM_CONDITIONAL(HAVE_GOSAM_CONTRIB,[test "x$have_gosam_contrib" = "xlib" -o "x$have_gosam_contrib" = "xlib64"])
if test "x$have_gosam_contrib" = "xlib" -o "x$have_gosam_contrib" = "xlib64" ; then
LOAD_GOSAM_CONTRIB="library"
CREATE_GOSAM_CONTRIB="create"
INSERT_GOSAM_CONTRIB="insert"
else
LOAD_GOSAM_CONTRIB="# library"
CREATE_GOSAM_CONTRIB="# create"
INSERT_GOSAM_CONTRIB="# insert"
fi
AC_SUBST([LOAD_GOSAM_CONTRIB])
AC_SUBST([CREATE_GOSAM_CONTRIB])
AC_SUBST([INSERT_GOSAM_CONTRIB])
])
dnl ##### OpenLoops #####
AC_DEFUN([HERWIG_CHECK_OPENLOOPS],
[
AC_MSG_CHECKING([for OpenLoops])
AC_ARG_WITH([openloops],
AS_HELP_STRING([--with-openloops=DIR], [Installation path of OpenLoops]),
[],
[with_openloops=no]
)
AC_MSG_RESULT([$with_openloops])
AS_IF([test "x$with_openloops" != "xno"],
[AC_CHECK_FILES(
${with_openloops}/lib/libopenloops.so,
[have_openloops=lib], [have_openloops=no])],
[have_openloops=no])
AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ],
[AC_CHECK_FILES(
${with_openloops}/lib/libopenloops.dylib,
[have_openloops=lib], [have_openloops=no])])
AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ],
[AC_CHECK_FILES(
${with_openloops}/lib64/libopenloops.so,
[have_openloops=lib64], [have_openloops=no])])
AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno" ],
[AC_CHECK_FILES(
${with_openloops}/lib64/libopenloops.dylib,
[have_openloops=lib64], [have_openloops=no])])
AS_IF([test "x$have_openloops" = "xlib"],
[OPENLOOPSLIBS=${with_openloops}/lib
AC_SUBST(OPENLOOPSLIBS)
])
AS_IF([test "x$have_openloops" = "xlib64"],
[OPENLOOPSLIBS=${with_openloops}/lib64
AC_SUBST(OPENLOOPSLIBS)
])
AS_IF([test "x$with_openloops" != "xno" -a "x$have_openloops" = "xno"],
[AC_MSG_ERROR([OpenLoops requested but not found])])
AM_CONDITIONAL(HAVE_OPENLOOPS,[test "x$have_openloops" = "xlib" -o "x$have_openloops" = "xlib64"])
if test "x$have_openloops" = "xlib" -o "x$have_openloops" = "xlib64" ; then
OPENLOOPSPREFIX=${with_openloops}
LOAD_OPENLOOPS="library"
CREATE_OPENLOOPS="create"
INSERT_OPENLOOPS="insert"
SET_OPENLOOPS="set"
DO_OPENLOOPS="do"
MKDIR_OPENLOOPS="mkdir"
else
LOAD_OPENLOOPS="# library"
CREATE_OPENLOOPS="# create"
INSERT_OPENLOOPS="# insert"
SET_OPENLOOPS="# set"
DO_OPENLOOPS="# do"
MKDIR_OPENLOOPS="# mkdir"
fi
AC_SUBST([OPENLOOPSPREFIX])
AC_SUBST([LOAD_OPENLOOPS])
AC_SUBST([CREATE_OPENLOOPS])
AC_SUBST([INSERT_OPENLOOPS])
AC_SUBST([SET_OPENLOOPS])
AC_SUBST([DO_OPENLOOPS])
AC_SUBST([MKDIR_OPENLOOPS])
])
#########################################
dnl ##### madgraph #####
AC_DEFUN([HERWIG_CHECK_MADGRAPH],
[
AC_MSG_CHECKING([for MadGraph])
AC_ARG_WITH([madgraph],
AS_HELP_STRING([--with-madgraph=DIR], [Installation path of MadGraph]),
[],
[with_madgraph=no]
)
AC_MSG_RESULT([$with_madgraph])
AS_IF([test "x$with_madgraph" != "xno"],
[AC_CHECK_FILES(
${with_madgraph}/bin/mg5_aMC,
[have_madgraph=yes], [have_madgraph=no])],
[have_madgraph=no])
AS_IF([test "x$have_madgraph" = "xyes"],
[MADGRAPHPREFIX=${with_madgraph}
AC_SUBST(MADGRAPHPREFIX)
])
AS_IF([test "x$with_madgraph" != "xno" -a "x$have_madgraph" = "xno"],
[AC_MSG_ERROR([MadGraph requested but not found])])
AM_CONDITIONAL(HAVE_MADGRAPH,[test "x$have_madgraph" = "xyes" ])
if test "x$have_madgraph" = "xyes" ; then
LOAD_MADGRAPH="library"
CREATE_MADGRAPH="create"
INSERT_MADGRAPH="insert"
SET_MADGRAPH="set"
DO_MADGRAPH="do"
else
LOAD_MADGRAPH="# library"
CREATE_MADGRAPH="# create"
INSERT_MADGRAPH="# insert"
SET_MADGRAPH="# set"
DO_MADGRAPH="# do"
fi
AC_SUBST([LOAD_MADGRAPH])
AC_SUBST([CREATE_MADGRAPH])
AC_SUBST([INSERT_MADGRAPH])
AC_SUBST([SET_MADGRAPH])
AC_SUBST([DO_MADGRAPH])
])
dnl ##### EvtGen #####
AC_DEFUN([HERWIG_CHECK_EVTGEN],
[
AC_MSG_CHECKING([for evtgen])
AC_ARG_WITH([evtgen],
AS_HELP_STRING([--with-evtgen=DIR], [Installation path of EvtGen]),
[],
[with_evtgen=no]
)
AC_MSG_RESULT([$with_evtgen])
AS_IF([test "x$with_evtgen" != "xno"],
[AC_CHECK_FILES(
${with_evtgen}/lib/libEvtGenExternal.so,
[have_evtgen=lib], [have_evtgen=no])],
[have_evtgen=no])
AS_IF([test "x$have_evtgen" = "xlib"],
[EVTGENPREFIX=${with_evtgen}
AC_SUBST(EVTGENPREFIX)
])
AS_IF([test "x$with_evtgen" != "xno" -a "x$have_evtgen" = "xno"],
[AC_MSG_ERROR([EvtGen requested but not found])])
AM_CONDITIONAL(HAVE_EVTGEN,[test "x$have_evtgen" = "xlib" ])
if test "x$have_evtgen" = "xlib" ; then
LOAD_EVTGEN_DECAYS="read EvtGenBDecays.in"
LOAD_EVTGEN_DECAYER="read EvtGenDecayer.in"
EVTGENLIBS="-L$with_evtgen/lib -lEvtGen -lEvtGenExternal"
else
LOAD_EVTGEN_DECAYS="read HerwigBDecays.in"
LOAD_EVTGEN_DECAYER="#read EvtGenDecayer.in"
EVTGENLIBS=""
fi
AC_SUBST([LOAD_EVTGEN_DECAYS])
AC_SUBST([LOAD_EVTGEN_DECAYER])
AC_SUBST([EVTGENLIBS])
])
AC_DEFUN([HERWIG_CHECK_PYTHIA],
[
dnl check if a directory is specified for Pythia
AC_ARG_WITH(pythia,
[AC_HELP_STRING([--with-pythia=dir],
[Assume the given directory for Pythia])])
dnl search for the pythia-config script
if test "$with_pythia" = ""; then
AC_PATH_PROG(pythiaconfig, pythia8-config, no)
else
AC_PATH_PROG(pythiaconfig, pythia8-config, no, ${with_pythia}/bin)
fi
if test "${pythiaconfig}" = "no"; then
AC_MSG_CHECKING(Pythia)
AC_MSG_RESULT(no);
# $2
else
PYTHIA8DATA=`${pythiaconfig} --datadir`/xmldoc
fi
AC_SUBST(PYTHIA8DATA)
])
dnl CHECK PYTHIA END
dnl ##### PDF PATH #####
AC_DEFUN([HERWIG_PDF_PATH],
[
AC_MSG_CHECKING([which Herwig++ PDF data to use])
AC_ARG_WITH(pdf,
AC_HELP_STRING([--with-pdf=DIR],[installation path of Herwig++PDF data tarball]),
[],
[with_pdf=${prefix}]
)
HERWIG_PDF_PREFIX=${with_pdf}/share/Herwig++PDF
if test -f "${HERWIG_PDF_PREFIX}/mrst/2008/mrstMCal.dat"; then
AC_MSG_RESULT([$with_pdf])
localPDFneeded=false
else
AC_MSG_RESULT([Using built-in PDF data set. For other data sets, set --with-pdf.])
HERWIG_PDF_PREFIX=PDF
localPDFneeded=true
fi
HERWIG_PDF_DEFAULT=${HERWIG_PDF_PREFIX}/mrst/2008/mrstMCal.dat
HERWIG_PDF_NLO=${HERWIG_PDF_PREFIX}/mrst/2002/mrst2002nlo.dat
HERWIG_PDF_POMERON=${HERWIG_PDF_PREFIX}/diffraction/
AM_CONDITIONAL(WANT_LOCAL_PDF,[test "x$localPDFneeded" = "xtrue"])
AC_SUBST(HERWIG_PDF_DEFAULT)
AC_SUBST(HERWIG_PDF_NLO)
AC_SUBST(HERWIG_PDF_POMERON)
])
dnl ###### GSL ######
AC_DEFUN([HERWIG_CHECK_GSL],
[
AC_MSG_CHECKING([for gsl location])
GSLINCLUDE=""
GSLLIBS=""
AC_ARG_WITH(gsl,
AC_HELP_STRING([--with-gsl=DIR],[location of gsl installation @<:@default=system libs@:>@]),
[],
[with_gsl=system])
if test "x$with_gsl" = "xno"; then
AC_MSG_ERROR([libgsl is required. Please install the GNU scientific library and header files.])
fi
if test "x$with_gsl" = "xsystem"; then
AC_MSG_RESULT([in system libraries])
oldlibs="$LIBS"
AC_CHECK_LIB(m,main)
AC_CHECK_LIB(gslcblas,main)
AC_CHECK_LIB(gsl,main,[],
[
AC_MSG_ERROR([Cannot find libgsl. Please install the GNU scientific library and header files or use --with-gsl=.])
]
)
GSLLIBS="$LIBS"
GSLPATH="$with_gsl"
LIBS=$oldlibs
else
if test "`uname -m`" = "x86_64" -a -e "$with_gsl/lib64/libgsl.a" -a -d "$with_gsl/include/gsl"; then
AC_MSG_RESULT([found in $with_gsl])
GSLLIBS="-L$with_gsl/lib64 -R$with_gsl/lib64 -lgslcblas -lgsl"
GSLINCLUDE="-I$with_gsl/include"
GSLPATH="$with_gsl"
elif test -e "$with_gsl/lib/libgsl.a" -a -d "$with_gsl/include/gsl"; then
AC_MSG_RESULT([found in $with_gsl])
GSLLIBS="-L$with_gsl/lib -R$with_gsl/lib -lgslcblas -lgsl"
GSLINCLUDE="-I$with_gsl/include"
GSLPATH="$with_gsl"
else
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Can't find $with_gsl/lib/libgsl.a or the headers in $with_gsl/include])
fi
fi
AC_SUBST(GSLINCLUDE)
AC_SUBST(GSLLIBS)
AC_SUBST(GSLPATH)
])
dnl ##### COMPILERFLAGS #####
AC_DEFUN([HERWIG_COMPILERFLAGS],
[
AC_REQUIRE([HERWIG_CHECK_GSL])
AC_REQUIRE([HERWIG_CHECK_THEPEG])
AC_REQUIRE([BOOST_REQUIRE])
AC_REQUIRE([AX_COMPILER_VENDOR])
AM_CPPFLAGS="-I\$(top_builddir)/include $THEPEGINCLUDE \$(GSLINCLUDE) \$(BOOST_CPPFLAGS)"
AC_MSG_CHECKING([for debugging mode])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--enable-debug],[debug mode, use --enable-debug=slow for additional options that slow down the run.]),
[],
[enable_debug=no]
)
AC_MSG_RESULT([$enable_debug])
if test "x$enable_debug" = "xno"; then
debugflags=""
else
debugflags="-g"
fi
dnl -Wfloat-equal -fvisibility-inlines-hidden -Wctor-dtor-privacy -Weffc++
if test -n "$GCC"; then
warnflags="-pedantic -Wall -Wextra -Wno-overloaded-virtual"
if test "x$enable_debug" = "xslow"; then
debugflags="$debugflags -fno-inline"
AM_CPPFLAGS="$AM_CPPFLAGS -D_GLIBCXX_DEBUG"
fi
fi
dnl do an actual capability check on ld instead of this workaround
case "${host}" in
*-darwin*)
;;
*)
AM_LDFLAGS="-Wl,--enable-new-dtags"
;;
esac
case "${ax_cv_cxx_compiler_vendor}" in
gnu)
AM_CXXFLAGS="-pedantic -Wall -W"
;;
clang)
AM_CXXFLAGS="-pedantic -Wall -Wno-overloaded-virtual -Wno-unused-function"
dnl -Wno-unneeded-internal-declaration
;;
intel)
AM_CXXFLAGS="-strict-ansi -Wall -wd13000,1418,981,444,383,1599,1572,2259,980"
;;
esac
AC_SUBST(AM_CPPFLAGS)
AC_SUBST(AM_CFLAGS, ["$warnflags $debugflags"])
AC_SUBST(AM_CXXFLAGS,["$AM_CXXFLAGS $warnflags $debugflags"])
AC_SUBST(AM_FCFLAGS, ["$debugflags"])
AC_SUBST(AM_LDFLAGS)
])
AC_DEFUN([HERWIG_ENABLE_MODELS],
[
AC_MSG_CHECKING([if BSM models should be built])
AC_ARG_ENABLE(models,
AC_HELP_STRING([--disable-models],[Turn off compilation of BSM models.]),
[],
[enable_models=yes]
)
AC_MSG_RESULT([$enable_models])
LOAD_BSM=""
if test "$enable_models" = "yes"; then
LOAD_BSM="read BSMlibs.in"
fi
AC_SUBST(LOAD_BSM)
AM_CONDITIONAL(WANT_BSM,[test "$enable_models" = "yes"])
])
AC_DEFUN([HERWIG_OVERVIEW],
[
FCSTRING=`$FC --version | head -1`
CXXSTRING=`$CXX --version | head -1`
CCSTRING=`$CC --version | head -1`
if test "x$PYTHON" != "x:"
then
python_was_found="yes, using Python $PYTHON_VERSION"
else
python_was_found="no, requires Python >= 2.6"
fi
cat << _HW_EOF_ > config.herwig
*****************************************************
*** $PACKAGE_STRING configuration summary
*** Please include this information in bug reports!
***--------------------------------------------------
*** Prefix: $prefix
***
*** BSM models: $enable_models
*** UFO converter: ${python_was_found}
***
*** Herwig debug mode: $enable_debug
***
*** ThePEG: $with_thepeg
*** ThePEG headers: $with_thepeg_headers
***
*** GoSam: $with_gosam
*** GoSam-Contrib: $with_gosam_contrib
*** MadGraph: $with_madgraph
*** njet: $with_njet
*** OpenLoops: $with_openloops
*** VBFNLO: $with_vbfnlo
***
*** EvtGen: $with_evtgen
*** GSL: $with_gsl
*** boost: ${BOOST_CPPFLAGS:-system}
*** Fastjet: ${fjconfig}
***
*** Host: $host
*** CC: $CCSTRING
*** CXX: $CXXSTRING
*** FC: $FCSTRING
***
*** CXXFLAGS: $CXXFLAGS
*****************************************************
_HW_EOF_
])
diff --git a/src/HerwigCLI.cc b/src/HerwigCLI.cc
--- a/src/HerwigCLI.cc
+++ b/src/HerwigCLI.cc
@@ -1,165 +1,165 @@
// -*- C++ -*-
//
-// Herwig.h is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2015 The Herwig Collaboration
+// HerwigCLI.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2016 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#include "HerwigCLI.h"
#include "herwigopts.h"
#include <ThePEG/Utilities/DynamicLoader.h>
#include <ThePEG/Utilities/Debug.h>
#include <ThePEG/Repository/Repository.h>
#include <ThePEG/Handlers/SamplerBase.h>
namespace Herwig {
void HerwigCLI::quitWithHelp() const {
std::cerr << gengetopt_args_info_usage << '\n';
quit();
}
void HerwigCLI::quit() const {
ThePEG::Repository::cleanup();
exit( EXIT_FAILURE );
}
HerwigCLI::~HerwigCLI() {
ThePEG::Repository::cleanup();
}
HerwigCLI::HerwigCLI(int argc, char * argv[])
: runMode_(RunMode::ERROR),
resume_(false), tics_(true), tag_(),
inputfile_(), repository_(), setupfile_(),
integrationList_(),
N_(-1), seed_(0), jobs_(1),
jobsize_(0), maxjobs_(0)
{
gengetopt_args_info args_info;
if ( cmdline_parser( argc, argv, &args_info ) != 0 ) {
std::cerr << "Could not parse command line.\n";
return;
}
if ( args_info.version_given ) {
std::cout <<
#include "hgstamp.inc"
"" << '\n';
std::cout << ThePEG::Repository::version() << std::endl;
cmdline_parser_free( &args_info );
exit( EXIT_SUCCESS );
}
// require one command
if ( args_info.inputs_num < 1 )
quitWithHelp();
// Define runMode of program
std::string tmpRunMode = args_info.inputs[0];
if ( tmpRunMode == "init" ) { runMode_ = RunMode::INIT; }
else if ( tmpRunMode == "read" ) { runMode_ = RunMode::READ; }
else if ( tmpRunMode == "build" ) { runMode_ = RunMode::BUILD; }
else if ( tmpRunMode == "integrate" ) { runMode_ = RunMode::INTEGRATE; }
else if ( tmpRunMode == "mergegrids" ) { runMode_ = RunMode::MERGEGRIDS; }
else if ( tmpRunMode == "run" ) { runMode_ = RunMode::RUN; }
else {
runMode_ = RunMode::ERROR;
quitWithHelp();
}
// Use second argument as input- or runfile name
if ( args_info.inputs_num > 1 )
inputfile_ = args_info.inputs[1];
// Defaults for these filenames are set in the ggo file
repository_ = args_info.repo_arg;
// Number of events
if ( args_info.numevents_given )
N_ = args_info.numevents_arg;
// RNG seed
if ( args_info.seed_given ) {
seed_ = args_info.seed_arg;
}
// run name tag (default given in ggo file)
tag_ = args_info.tag_arg;
// run modification file
if ( args_info.setupfile_given )
setupfile_ = args_info.setupfile_arg;
// parallel jobs
if ( args_info.jobs_given )
jobs_ = args_info.jobs_arg;
// Directories from which Herwig reads filesystemfor ( size_t i = 0; i < args_info.append_read_given; ++i )
for ( size_t i = 0; i < args_info.append_read_given; ++i )
appendReadDirectories_.push_back( args_info.append_read_arg[i] );
for ( size_t i = 0; i < args_info.prepend_read_given; ++i )
prependReadDirectories_.push_back( args_info.prepend_read_arg[i] );
// Library search path for dlopen()
for ( size_t i = 0; i < args_info.append_given; ++i )
ThePEG::DynamicLoader::appendPath( args_info.append_arg[i] );
for ( size_t i = 0; i < args_info.prepend_given; ++i )
ThePEG::DynamicLoader::prependPath( args_info.prepend_arg[i] );
// Debugging level
if ( args_info.debug_given )
ThePEG::Debug::setDebug( args_info.debug_arg );
// Floating point exceptions
if ( args_info.debug_fpe_flag )
ThePEG::Debug::unmaskFpuErrors();
// Exit-on-error flag
if ( ! args_info.noexitonerror_flag )
ThePEG::Repository::exitOnError() = 1;
// Tics
if ( args_info.quiet_flag )
tics_ = false;
// integration list
if ( args_info.jobid_given ) {
integrationList_ = "integrationJob" + std::string(args_info.jobid_arg);
}
// job size
if ( args_info.jobsize_given ) {
if ( runMode_ != RunMode::BUILD ) {
std::cerr << "--jobsize option is only available in 'build' mode.\n";
quitWithHelp();
}
jobsize_ = args_info.jobsize_arg;
ThePEG::SamplerBase::setIntegratePerJob(jobsize_);
}
// max integration jobs
if ( args_info.maxjobs_given ) {
if ( runMode_ != RunMode::BUILD ) {
std::cerr << "--maxjobs option is only available in 'build' mode.\n";
quitWithHelp();
}
maxjobs_ = args_info.maxjobs_arg;
ThePEG::SamplerBase::setIntegrationJobs(maxjobs_);
}
// Resume
if ( args_info.resume_flag )
resume_ = true;
cmdline_parser_free( &args_info );
}
}
diff --git a/src/HerwigCLI.h b/src/HerwigCLI.h
--- a/src/HerwigCLI.h
+++ b/src/HerwigCLI.h
@@ -1,98 +1,108 @@
// -*- C++ -*-
//
-// Herwig.h is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2015 The Herwig Collaboration
+// HerwigCLI.h is a part of Herwig - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2016 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef SRC_HERWIG_CLI_H
#define SRC_HERWIG_CLI_H
-#include "HerwigUI.h"
+#include "Herwig/API/HerwigUI.h"
+#include <iostream>
namespace Herwig {
/**
* HerwigCLI is the default implementation of the HerwigUI interface.
*
* Using the gengetopt tool, we fill all required pieces from reading
* command line flags from the main executable.
*/
class HerwigCLI : public HerwigUI {
public:
/// Constructor from the arguments provided by main()
HerwigCLI(int argc, char * argv[]);
/// Destructor to leave a clean ThePEG::Repository behind
~HerwigCLI();
/// Requested Herwig run mode
RunMode::Mode runMode() const { return runMode_; }
/// Try to resume execution from an earlier interrupted run.
bool resume() const { return resume_; }
/// Require verbose progress markers
bool tics() const { return tics_; }
/// A user-defined tag to append to the run name.
std::string tag() const { return tag_; }
/// Name of the file to be read
std::string inputfile() const { return inputfile_; }
/// Repository name to operate on
std::string repository() const { return repository_; }
/// Name of the setup file to be read, to modify the repository
std::string setupfile() const { return setupfile_; }
std::string integrationList() const { return integrationList_; }
const std::vector<std::string> &
prependReadDirectories() const { return prependReadDirectories_; }
const std::vector<std::string> &
appendReadDirectories() const { return appendReadDirectories_; }
long N() const { return N_; }
int seed() const { return seed_; }
int jobs() const { return jobs_; }
unsigned int jobSize() const { return jobsize_; }
unsigned int maxJobs() const { return maxjobs_; }
void quitWithHelp() const;
void quit() const;
+ /// Return the standard out stream to be used
+ virtual std::ostream& outStream() const { return std::cout; }
+
+ /// Return the standard err stream to be used
+ virtual std::ostream& errStream() const { return std::cerr; }
+
+ /// Return the standard in stream to be used
+ virtual std::istream& inStream() const { return std::cin; }
+
private:
RunMode::Mode runMode_;
bool resume_;
bool tics_;
std::string tag_;
std::string inputfile_;
std::string repository_;
std::string setupfile_;
std::string integrationList_;
std::vector<std::string> prependReadDirectories_;
std::vector<std::string> appendReadDirectories_;
long N_;
int seed_;
int jobs_;
unsigned int jobsize_;
unsigned int maxjobs_;
};
}
#endif
diff --git a/src/HerwigMain.cc b/src/HerwigMain.cc
--- a/src/HerwigMain.cc
+++ b/src/HerwigMain.cc
@@ -1,61 +1,61 @@
// -*- C++ -*-
//
-// Herwig.h is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2015 The Herwig Collaboration
+// HerwigMain.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2016 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#include "HerwigCLI.h"
-#include "Herwig.h"
+#include <Herwig/API/HerwigAPI.h>
#include <iostream>
#include <cstdlib>
#include <ThePEG/Utilities/Exception.h>
int main(int argc, char * argv[]) {
try {
// read in command line options
const Herwig::HerwigCLI cl = Herwig::HerwigCLI(argc, argv);
// Call program switches according to runMode
switch ( cl.runMode() ) {
case Herwig::RunMode::INIT: Herwig::API::init(cl); break;
case Herwig::RunMode::READ: Herwig::API::read(cl); break;
case Herwig::RunMode::BUILD: Herwig::API::build(cl); break;
case Herwig::RunMode::INTEGRATE: Herwig::API::integrate(cl); break;
case Herwig::RunMode::MERGEGRIDS: Herwig::API::mergegrids(cl); break;
case Herwig::RunMode::RUN: Herwig::API::run(cl); break;
case Herwig::RunMode::ERROR:
std::cerr << "Error during read in of command line parameters.\n"
<< "Program execution will stop now.";
return EXIT_FAILURE;
default:
cl.quitWithHelp();
}
return EXIT_SUCCESS;
}
catch ( ThePEG::Exception & e ) {
std::cerr << argv[0] << ": ThePEG::Exception caught.\n"
<< e.what() << '\n'
<< "See logfile for details.\n";
return EXIT_FAILURE;
}
catch ( std::exception & e ) {
std::cerr << argv[0] << ": " << e.what() << '\n';
return EXIT_FAILURE;
}
catch ( const char* what ) {
std::cerr << argv[0] << ": caught exception: "
<< what << "\n";
return EXIT_FAILURE;
}
catch ( ... ) {
std::cerr << argv[0] << ": Unknown exception caught.\n";
return EXIT_FAILURE;
}
}
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,239 +1,239 @@
SUBDIRS = defaults snippets Matchbox Merging
AUTOMAKE_OPTIONS = -Wno-portability
defaultsdir = ${pkgdatadir}/defaults
bin_PROGRAMS = Herwig
Herwig_SOURCES = \
-HerwigMain.cc Herwig.h Herwig.cc HerwigCLI.cc HerwigCLI.h HerwigUI.h \
+HerwigMain.cc HerwigCLI.cc HerwigCLI.h \
herwigopts.c herwigopts.h
BUILT_SOURCES = herwigopts.c herwigopts.h
Herwig_LDFLAGS = $(AM_LDFLAGS) -export-dynamic $(THEPEGLDFLAGS) \
$(BOOST_SYSTEM_LDFLAGS) $(BOOST_FILESYSTEM_LDFLAGS)
Herwig_LDADD = $(THEPEGLIB) -ldl \
-$(top_builddir)/Utilities/libHwRunDirectories.la \
+$(top_builddir)/API/libHerwigAPI.la \
$(BOOST_SYSTEM_LIBS) $(BOOST_FILESYSTEM_LIBS)
Herwig_CPPFLAGS = $(AM_CPPFLAGS) \
-DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \
-DHERWIG_PKGLIBDIR="\"$(pkglibdir)\"" \
-DTHEPEG_PKGLIBDIR="\"$(THEPEGLIBPATH)\""
bin_SCRIPTS = herwig-config
HELPERFILES = CMSSM40.1.1.slha RPV3.1.slha NMSSM.spc \
ADD.model \
Leptoquark.model \
LH.model \
LHTP.model \
MSSM.model \
MUED.model \
NMSSM.model \
RPV-Bi.model \
RPV-Tri.model \
RS.model \
Sextet.model \
TTBA.model \
Zprime.model \
RPV-BI.slha \
RPV-TRI.slha \
RPV-UDD.slha
INPUTFILES = \
DIS.in \
DIS-Matchbox.in \
GammaGamma.in \
ILC.in \
ILC-MSSM.in \
ILC-MUED.in \
ILC-RS.in \
LEP.in \
LEP-Matchbox.in \
LEP-Merging.in \
LHC-ADD.in \
LHC-diffractive.in \
LHC-GammaGamma.in \
LHC.in \
LHC-Matchbox.in \
LHC-Merging.in \
LHC-LQ.in \
LHC-MSSM.in \
LHC-MUED.in \
LHC-NMSSM.in \
LHC-Powheg.in \
LHC-RPV.in \
LHC-RS.in \
LHC-Sextet.in \
LHC-TRP.in \
LHC-TTBA.in \
LHC-MB.in \
LHC-ZP.in \
TVT.in \
TVT-Powheg.in \
TVT-TTBA.in \
LHC-LH.in \
LHC-LHTP.in
dist_pkgdata_DATA = $(INPUTFILES) $(HELPERFILES)
pkgdata_DATA = Makefile-UserModules
CLEANFILES = HerwigDefaults.rpo \
*.run *.log *.out *.tex \
multi.test *.output probs.test chisq.value \
LHC-RS-BR.spc LHC-MSSM-BR.spc LHC-RPV-BR.spc
clean-local:
-rm -rf Herwig
## checking targets ##
HerwigDefaults.rpo: Herwig $(srcdir)/defaults/*.in defaults/PDF.in defaults/Analysis.in $(top_builddir)/lib/*.so
./Herwig init -L$(top_builddir)/lib defaults/HerwigDefaults.in -D
check_BSM_Full=
check_BSM=
if WANT_BSM
check_BSM += check-LHC-RPV check-LHC-RS
check_BSM_Full += \
check-LHC-RPV check-LHC-MSSM check-ILC-MSSM \
check-LHC-NMSSM \
check-LHC-MUED check-ILC-MUED \
check-LHC-RS check-ILC-RS check-LHC-ADD \
check-LHC-LH check-LHC-LHTP \
check-LHC-TRP \
check-LHC-TTBA check-TVT-TTBA \
check-LHC-ZP \
check-LHC-LQ \
check-LHC-Sextet
endif
check_BSM_Full_valgrind = $(subst check,check-valgrind,$(check_BSM_Full))
check_BSM_valgrind = $(subst check,check-valgrind,$(check_BSM))
check-local: check-LEP check-LHC $(check_BSM) check-DIS check-ILC check-GammaGamma check-LHC-Powheg
check-valgrind-local: check-valgrind-LEP check-valgrind-LHC $(check_BSM_valgrind) check-valgrind-DIS check-valgrind-ILC check-valgrind-GammaGamma check-valgrind-LHC-Powheg
check-Powheg: check-LHC-Powheg check-TVT-Powheg
check-valgrind-Powheg: check-valgrind-LHC-Powheg check-valgrind-TVT-Powheg
check-BSM: $(check_BSM_Full)
check-valgrind-BSM: $(check_BSM_Full_valgrind)
check_Matchbox= \
check-LEP-Matchbox check-DIS-Matchbox check-LHC-Matchbox
check_Matchbox_valgrind = $(subst check,check-valgrind,$(check_Matchbox))
check-Matchbox: $(check_Matchbox)
check-valgrind-Matchbox: $(check_Matchbox_valgrind)
check-extra: check-LHC-diffractive check-LHC-GammaGamma check-LHC-MB check-TVT
check-valgrind-extra: check-valgrind-LHC-diffractive check-valgrind-LHC-GammaGamma check-valgrind-LHC-MB check-valgrind-TVT
check-all: check-local check-Powheg check-BSM check-Matchbox check-extra
check-valgrind-all: check-valgrind-local check-valgrind-Powheg check-valgrind-BSM check-valgrind-Matchbox check-valgrind-extra
link-helper-files:
@for i in $(HELPERFILES); do \
if test -f $(srcdir)/$$i -a ! -e $$i; then \
$(LN_S) -f $(srcdir)/$$i; fi; done
## valgrind targets ##
VALGRIND=valgrind --leak-check=full --num-callers=25 --freelist-vol=100000000 --leak-resolution=med --trace-children=yes
check-valgrind-%: $(srcdir)/%.in HerwigDefaults.rpo link-helper-files
$(VALGRIND) ./Herwig read -d1 -D $< &> valgrind-$(notdir $(subst .in,,$<))-read.log
$(VALGRIND) ./Herwig run $(notdir $(subst .in,.run,$<)) -N 500 -d1 -D &> valgrind-$(notdir $(subst .in,,$<))-run.log
valgrind: valgrind-init valgrind-read valgrind-run
valgrind-init:
$(VALGRIND) ./Herwig init -d1 -D -L$(top_builddir)/lib defaults/HerwigDefaults.in \
&> /tmp/valgrind-init.log
valgrind-read:
$(VALGRIND) ./Herwig read -d1 -D LHC.in &> /tmp/valgrind-read.log
valgrind-run:
$(VALGRIND) ./Herwig run -d1 -D -N5 LHC.run &> /tmp/valgrind-run.log
CHECKCOMMAND = ./Herwig run $(notdir $(subst .in,.run,$<)) -N500 -d1 -D
check-%: $(srcdir)/%.in HerwigDefaults.rpo link-helper-files
./Herwig read -i . $< -D
@echo $(CHECKCOMMAND)
@$(CHECKCOMMAND) && echo "# $@ OK #" \
|| (echo "###### $@ BAD ######"; false)
SETUPTHEPEG=$(THEPEGPATH)/bin/setupThePEG
THEPEGREPO=$(THEPEGLIBPATH)/ThePEGDefaults.rpo
install-exec-local:
$(install_sh_SCRIPT) $(srcdir)/Herwig++ $(DESTDIR)$(bindir)/Herwig++
sed -e's!@BINDIR@!$(bindir)!' $(srcdir)/Herwig++ > $(DESTDIR)$(bindir)/Herwig++
uninstall-local:
rm -f $(DESTDIR)$(bindir)/Herwig++
install-data-hook:
@echo Creating repository
@./Herwig init -L$(DESTDIR)$(pkglibdir) -i$(DESTDIR)$(pkgdatadir) -i$(DESTDIR)$(pkgdatadir)/snippets $(DESTDIR)$(defaultsdir)/HerwigDefaults.in --repo=$(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo
@if test -n "$(DESTDIR)"; \
then sed -i.bak -e "s@$(DESTDIR)@@g" $(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo; \
rm -f $(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo.bak; \
fi
uninstall-hook:
rm -f $(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo
register: register-with-thepeg-repo
register-with-thepeg-repo:
@if test -x "$(SETUPTHEPEG)" -a -w "$(THEPEGREPO)"; \
then echo Registering with ThePEG; \
"$(SETUPTHEPEG)" --init \
$(DESTDIR)$(defaultsdir)/HerwigDefaults.in \
-r "$(THEPEGREPO)" -o "$(THEPEGREPO)" \
-i $(DESTDIR)$(pkgdatadir) \
-l$(DESTDIR)$(pkglibdir) ; \
if test -n "$(DESTDIR)"; \
then sed -i -e "s@$(DESTDIR)@@g" "$(THEPEGREPO)" ; fi ; \
fi
unregister : unregister-from-thepeg-repo
unregister-from-thepeg-repo:
@if test -x "$(SETUPTHEPEG)" -a -w "$(THEPEGREPO)"; \
then echo Unregistering with ThePEG; \
"$(SETUPTHEPEG)" --init defaults/HerwigCleanup.in \
-r "$(THEPEGREPO)" -o "$(THEPEGREPO)" \
-l$(DESTDIR)$(pkglibdir) ; \
fi
EXTRA_DIST = herwigopts.ggo Herwig++
nodist_Herwig_SOURCES = hgstamp.inc
BUILT_SOURCES += hgstamp.inc
CLEANFILES += hgstamp.inc
HGVERSION := $(shell hg -R $(top_srcdir) parents --template '"Herwig {node|short} ({branch})"' 2> /dev/null || echo \"$(PACKAGE_STRING)\" || true )
.PHONY: update_hgstamp
hgstamp.inc: update_hgstamp
@[ -f $@ ] || touch $@
@echo '$(HGVERSION)' | cmp -s $@ - || echo '$(HGVERSION)' > $@
GENGETOPT = gengetopt
%opts.h %opts.c : %opts.ggo
$(GENGETOPT) < $<
diff --git a/src/defaults/MatchboxDefaults.in.in b/src/defaults/MatchboxDefaults.in.in
--- a/src/defaults/MatchboxDefaults.in.in
+++ b/src/defaults/MatchboxDefaults.in.in
@@ -1,781 +1,789 @@
# -*- ThePEG-repository -*-
################################################################################
#
# Default setup for Matchbox matrix element generation.
# You do not need to make any change in here; processes of
# interest can be chosen in the standard input files.
#
################################################################################
################################################################################
# Load libraries
################################################################################
library JetCuts.so
library FastJetFinder.so
library HwMatchboxScales.so
library HwMatchboxCuts.so
library HwSampling.so
library HwColorFull.so
library HwMatchboxBuiltin.so
################################################################################
# Integration/sampling
################################################################################
mkdir /Herwig/Samplers
cd /Herwig/Samplers
create Herwig::BinSampler FlatBinSampler
set FlatBinSampler:InitialPoints 1000
set FlatBinSampler:UseAllIterations No
create Herwig::CellGridSampler CellGridSampler
set CellGridSampler:InitialPoints 10000
set CellGridSampler:ExplorationPoints 500
set CellGridSampler:ExplorationSteps 4
set CellGridSampler:Gain 0.3
set CellGridSampler:Epsilon 1.0
set CellGridSampler:MinimumSelection 0.000001
set CellGridSampler:NIterations 1
set CellGridSampler:EnhancementFactor 1
set CellGridSampler:UseAllIterations No
set CellGridSampler:RemapperPoints 50000
set CellGridSampler:RemapperMinSelection 0.00001
set CellGridSampler:RemapChannelDimension Yes
set CellGridSampler:LuminosityMapperBins 20
set CellGridSampler:GeneralMapperBins 0
set CellGridSampler:HalfPoints No
set CellGridSampler:MaxNewMax 30
set CellGridSampler:NonZeroInPresampling Yes
create Herwig::MonacoSampler MonacoSampler
set MonacoSampler:InitialPoints 15000
set MonacoSampler:NIterations 4
set MonacoSampler:EnhancementFactor 1.2
set MonacoSampler:UseAllIterations No
set MonacoSampler:RemapChannelDimension No
set MonacoSampler:LuminosityMapperBins 0
set MonacoSampler:HalfPoints No
set MonacoSampler:MaxNewMax 30
set MonacoSampler:NonZeroInPresampling Yes
create Herwig::GeneralSampler Sampler
set Sampler:UpdateAfter 1000
set Sampler:BinSampler CellGridSampler
set Sampler:AddUpSamplers Off
set Sampler:GlobalMaximumWeight Off
set Sampler:FlatSubprocesses Off
set Sampler:MinSelection 0.000001
set Sampler:AlmostUnweighted Off
set Sampler:RunCombinationData Off
set Sampler:WriteGridsOnFinish No
set Sampler:MaxEnhancement 1.1
################################################################################
# Setup the factory object
################################################################################
mkdir /Herwig/MatrixElements/Matchbox
cd /Herwig/MatrixElements/Matchbox
create Herwig::MatchboxFactory Factory
do Factory:StartParticleGroup p
insert Factory:ParticleGroup 0 /Herwig/Particles/b
insert Factory:ParticleGroup 0 /Herwig/Particles/bbar
insert Factory:ParticleGroup 0 /Herwig/Particles/c
insert Factory:ParticleGroup 0 /Herwig/Particles/cbar
insert Factory:ParticleGroup 0 /Herwig/Particles/s
insert Factory:ParticleGroup 0 /Herwig/Particles/sbar
insert Factory:ParticleGroup 0 /Herwig/Particles/d
insert Factory:ParticleGroup 0 /Herwig/Particles/dbar
insert Factory:ParticleGroup 0 /Herwig/Particles/u
insert Factory:ParticleGroup 0 /Herwig/Particles/ubar
insert Factory:ParticleGroup 0 /Herwig/Particles/g
do Factory:EndParticleGroup
do Factory:StartParticleGroup pbar
insert Factory:ParticleGroup 0 /Herwig/Particles/b
insert Factory:ParticleGroup 0 /Herwig/Particles/bbar
insert Factory:ParticleGroup 0 /Herwig/Particles/c
insert Factory:ParticleGroup 0 /Herwig/Particles/cbar
insert Factory:ParticleGroup 0 /Herwig/Particles/s
insert Factory:ParticleGroup 0 /Herwig/Particles/sbar
insert Factory:ParticleGroup 0 /Herwig/Particles/d
insert Factory:ParticleGroup 0 /Herwig/Particles/dbar
insert Factory:ParticleGroup 0 /Herwig/Particles/u
insert Factory:ParticleGroup 0 /Herwig/Particles/ubar
insert Factory:ParticleGroup 0 /Herwig/Particles/g
do Factory:EndParticleGroup
do Factory:StartParticleGroup j
insert Factory:ParticleGroup 0 /Herwig/Particles/b
insert Factory:ParticleGroup 0 /Herwig/Particles/bbar
insert Factory:ParticleGroup 0 /Herwig/Particles/c
insert Factory:ParticleGroup 0 /Herwig/Particles/cbar
insert Factory:ParticleGroup 0 /Herwig/Particles/s
insert Factory:ParticleGroup 0 /Herwig/Particles/sbar
insert Factory:ParticleGroup 0 /Herwig/Particles/d
insert Factory:ParticleGroup 0 /Herwig/Particles/dbar
insert Factory:ParticleGroup 0 /Herwig/Particles/u
insert Factory:ParticleGroup 0 /Herwig/Particles/ubar
insert Factory:ParticleGroup 0 /Herwig/Particles/g
do Factory:EndParticleGroup
do Factory:StartParticleGroup u
insert Factory:ParticleGroup 0 /Herwig/Particles/u
do Factory:EndParticleGroup
do Factory:StartParticleGroup ubar
insert Factory:ParticleGroup 0 /Herwig/Particles/ubar
do Factory:EndParticleGroup
do Factory:StartParticleGroup d
insert Factory:ParticleGroup 0 /Herwig/Particles/d
do Factory:EndParticleGroup
do Factory:StartParticleGroup dbar
insert Factory:ParticleGroup 0 /Herwig/Particles/dbar
do Factory:EndParticleGroup
do Factory:StartParticleGroup s
insert Factory:ParticleGroup 0 /Herwig/Particles/s
do Factory:EndParticleGroup
do Factory:StartParticleGroup sbar
insert Factory:ParticleGroup 0 /Herwig/Particles/sbar
do Factory:EndParticleGroup
do Factory:StartParticleGroup c
insert Factory:ParticleGroup 0 /Herwig/Particles/c
do Factory:EndParticleGroup
do Factory:StartParticleGroup cbar
insert Factory:ParticleGroup 0 /Herwig/Particles/cbar
do Factory:EndParticleGroup
do Factory:StartParticleGroup b
insert Factory:ParticleGroup 0 /Herwig/Particles/b
do Factory:EndParticleGroup
do Factory:StartParticleGroup bbar
insert Factory:ParticleGroup 0 /Herwig/Particles/bbar
do Factory:EndParticleGroup
do Factory:StartParticleGroup t
insert Factory:ParticleGroup 0 /Herwig/Particles/t
do Factory:EndParticleGroup
do Factory:StartParticleGroup tbar
insert Factory:ParticleGroup 0 /Herwig/Particles/tbar
do Factory:EndParticleGroup
do Factory:StartParticleGroup g
insert Factory:ParticleGroup 0 /Herwig/Particles/g
do Factory:EndParticleGroup
do Factory:StartParticleGroup gamma
insert Factory:ParticleGroup 0 /Herwig/Particles/gamma
do Factory:EndParticleGroup
do Factory:StartParticleGroup h0
insert Factory:ParticleGroup 0 /Herwig/Particles/h0
do Factory:EndParticleGroup
do Factory:StartParticleGroup W+
insert Factory:ParticleGroup 0 /Herwig/Particles/W+
do Factory:EndParticleGroup
do Factory:StartParticleGroup W-
insert Factory:ParticleGroup 0 /Herwig/Particles/W-
do Factory:EndParticleGroup
do Factory:StartParticleGroup Z0
insert Factory:ParticleGroup 0 /Herwig/Particles/Z0
do Factory:EndParticleGroup
do Factory:StartParticleGroup e+
insert Factory:ParticleGroup 0 /Herwig/Particles/e+
do Factory:EndParticleGroup
do Factory:StartParticleGroup e-
insert Factory:ParticleGroup 0 /Herwig/Particles/e-
do Factory:EndParticleGroup
do Factory:StartParticleGroup mu+
insert Factory:ParticleGroup 0 /Herwig/Particles/mu+
do Factory:EndParticleGroup
do Factory:StartParticleGroup mu-
insert Factory:ParticleGroup 0 /Herwig/Particles/mu-
do Factory:EndParticleGroup
do Factory:StartParticleGroup tau+
insert Factory:ParticleGroup 0 /Herwig/Particles/tau+
do Factory:EndParticleGroup
do Factory:StartParticleGroup tau-
insert Factory:ParticleGroup 0 /Herwig/Particles/tau-
do Factory:EndParticleGroup
do Factory:StartParticleGroup nu_e
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_e
do Factory:EndParticleGroup
do Factory:StartParticleGroup nu_mu
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_mu
do Factory:EndParticleGroup
do Factory:StartParticleGroup nu_tau
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_tau
do Factory:EndParticleGroup
do Factory:StartParticleGroup nu_ebar
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_ebar
do Factory:EndParticleGroup
do Factory:StartParticleGroup nu_mubar
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_mubar
do Factory:EndParticleGroup
do Factory:StartParticleGroup nu_taubar
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_taubar
do Factory:EndParticleGroup
do Factory:StartParticleGroup l
insert Factory:ParticleGroup 0 /Herwig/Particles/e+
insert Factory:ParticleGroup 0 /Herwig/Particles/mu+
insert Factory:ParticleGroup 0 /Herwig/Particles/e-
insert Factory:ParticleGroup 0 /Herwig/Particles/mu-
do Factory:EndParticleGroup
do Factory:StartParticleGroup nu
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_e
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_mu
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_ebar
insert Factory:ParticleGroup 0 /Herwig/Particles/nu_mubar
do Factory:EndParticleGroup
do Factory:StartParticleGroup l+
insert Factory:ParticleGroup 0 /Herwig/Particles/e+
insert Factory:ParticleGroup 0 /Herwig/Particles/mu+
do Factory:EndParticleGroup
do Factory:StartParticleGroup l-
insert Factory:ParticleGroup 0 /Herwig/Particles/e-
insert Factory:ParticleGroup 0 /Herwig/Particles/mu-
do Factory:EndParticleGroup
################################################################################
# Default settings for hard process widths
################################################################################
set /Herwig/Particles/mu+:HardProcessWidth 0*GeV
set /Herwig/Particles/mu-:HardProcessWidth 0*GeV
set /Herwig/Particles/tau+:HardProcessWidth 0*GeV
set /Herwig/Particles/tau-:HardProcessWidth 0*GeV
################################################################################
# Setup amplitudes
################################################################################
cd /Herwig/MatrixElements/Matchbox
mkdir Amplitudes
cd Amplitudes
create ColorFull::TraceBasis TraceBasis
create Herwig::MatchboxHybridAmplitude GenericProcesses
@LOAD_MADGRAPH@ HwMatchboxMadGraph.so
@CREATE_MADGRAPH@ Herwig::MadGraphAmplitude MadGraph
@SET_MADGRAPH@ MadGraph:ColourBasis TraceBasis
@LOAD_GOSAM@ HwMatchboxGoSam.so
@CREATE_GOSAM@ Herwig::GoSamAmplitude GoSam
@LOAD_NJET@ HwMatchboxNJet.so
@CREATE_NJET@ Herwig::NJetsAmplitude NJet
@DO_NJET@ NJet:Massless 5
@DO_NJET@ NJet:Massless -5
@LOAD_OPENLOOPS@ HwMatchboxOpenLoops.so
@CREATE_OPENLOOPS@ Herwig::OpenLoopsAmplitude OpenLoops
@LOAD_VBFNLO@ HwMatchboxVBFNLO.so
@CREATE_VBFNLO@ Herwig::VBFNLOAmplitude VBFNLO
mkdir Builtin
cd Builtin
create Herwig::SimpleColourBasis SimpleColourBasis
create Herwig::SimpleColourBasis2 SimpleColourBasis2
create Herwig::MatchboxAmplitudellbarqqbar Amplitudellbarqqbar
set Amplitudellbarqqbar:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudellbarqqbarg Amplitudellbarqqbarg
set Amplitudellbarqqbarg:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudellbarqqbargg Amplitudellbarqqbargg
set Amplitudellbarqqbargg:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudellbarqqbarqqbar Amplitudellbarqqbarqqbar
set Amplitudellbarqqbarqqbar:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudelnuqqbar Amplitudelnuqqbar
set Amplitudelnuqqbar:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudelnuqqbarg Amplitudelnuqqbarg
set Amplitudelnuqqbarg:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudelnuqqbargg Amplitudelnuqqbargg
set Amplitudelnuqqbargg:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudelnuqqbarqqbar Amplitudelnuqqbarqqbar
set Amplitudelnuqqbarqqbar:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudehgg Amplitudehgg
set Amplitudehgg:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudehggg Amplitudehggg
set Amplitudehggg:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudehqqbarg Amplitudehqqbarg
set Amplitudehqqbarg:ColourBasis SimpleColourBasis
create Herwig::MatchboxAmplitudeqqbarttbar Amplitudeqqbarttbar
set Amplitudeqqbarttbar:ColourBasis SimpleColourBasis2
create Herwig::MatchboxAmplitudeqqbarttbarg Amplitudeqqbarttbarg
set Amplitudeqqbarttbarg:ColourBasis SimpleColourBasis2
create Herwig::MatchboxAmplitudeggttbar Amplitudeggttbar
set Amplitudeggttbar:ColourBasis SimpleColourBasis2
create Herwig::MatchboxAmplitudeggttbarg Amplitudeggttbarg
set Amplitudeggttbarg:ColourBasis SimpleColourBasis2
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudellbarqqbar
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudellbarqqbarg
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudellbarqqbargg
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudellbarqqbarqqbar
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudelnuqqbar
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudelnuqqbarg
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudelnuqqbargg
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudelnuqqbarqqbar
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudehgg
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudehggg
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudehqqbarg
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudeqqbarttbar
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudeqqbarttbarg
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudeggttbar
insert /Herwig/MatrixElements/Matchbox/Factory:Amplitudes 0 Amplitudeggttbarg
################################################################################
# Setup phasespace generators
################################################################################
cd /Herwig/MatrixElements/Matchbox
mkdir Phasespace
cd Phasespace
create Herwig::PhasespaceCouplings PhasespaceCouplings
create Herwig::MatchboxRambo Rambo
set Rambo:CouplingData PhasespaceCouplings
create Herwig::FlatInvertiblePhasespace InvertiblePhasespace
set InvertiblePhasespace:CouplingData PhasespaceCouplings
create Herwig::FlatInvertibleLabframePhasespace InvertibleLabframePhasespace
set InvertibleLabframePhasespace:CouplingData PhasespaceCouplings
set InvertibleLabframePhasespace:LogSHat False
create Herwig::TreePhasespaceChannels TreePhasespaceChannels
create Herwig::TreePhasespace TreePhasespace
set TreePhasespace:ChannelMap TreePhasespaceChannels
set TreePhasespace:M0 0.0001*GeV
set TreePhasespace:MC 0.00005*GeV
set TreePhasespace:CouplingData PhasespaceCouplings
do TreePhasespace:SetPhysicalCoupling 21 -1 1 0.059
do TreePhasespace:SetPhysicalCoupling 21 -2 2 0.059
do TreePhasespace:SetPhysicalCoupling 21 -3 3 0.059
do TreePhasespace:SetPhysicalCoupling 21 -4 4 0.059
do TreePhasespace:SetPhysicalCoupling 21 -5 5 0.059
do TreePhasespace:SetPhysicalCoupling 21 -6 6 0.059
do TreePhasespace:SetPhysicalCoupling 21 1 -1 0.059
do TreePhasespace:SetPhysicalCoupling 21 2 -2 0.059
do TreePhasespace:SetPhysicalCoupling 21 3 -3 0.059
do TreePhasespace:SetPhysicalCoupling 21 4 -4 0.059
do TreePhasespace:SetPhysicalCoupling 21 5 -5 0.059
do TreePhasespace:SetPhysicalCoupling 21 6 -6 0.059
do TreePhasespace:SetPhysicalCoupling 1 21 1 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 2 21 2 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 3 21 3 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 4 21 4 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 5 21 5 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 6 21 6 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -1 21 -1 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -2 21 -2 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -3 21 -3 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -4 21 -4 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -5 21 -5 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -6 21 -6 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 1 1 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 2 2 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 3 3 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 4 4 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 5 5 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling 6 6 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -1 -1 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -2 -2 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -3 -3 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -4 -4 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -5 -5 21 0.15733333333333333333
do TreePhasespace:SetPhysicalCoupling -6 -6 21 0.15733333333333333333
do TreePhasespace:SetCoupling 25 -1 1 0
do TreePhasespace:SetCoupling 25 -2 2 0
do TreePhasespace:SetCoupling 25 -3 3 0.00000001184279069851
do TreePhasespace:SetCoupling 25 -4 4 0.00000205034465001885
do TreePhasespace:SetCoupling 25 -5 5 0.00002314757096085280
do TreePhasespace:SetCoupling 25 -6 6 0.03982017320025470767
do TreePhasespace:SetCoupling 25 -11 11 0.00000000000034264835
do TreePhasespace:SetCoupling 25 -12 12 0
do TreePhasespace:SetCoupling 25 -13 13 0.00000001464912263400
do TreePhasespace:SetCoupling 25 -14 14 0
do TreePhasespace:SetCoupling 25 -15 15 0.00000414359033108195
do TreePhasespace:SetCoupling 25 -16 16 0
do TreePhasespace:SetCoupling 22 -1 1 0.00083932358497608365
do TreePhasespace:SetCoupling 22 -2 2 0.00335729433990433461
do TreePhasespace:SetCoupling 22 -3 3 0.00083932358497608365
do TreePhasespace:SetCoupling 22 -4 4 0.00335729433990433461
do TreePhasespace:SetCoupling 22 -5 5 0.00083932358497608365
do TreePhasespace:SetCoupling 22 -6 6 0.00335729433990433461
do TreePhasespace:SetCoupling 22 -11 11 0.00755391226478475287
do TreePhasespace:SetCoupling 22 -13 13 0.00755391226478475287
do TreePhasespace:SetCoupling 22 -15 15 0.00755391226478475287
do TreePhasespace:SetCoupling 24 -2 1 0.01652748072644379386
do TreePhasespace:SetCoupling 24 -4 1 0.00382028458188709739
do TreePhasespace:SetCoupling 24 -6 1 0.00014707756360995175
do TreePhasespace:SetCoupling 24 -2 3 0.00382265953677814621
do TreePhasespace:SetCoupling 24 -4 3 0.01651340063673257587
do TreePhasespace:SetCoupling 24 -6 3 0.00068534412570265868
do TreePhasespace:SetCoupling 24 -2 5 0.00005954351191129535
do TreePhasespace:SetCoupling 24 -4 5 0.00069891529650865192
do TreePhasespace:SetCoupling 24 -6 5 0.01694947628265615369
do TreePhasespace:SetCoupling 24 -12 11 0.01696396350749155147
do TreePhasespace:SetCoupling 24 -14 13 0.01696396350749155147
do TreePhasespace:SetCoupling 24 -16 15 0.01696396350749155147
do TreePhasespace:SetCoupling -24 2 -1 0.01652748072644379386
do TreePhasespace:SetCoupling -24 4 -1 0.00382028458188709739
do TreePhasespace:SetCoupling -24 6 -1 0.00014707756360995175
do TreePhasespace:SetCoupling -24 2 -3 0.00382265953677814621
do TreePhasespace:SetCoupling -24 4 -3 0.01651340063673257587
do TreePhasespace:SetCoupling -24 6 -3 0.00068534412570265868
do TreePhasespace:SetCoupling -24 2 -5 0.00005954351191129535
do TreePhasespace:SetCoupling -24 4 -5 0.00069891529650865192
do TreePhasespace:SetCoupling -24 6 -5 0.01694947628265615369
do TreePhasespace:SetCoupling -24 12 -11 0.01696396350749155147
do TreePhasespace:SetCoupling -24 14 -13 0.01696396350749155147
do TreePhasespace:SetCoupling -24 16 -15 0.01696396350749155147
do TreePhasespace:SetCoupling 23 -1 1 0.00407649129960709158
do TreePhasespace:SetCoupling 23 -2 2 0.00317809816318353030
do TreePhasespace:SetCoupling 23 -3 3 0.00407649129960709158
do TreePhasespace:SetCoupling 23 -4 4 0.00317809816318353030
do TreePhasespace:SetCoupling 23 -5 5 0.00407649129960709158
do TreePhasespace:SetCoupling 23 -6 6 0.00317809816318353030
do TreePhasespace:SetCoupling 23 -11 11 0.00276049468148072129
do TreePhasespace:SetCoupling 23 -12 12 0.00545567409075140513
do TreePhasespace:SetCoupling 23 -13 13 0.00276049468148072129
do TreePhasespace:SetCoupling 23 -14 14 0.00545567409075140513
do TreePhasespace:SetCoupling 23 -15 15 0.00276049468148072129
do TreePhasespace:SetCoupling 23 -16 16 0.00545567409075140513
do TreePhasespace:SetCoupling 21 21 21 0.354
do TreePhasespace:SetCoupling 25 21 21 0.00000000016160437564
do TreePhasespace:SetCoupling 25 25 25 0.18719783125611995353
do TreePhasespace:SetCoupling 25 22 22 0.00000000006295673620
do TreePhasespace:SetCoupling 25 24 -24 219.30463760755686425818
do TreePhasespace:SetCoupling 25 23 23 362.91922658249853887524
do TreePhasespace:SetCoupling 22 24 -24 0.00755391226478475287
do TreePhasespace:SetCoupling 23 24 -24 0.02637401475019835008
@CREATE_VBFNLO@ Herwig::VBFNLOPhasespace VBFNLOPhasespace
@SET_VBFNLO@ VBFNLOPhasespace:CouplingData PhasespaceCouplings
set /Herwig/MatrixElements/Matchbox/Factory:Phasespace TreePhasespace
################################################################################
# Setup utilities for matching
################################################################################
cd /Herwig/MatrixElements/Matchbox
create Herwig::HardScaleProfile HardScaleProfile
create Herwig::MEMatching MEMatching
set MEMatching:RestrictPhasespace On
set MEMatching:HardScaleProfile /Herwig/MatrixElements/Matchbox/HardScaleProfile
set MEMatching:BornScaleInSubtraction BornScale
set MEMatching:RealEmissionScaleInSubtraction RealScale
set MEMatching:EmissionScaleInSubtraction RealScale
set MEMatching:BornScaleInSplitting ShowerScale
set MEMatching:RealEmissionScaleInSplitting ShowerScale
set MEMatching:EmissionScaleInSplitting ShowerScale
set MEMatching:TruncatedShower Yes
set MEMatching:MaxPtIsMuF Yes
set MEMatching:FFPtCut 1.0*GeV
set MEMatching:FIPtCut 1.0*GeV
set MEMatching:IIPtCut 1.0*GeV
set MEMatching:SafeCut 0.*GeV
create Herwig::ShowerApproximationGenerator MECorrectionHandler
set MECorrectionHandler:ShowerApproximation MEMatching
set MECorrectionHandler:Phasespace /Herwig/MatrixElements/Matchbox/Phasespace/InvertiblePhasespace
set MECorrectionHandler:PresamplingPoints 50000
set MECorrectionHandler:FreezeGrid 100000
create Herwig::DipoleMatching DipoleMatching HwDipoleMatching.so
# set in DipoleShowerDefaults.in as not available at this point
# set DipoleMatching:ShowerHandler /Herwig/DipoleShower/DipoleShowerHandler
set DipoleMatching:BornScaleInSubtraction BornScale
set DipoleMatching:RealEmissionScaleInSubtraction BornScale
set DipoleMatching:EmissionScaleInSubtraction BornScale
set DipoleMatching:FFPtCut 1.0*GeV
set DipoleMatching:FIPtCut 1.0*GeV
set DipoleMatching:IIPtCut 1.0*GeV
set DipoleMatching:SafeCut 4.*GeV
create Herwig::QTildeMatching QTildeMatching HwQTildeMatching.so
set QTildeMatching:ShowerHandler /Herwig/Shower/ShowerHandler
set QTildeMatching:BornScaleInSubtraction BornScale
set QTildeMatching:RealEmissionScaleInSubtraction BornScale
set QTildeMatching:EmissionScaleInSubtraction BornScale
set QTildeMatching:QTildeFinder /Herwig/Shower/PartnerFinder
set QTildeMatching:SafeCut 4.*GeV
# just a dummy, since SudakovCommonn can't be used
# it's only used to get the value of the kinCutoffScale
set QTildeMatching:QTildeSudakov /Herwig/Shower/QtoQGSudakov
################################################################################
# Setup utilities for process generation
################################################################################
cd /Herwig/MatrixElements/Matchbox
mkdir Utility
cd Utility
create Herwig::Tree2toNGenerator DiagramGenerator
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFGVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/GGGVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFPVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFZVertex
cp /Herwig/Vertices/FFWVertex /Herwig/Vertices/FFWMatchboxVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFWMatchboxVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/WWHVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/WWWVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/HGGVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/HHHVertex
cp /Herwig/Vertices/FFHVertex /Herwig/Vertices/TTHVertex
set /Herwig/Vertices/TTHVertex:Fermion 6
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/TTHVertex
cp /Herwig/Vertices/FFHVertex /Herwig/Vertices/BBHVertex
set /Herwig/Vertices/BBHVertex:Fermion 5
+cp /Herwig/Vertices/FFHVertex /Herwig/Vertices/TauTauHVertex
+set /Herwig/Vertices/TauTauHVertex:Fermion 15
+
+insert DiagramGenerator:Vertices 0 /Herwig/Vertices/TauTauHVertex
+
+cp /Herwig/Vertices/FFHVertex /Herwig/Vertices/MuMuHVertex
+set /Herwig/Vertices/MuMuHVertex:Fermion 13
+
create Herwig::ProcessData ProcessData
set /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator DiagramGenerator
set /Herwig/MatrixElements/Matchbox/Factory:ProcessData ProcessData
################################################################################
# Setup jet cuts
################################################################################
cd /Herwig/Cuts
create Herwig::MatchboxFactoryMatcher MatchboxJetMatcher
set MatchboxJetMatcher:Group j
create ThePEG::FastJetFinder JetFinder
set JetFinder:UnresolvedMatcher MatchboxJetMatcher
set JetFinder:Variant AntiKt
set JetFinder:RecombinationScheme E
set JetFinder:Mode Inclusive
set JetFinder:ConeRadius 0.7
create ThePEG::JetRegion FirstJet
set FirstJet:PtMin 20.*GeV
do FirstJet:YRange -5.0 5.0
set FirstJet:Fuzzy Yes
set FirstJet:EnergyCutWidth 4.0*GeV
set FirstJet:RapidityCutWidth 0.4
insert FirstJet:Accepts[0] 1
create ThePEG::JetRegion SecondJet
set SecondJet:PtMin 20.*GeV
do SecondJet:YRange -5.0 5.0
set SecondJet:Fuzzy Yes
set SecondJet:EnergyCutWidth 4.0*GeV
set SecondJet:RapidityCutWidth 0.4
insert SecondJet:Accepts[0] 2
create ThePEG::JetRegion ThirdJet
set ThirdJet:PtMin 20.*GeV
do ThirdJet:YRange -5.0 5.0
set ThirdJet:Fuzzy Yes
set ThirdJet:EnergyCutWidth 4.0*GeV
set ThirdJet:RapidityCutWidth 0.4
insert ThirdJet:Accepts[0] 3
create ThePEG::JetRegion FourthJet
set FourthJet:PtMin 20.*GeV
do FourthJet:YRange -5.0 5.0
set FourthJet:Fuzzy Yes
set FourthJet:EnergyCutWidth 4.0*GeV
set FourthJet:RapidityCutWidth 0.4
insert FourthJet:Accepts[0] 4
create ThePEG::FuzzyTheta FuzzyTheta
set FuzzyTheta:EnergyWidth 4.0*GeV
set FuzzyTheta:RapidityWidth 0.4
set FuzzyTheta:AngularWidth 0.4
create ThePEG::NJetsCut NJetsCut
set NJetsCut:UnresolvedMatcher MatchboxJetMatcher
set NJetsCut:NJetsMin 2
create ThePEG::JetCuts JetCuts
set JetCuts:UnresolvedMatcher MatchboxJetMatcher
set JetCuts:Ordering OrderPt
create Herwig::IdentifiedParticleCut IdentifiedParticleCut
cp IdentifiedParticleCut LeptonCut
set LeptonCut:Matcher /Herwig/Matchers/Lepton
cp IdentifiedParticleCut ChargedLeptonCut
set ChargedLeptonCut:Matcher /Herwig/Matchers/ChargedLepton
cp IdentifiedParticleCut BottomQuarkCut
set BottomQuarkCut:Matcher /Herwig/Matchers/Bottom
cp IdentifiedParticleCut TopQuarkCut
set TopQuarkCut:Matcher /Herwig/Matchers/Top
cp IdentifiedParticleCut WBosonCut
set WBosonCut:Matcher /Herwig/Matchers/WBoson
cp IdentifiedParticleCut ZBosonCut
set ZBosonCut:Matcher /Herwig/Matchers/ZBoson
cp IdentifiedParticleCut HiggsBosonCut
set HiggsBosonCut:Matcher /Herwig/Matchers/HiggsBoson
cp IdentifiedParticleCut PhotonCut
set PhotonCut:Matcher /Herwig/Matchers/Photon
create Herwig::FrixionePhotonSeparationCut PhotonIsolationCut
set PhotonIsolationCut:UnresolvedMatcher MatchboxJetMatcher
create Herwig::MatchboxDeltaRCut MatchboxDeltaRCut
cp MatchboxDeltaRCut LeptonDeltaRCut
set LeptonDeltaRCut:FirstMatcher /Herwig/Matchers/Lepton
set LeptonDeltaRCut:SecondMatcher /Herwig/Matchers/Lepton
cp MatchboxDeltaRCut ChargedLeptonDeltaRCut
set ChargedLeptonDeltaRCut:FirstMatcher /Herwig/Matchers/ChargedLepton
set ChargedLeptonDeltaRCut:SecondMatcher /Herwig/Matchers/ChargedLepton
create Herwig::InvariantMassCut InvariantMassCut
cp InvariantMassCut LeptonPairMassCut
set LeptonPairMassCut:FirstMatcher /Herwig/Matchers/Lepton
set LeptonPairMassCut:SecondMatcher /Herwig/Matchers/Lepton
cp InvariantMassCut ChargedLeptonPairMassCut
set ChargedLeptonPairMassCut:FirstMatcher /Herwig/Matchers/ChargedLepton
set ChargedLeptonPairMassCut:SecondMatcher /Herwig/Matchers/ChargedLepton
create Herwig::MissingPtCut MissingPtCut
set MissingPtCut:Matcher /Herwig/Matchers/Neutrino
################################################################################
# Setup scale choices
################################################################################
cd /Herwig/MatrixElements/Matchbox
mkdir Scales
cd Scales
create Herwig::MatchboxScaleChoice SHatScale
cp SHatScale FixedScale
set FixedScale:FixedScale 100.*GeV
create Herwig::MatchboxPtScale MaxJetPtScale
set MaxJetPtScale:JetFinder /Herwig/Cuts/JetFinder
create Herwig::MatchboxLeptonMassScale LeptonPairMassScale
create Herwig::MatchboxLeptonPtScale LeptonPairPtScale
create Herwig::MatchboxHtScale HTScale
create Herwig::MatchboxTopMassScale TopPairMassScale
create Herwig::MatchboxTopMTScale TopPairMTScale
set HTScale:JetFinder /Herwig/Cuts/JetFinder
set HTScale:IncludeMT No
set HTScale:JetPtCut 15.*GeV
cp HTScale HTPrimeScale
set HTPrimeScale:IncludeMT Yes
set HTPrimeScale:JetPtCut 15.*GeV
cp LeptonPairMassScale LeptonQ2Scale
set /Herwig/MatrixElements/Matchbox/Factory:ScaleChoice LeptonPairMassScale
################################################################################
# Factories for different colliders
# only provided for backwards compatibility; refer to Matchbox/*.in input file
# snippets for generic handling
################################################################################
cd /Herwig/MatrixElements/Matchbox
cp Factory EEFactory
set EEFactory:PartonExtractor /Herwig/Partons/EEExtractor
set EEFactory:Cuts /Herwig/Cuts/EECuts
set EEFactory:FirstPerturbativePDF No
set EEFactory:SecondPerturbativePDF No
cp Factory DISFactory
set DISFactory:PartonExtractor /Herwig/Partons/DISExtractor
set DISFactory:Cuts /Herwig/Cuts/DISCuts
set DISFactory:FirstPerturbativePDF No
set DISFactory:SecondPerturbativePDF Yes
cp Factory PPFactory
set PPFactory:PartonExtractor /Herwig/Partons/QCDExtractor
set PPFactory:Cuts /Herwig/Cuts/QCDCuts
set PPFactory:FirstPerturbativePDF Yes
set PPFactory:SecondPerturbativePDF Yes
cd /

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 6:28 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3799743
Default Alt Text
(755 KB)

Event Timeline